Docker 入门笔记

Docker 入门笔记

Docker是什么?

  • Docker是一个开源的应用容器引擎,可以轻松的让开发者打包任何应用以及依赖包到一个轻量级的、可移植的、自给自足的容器中。然后发布到任何流行的Linux机器上,也可以实现虚拟化。开发者把编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。容器是完全使用沙箱机制,相互之间不会有任何接口。
  • 一个完整的Docker有以下几个部分组成:
    1. DockerClient客户端;
    2. Docker Daemon守护进程;
    3. Docker Image镜像;
    4. DockerContainer容器。

Docker通常用于如下场景:

  1. web应用的自动化打包和发布;
  2. 自动化测试和持续集成、发布;
  3. 在服务型环境中部署和调整数据库或其他的后台应用;
  4. 从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。
  • Docker 并不需要创建完整的虚拟操作系统,但还是会创建独立的环境 也就是 容器 Container [kənˈteinə]
  • 容器里面也是有操作系统的 这样可以跑着各自的应用程序互不干扰 容器之间共用的是主机的内核,但是容器不会访问内核,而是通过Docker引擎来访问,容器里面需要什么应用再根据实际增加。
  • Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。
容器
  • 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
仓库
  • 镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务, 就是这样的服务。
  • 一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。
  • 通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
  • 以 为例,ubuntu 是仓库的名字,其内包含有不同的版本标签,如,16.04, 18.04。我们可以通过 ubuntu:16.04,或者 ubuntu:18.04 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 ubuntu,那将视为 ubuntu:latest。
  • 仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。但这并非绝对,取决于所使用的具体 Docker Registry 的软件或服务。

前提

  • 各种版本的应用就定格形成镜像,如果其中有一个应用或者多个应用的版本不一样,就是另一个镜像了。镜像是一个相对静态的东西,要让镜像 “动起来” 也就是说我们可以根据不同的镜像 运行在不同容器里面的,做到相互隔离
  • 可以将不同版本的应用 写到一个 文件中保存起来 这个文件就 是 dockerfile
  • 每个镜像image的形成需要特定的步骤,需要指定 用什么操作系统,应用版本和各种指令
  • 如果在一个特定的操作系统,使用指定版本的应用,以及各种依赖,那我们就可以把这些写入 Dockerfile

创建一个属于自己的 docker 镜像

  • 要形成一个镜像,我们需要使用 docker build 命令来构建,运行的时候 Docker 引擎就会构建镜像。这个镜像实际上是还没有运行的。要运行需要 docker run命令,这个命令让Docker 引擎就会为我们分配一个新的容器,一个镜像分别可以在多个容器里运行。镜像除了可以在自己的主机里运行,还可以分享给别人,可以把制作好的镜像推送到 DockerHub (类似于 github) 使用的就是 docker push命令 别人就可以去Docker hub 找合适自己的镜像
    然后用docker pull 把镜像拉去到自己的本地,在各自的本地在使用 docker run 就可以用容器运行镜像了

实战

  • 首先需要在官网下载安装 Docker
wget  https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe?utm_source=docker&utm_medium=webreferral&utm_campaign=dd-smartbutton&utm_location=module
  • 什么 你问我 wget 命令 not found command 怎么办? 那就去下载一个 Cygwin64 下载地址 如下
    Cygwin64 下载地址
  • 或者使用下载工具也是可以的 地址不变
  • 现在下来之后 检查 有没有启动 hyper-v 功能
  • 可以用命令启动 也可以 在 windows 11 的设置 的 应用 > 可选功能 中 开启
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
  • 将 WSL 2 设置为默认版本
wsl --set-default-version 2
  • 然后下载安装 适用于 x64 计算机的 WSL2 Linux 内核更新包
wget https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
Administrator@DESKTOP-V8D67KJ ~/Desktop
$ wget https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
--2022-10-30 10:16:32--  https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
Resolving wslstorestorage.blob.core.windows.net (wslstorestorage.blob.core.windows.net)... 13.93.168.80
Connecting to wslstorestorage.blob.core.windows.net (wslstorestorage.blob.core.windows.net)|13.93.168.80|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 17104896 (16M) [application/octet-stream]
Saving to: 'wsl_update_x64.msi'

wsl_update_x64.msi         100%[====================================================================================================>]  16.31M  2.91MB/s    in 6.5s    

2022-10-30 10:16:39 (2.53 MB/s) - 'wsl_update_x64.msi' saved [17104896/17104896]
  • 下载安装后 执行 Docker Desktop Installer.exe 即 Docker Desktop 的安装包
  • 然后无脑下一步就可以了
使用 Node js 搭建一个简单的服务器
  • 创建一个文件夹
Administrator@DESKTOP-V8D67KJ ~/Desktop
$ mkdir Nodejs_Docker

Administrator@DESKTOP-V8D67KJ ~/Desktop
$ cd Nodejs_Docker/
  • 使用命令初始化一个项目
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ npm init -y
Wrote to C:\Users\Administrator\Desktop\Nodejs_Docker\package.json:

{
  "name": "nodejs_docker",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}


# 执行之后 会 自动生成一个 package.json
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ ls
package.json
  • 这里使用 express 框架 来构建服务器 所以使用命令来安装框架,框架安装完成之后 自动在package.json文件中添加
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ npm install express

up to date, audited 58 packages in 3s

7 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ cat package.json 
{
  "name": "nodejs_docker",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    # 安装完成后自动在 配置文件中添加依赖
    "express": "^4.18.2"
  }
}

Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ ls
node_modules  package.json  package-lock.json
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ ls -al
总用量 49
drwxr-xr-x+ 1 Administrator  Administrator     0 1030 17:45 .
drwxrwx---+ 1 Administrators Administrator     0 1030 17:34 ..
# 而且会生成一个 node_moules 这个文件夹 会保存我们的安装的模块
drwxr-xr-x+ 1 Administrator  Administrator     0 1030 17:45 node_modules 
-rwxr-xr-x+ 1 Administrator  Administrator   277 1030 17:45 package.json
-rwxr-xr-x+ 1 Administrator  Administrator 39691 1030 17:47 package-lock.json
  • 现在我们就可以在这个 Nodejs_Docker 文件夹 下 创建一个 app.js 文件 然后使用任意的编辑器 编辑这个文件
const express = require("express");
const app = express();
const PORT = 3000;
const banner = [
 "  __                                                              " ,
 "    /| |         |       |          |/  |           /             " ,      
 "  ( | | ___  ___| ___     ___      |   | ___  ___ (     ___  ___  " ,
 "  | | )|   )|   )|___)  )|___      |   )|   )|    |___)|___)|   ) " ,
 "  | |/ |__/ |__/ |__   /  __/      |__/ |__/ |__  | \  |__  |   | " ,
 "                    __/        ---                                " 
]
app.get("/",(req,res)=>{
    res.send("<h1>Hello, Nodejs World</h1>");
});
app.listen(PORT, ()=>{
    // 我这里就用了一个比较骚气的 控制台打印
    console.log(banner.join('\n'))
    console.log("服务已经启动 访问地址: http://localhost:"+PORT)
})
  • 编辑完成后就可以使用 node 命令来运行 服务了
node app.js
  • 运行结果
PS C:\Users\Administrator\Desktop\Nodejs_Docker> node app.js
  __
    /| |         |       |          |/  |           /
  ( | | ___  ___| ___     ___      |   | ___  ___ (     ___  ___  
  | | )|   )|   )|___)  )|___      |   )|   )|    |___)|___)|   ) 
  | |/ |__/ |__/ |__   /  __/      |__/ |__/ |__  |   |__  |   | 
                    __/        ---
服务已经启动 访问地址: http://localhost:3000

服务启动后的运行结果

  • 在app.js 的所在位置 创建一个 Dockerfilede 文件
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
# 注意没有后缀 而且首字母 大写
$ touch Dockerfile

Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ ls -al Dockerfile
-rw-r--r--+ 1 Administrator Administrator 0 1030 20:23 Dockerfile
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ ls
app.js  Dockerfile  node_modules  package.json  package-lock.json
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ ls -al 
总用量 57
drwxr-xr-x+ 1 Administrator  Administrator     0 1030 20:26 .
drwxrwx---+ 1 Administrators Administrator     0 1030 20:48 ..
-rwxr-xr-x+ 1 Administrators Administrator   825 1030 19:15 app.js
-rw-r--r--+ 1 Administrator  Administrator     0 1030 20:23 Dockerfile
drwxr-xr-x+ 1 Administrator  Administrator     0 1030 17:45 node_modules
-rwxr-xr-x+ 1 Administrator  Administrator   277 1030 17:45 package.json
-rwxr-xr-x+ 1 Administrator  Administrator 39691 1030 17:47 package-lock.json

Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
  • 而刚刚的 nodejs 是在本地跑起来的 我们的本地是由操作系统的,我们也可以为镜像定制操作系统,一般来说我们不会自己再去手写一个操作系统,因此我们可以去找操作系统的镜像
  • 也就是去 Docker Hub 里找 对应的 镜像
  • 进入 docer hub 中搜索 node
    node 的搜索结果
  • 这个镜像就是一个基础镜像 而且这个基础镜像 已经指定的了 node 和操作系统的版本
  • 可以在这个镜像的基础上再去添加别的东西 来构建自己的镜像
  • 编辑 Dockerfile
FROM node:18-alpine3.15 # 这里 用 from 来引用基础镜像 指定 node 的版本 为 18 操作系统是 alpine3.15 alpine3.15 是 linux 的发行版 
WORKDIR /Nodejs_Docker  # 指定容器的工作目录
  • 接下来 我们把 这个目录里的 package.json 复制到镜像里 因为 package.json 是 Node 项目的核心里面也会指明依赖的版本 所以我们要把这个文件复制到镜像里
FROM node:18-alpine3.15 # 这里 用 from 来引用基础镜像 指定 node 的版本 为 18 操作系统是 alpine3.15 alpine3.15 是 linux 的发行版 
WORKDIR /Nodejs_Docker  # 指定容器的工作目录
COPY package.json .
RUN npm install # 执行 npm install 在镜像中安装依赖
COPY . . # 再次使用 COPY 命令将目录下的文件复制到镜像的工作目录里
# 查看 Dockerfile 文件 
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ cat Dockerfile 
FROM node:18-alpine3.15
WORKDIR /Nodejs_Docker
COPY package.json
RUN npm install
COPY . .
  • 这里会有两个问题 首先 并不需要把 node_modules这个目录以及目录下的所有文件 复制到镜像的工作目录里 因为 再启动镜像的时候会执行 npm install 的时候 就会 自动 下载 安装 需要忽略掉这个文件夹 道理和 gitignore 是差不多的 因此我们在这里创建一个 .dockerignore 的文件
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ touch .dockerignore

Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ ls -al 
总用量 62
drwxr-xr-x+ 1 Administrator  Administrator     0 1030 21:09 .
drwxrwx---+ 1 Administrators Administrator     0 1030 20:48 ..
-rw-r--r--+ 1 Administrator  Administrator     0 1030 21:09 .dockerignore       
-rwxr-xr-x+ 1 Administrators Administrator   825 1030 19:15 app.js
-rw-r--r--+ 1 Administrator  Administrator    96 1030 21:08 Dockerfile
drwxr-xr-x+ 1 Administrator  Administrator     0 1030 17:45 node_modules        
-rwxr-xr-x+ 1 Administrator  Administrator   277 1030 17:45 package.json        
-rwxr-xr-x+ 1 Administrator  Administrator 39691 1030 17:47 package-lock.json   

Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
  • 除了 node_modules 我们也没有必要把 Dockerfile 拷贝进去因为 Dockerfile 是构建时用的 当然 .dockerignore 也需要忽略掉 类似的还有 .git .gitignore
# 查看 .dockerignore 文件 
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ cat .dockerignore 
node_modules
Dockerfile
.git
.gitignore
.dockerignore
  • 即使我们忽略掉很多文件但是两次 copy的操作仍然会把我们的 package.json 文件复制进去 其实这样写是 考虑到性能的,在构建镜像的时候 Docker 会根据 Dockerfile里的信息 一行一行地执行 每一行执行完了以后就会缓存起来
  • package.json 主要就是记录配置和依赖等信息的,我们一般很少会进行改动 改动最多的是 js文件。如果我们每次修改完js文件以后,再次构建镜像 因为前面几个步骤都不变,就会变得超快 毕竟可以用缓存
  • 但是如果我们只用一个 COPY 命令 而没有分开写两个 COPY 就会导致牵一发而动全身的现象,浪费更多时间
  • 两个问题清楚以后 为了方便后续的操作 需要在 Dockerfile 中 配置一下端口号
EXPOSE 3000
  • 我们的容器的端口和我们本机的端口号 是不一样的,各自处于不同的操作系统和不同的环境
  • 最后 可以 使用CMD 命令 来运行 app.js 了
CMD["node","app.js"]
  • 特别要注意的是 CMD 命令 接的内容是需要用数组的表示
  • 现在我们的镜像 终于构建完成了
  • 接着启动一下 docker
  • 在当前目录里 使用 docker build . 命令 启动 docker
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ docker build .
[+] Building 34.7s (4/9)
 => [internal] load build definition from Dockerfile                                                                                                                                    0.1s
 => => transferring dockerfile: 172B                                                                                                                                                    0.0s
 => [internal] load .dockerignore                                                                                                                                                       0.1s
 => => transferring context: 99B                                                                                                                                                        0.0s
 => [internal] load metadata for docker.io/library/node:18-alpine3.15                                                                                                                   7.6s
 => [internal] load build context                                                                                                                                                       0.1s
 => => transferring context: 40.93kB                                                                                                                                                    0.0s
 => [1/5] FROM docker.io/library/node:18-alpine3.15@sha256:cc01b1f106743660b64c19b5ed6668be7a6523f28229103af5e77c381f68babc                                                            26.9s
 => => resolve docker.io/library/node:18-alpine3.15@sha256:cc01b1f106743660b64c19b5ed6668be7a6523f28229103af5e77c381f68babc                                                             0.1s
 => => sha256:7b47aea5e936bb7d848fdc29ef3d5afb8835fa074eadcf082680b5f0cfb8f00b 1.16kB / 1.16kB                                                                                          0.0s
 => => sha256:6921355c22dec2580384452b4ad17720a248f49484fe1d6feb26cce82c25a46b 6.44kB / 6.44kB                                                                                          0.0s
 => => sha256:9621f1afde84053b2f9b6ff34fc7f7460712247c01cbab483c5fa7132cf782ca 0B / 2.82MB                                                                                             26.8s
 => => sha256:e4ab87b0f8a7003a5f7d104eb1b3bc43d3af2918d7a8f6300126a47646f97c3d 0B / 46.27MB                                                                                            26.8s
 => => sha256:0ab31ae924401714a803b5f485aae108d2a8cc2313d97862ff799200b5ae83c8 1.05MB / 2.35MB                                                                                         26.8s
 => => sha256:cc01b1f106743660b64c19b5ed6668be7a6523f28229103af5e77c381f68babc 1.43kB / 1.43kB     
  • 执行结果
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ docker build .
[+] Building 2.0s (10/10) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                                                    0.1s
 => => transferring dockerfile: 32B                                                                                                                                                     0.0s 
 => [internal] load .dockerignore                                                                                                                                                       0.1s 
 => => transferring context: 34B                                                                                                                                                        0.0s 
 => [internal] load metadata for docker.io/library/node:18-alpine3.15                                                                                                                   1.6s
 => [internal] load build context                                                                                                                                                       0.1s
 => => transferring context: 98B                                                                                                                                                        0.0s 
 => [1/5] FROM docker.io/library/node:18-alpine3.15@sha256:cc01b1f106743660b64c19b5ed6668be7a6523f28229103af5e77c381f68babc                                                             0.0s 
 => CACHED [2/5] WORKDIR /Nodejs_Docker                                                                                                                                                 0.0s 
 => CACHED [3/5] COPY package.json .                                                                                                                                                    0.0s 
 => CACHED [4/5] RUN npm install                                                                                                                                                        0.0s 
 => CACHED [5/5] COPY . .                                                                                                                                                               0.0s 
 => exporting to image                                                                                                                                                                  0.1s 
 => => exporting layers                                                                                                                                                                 0.0s 
 => => writing image sha256:d5ba72249903ad72b9ef9bc1b9af607c564c4310182107c3c28d70d98a9fdc90                                                                                            0.0s 


# 查看镜像 要执行 docker image ls
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
# 这里的 image 可以是复数 也可以 是下面那条命令
$ docker images 
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
<none>       <none>    d5ba72249903   8 hours ago   173MB

Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
<none>       <none>    d5ba72249903   9 hours ago   173MB
  • 此时的镜像是没有名字的 所以是 none
  • 可以看到 这个镜像要比虚拟机小不知道要缩多少倍
  • 使用 docker tag 来给镜像命名 只不过后面要加上镜像的ID 当有很少的镜像的时候可以偷懒只写 镜像 ID 的前几个字母
docker tag d5ba codervibe/Nodejs_Docker:v1.0
  • 这个时候 出错了
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ docker tag d5bacodervibe/NodejsDocker:v1.0:v1.0
Error parsing reference: "codervibe/NodejsDocker:v1.0" is not a valid repository/tag: invalid reference format: repository name must be lowercase
  • Error parsing reference: “codervibe/NodejsDocker:v1.0” is not a valid repository/tag: invalid reference format: repository name must be lowercase
  • 这句报错的主要意思是 无效的参考格式:存储库名称必须为小写
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ docker tag d5ba codervibe/nodejsdocker:v1.0
  • 命名完成后 就会是这个样子
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ docker image ls
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE
codervibe/nodejsdocker   v1.0      d5ba72249903   10 hours ago   173MB
  • 这里的镜像的的命名格式 是 用户名/镜像名:版本 如果不加版本就是 latest 建议加上
  • 如果只是储存在本地 是用什么样的名字倒是无所谓 但是我这里要推送到 Docker Hub 上 所以最好还是按照这个格式使用
  • 在 Docker Hub上注册好账号 注册好之后回到命令行
  • 使用 docker login 进行登录 账号和密码
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.er ID, head over to https://hub.docker.com to create one.
Username: codervibe
Password: # 这里的密码输入是没有提示的 直接输入即可
Login Succeeded

Logging in with your password grants your terminal complete access to your account. 
For better security, log in with a limited-privilege personal access token. Learn more at https://docs.docker.com/go/access-tokens/
  • 使用 docker push 命令将镜像 推送到 Docker Hub
Administrator@DESKTOP-V8D67KJ ~/Desktop/Nodejs_Docker
$ docker push codervibe/nodejsdocker
Using default tag: latest
The push refers to repository [docker.io/codervibe/nodejsdocker]
tag does not exist: codervibe/nodejsdocker:latest
C:\Users\Administrator\Desktop\Nodejs_Docker>docker push codervibe/nodejsdocker:v1.0
The push refers to repository [docker.io/codervibe/nodejsdocker]
The push refers to repository [docker.io/codervibe/nodejsdocker]
2775f1c9b046: Pushed
a33a33455a09: Pushed
30abd3b96b2d: Pushed
b826e180ca43: Pushed
7873ffdc5975: Pushed
6c3b0ca38fdf: Pushed
2510f5d20f3d: Pushing [==>                                                ]  8.301MB/153.7MB
34d5ebaa5410: Pushed
  • 上传完成后
C:\Users\Administrator\Desktop\Nodejs_Docker>docker push codervibe/nodejsdocker:v1.0
The push refers to repository [docker.io/codervibe/nodejsdocker]
2775f1c9b046: Layer already exists
a33a33455a09: Layer already exists
30abd3b96b2d: Layer already exists
b826e180ca43: Layer already exists
7873ffdc5975: Layer already exists
6c3b0ca38fdf: Layer already exists
2510f5d20f3d: Pushed
34d5ebaa5410: Layer already exists
v1.0: digest: sha256:1dadf1a34c48f2f48454aa831841d45a569182baf18b7a5370a9eef4d804461b size: 1991
  • 然后登录 docker hub 登录相应的账号 就可以看到 push 的镜像了
  • 那么我们能否在 构建镜像的时候就定义名字呢?
  • 答案是当然没问题 可以使用选项 -t 意思就是 tag 标签
  • 例子
C:\Users\Administrator\Desktop\Nodejs_Docker>docker build -t <name> . 
# 在 -t 选项后面 添加一个名字即可  最后使用 . 来表示相对地址
C:\Users\Administrator\Desktop\Nodejs_Docker>docker build -t eggimage:v1.0 .  # 这里的镜像名称是我随便命名的 只是为了练习 -t 这个选项
[+] Building 5.7s (11/11) FINISHED
 => [internal] load build definition from Dockerfile                            0.2s
 => => transferring dockerfile: 32B                                             0.1s 
 => [internal] load .dockerignore                                               0.1s
 => => transferring context: 34B                                                0.0s 
 => [internal] load metadata for docker.io/library/node:18-alpine3.15           5.2s
 => [auth] library/node:pull token for registry-1.docker.io                     0.0s
 => [1/5] FROM docker.io/library/node:18-alpine3.15@sha256:cd3a7004267e419477b  0.0s
 => [internal] load build context                                               0.0s
 => => transferring context: 98B                                                0.0s
 => CACHED [2/5] WORKDIR /Nodejs_Docker                                         0.0s
 => CACHED [3/5] COPY package.json .                                            0.0s
 => CACHED [4/5] RUN npm install                                                0.0s
 => CACHED [5/5] COPY . .                                                       0.0s
 => exporting to image                                                          0.1s
 => => exporting layers                                                         0.0s
 => => writing image sha256:d8644d361b47699737ba982baa6ebab28b52c67f37920e60fe  0.0s
 => => naming to docker.io/library/eggimage:v1.0                                0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
  • 因为 docker 使用缓存来构建 所以速度会非常快
  • 这时 使用 docker image ls 就可以查看了
C:\Users\Administrator\Desktop\Nodejs_Docker>docker image ls
REPOSITORY               TAG       IMAGE ID       CREATED       SIZE
codervibe/nodejsdocker   v1.0      d8644d361b47   2 hours ago   173MB
eggimage                 v1.0      d8644d361b47   2 hours ago   173MB

C:\Users\Administrator\Desktop\Nodejs_Docker>
  • 既然已经推送到 Docker Hub 我就不想存在本地了
  • 我们就可以使用 docker rmi 来删除镜像
  • 如果镜像还在使用中 就需要用 -f 来 force 强制执行
  • -f 之后 要加上 镜像的名字
  • 需要注意的 是 目前创建的两个镜像内容是一样的,因此 他们的 ID 也是一样的
  • 也就是说 -f 后面 加上 镜像的名字 或者 镜像的 ID 都是可以的
C:\Users\Administrator\Desktop\Nodejs_Docker>docker rmi -f eggimage:v1.0 
Untagged: eggimage:v1.0

C:\Users\Administrator\Desktop\Nodejs_Docker>docker image ls              
REPOSITORY               TAG       IMAGE ID       CREATED       SIZE
codervibe/nodejsdocker   v1.0      d8644d361b47   2 hours ago   173MB
C:\Users\Administrator\Desktop\Nodejs_Docker>docker image ls
REPOSITORY               TAG       IMAGE ID       CREATED       SIZE
codervibe/nodejsdocker   v1.0      d8644d361b47   2 hours ago   173MB

C:\Users\Administrator\Desktop\Nodejs_Docker>docker rmi d8644d361b47                 
Untagged: codervibe/nodejsdocker:v1.0
Untagged: codervibe/nodejsdocker@sha256:1dadf1a34c48f2f48454aa831841d45a569182baf18b7a5370a9eef4d804461b
Deleted: sha256:d8644d361b47699737ba982baa6ebab28b52c67f37920e60fe98331b3636a127  
  • 如果想将镜像存储到本地 可以直接使用 docker pull 镜像名字

C:\Users\Administrator\Desktop\Nodejs_Docker>docker pull  codervibe/nodejsdocker:v1.0  
v1.0: Pulling from codervibe/nodejsdocker
9621f1afde84: Already exists
b2ff27170c03: Already exists
857f24243633: Already exists
f5234ba59f34: Already exists
5995d794dc7a: Already exists
cf24c846c22c: Already exists
9584af0953fe: Already exists
4eb143716138: Already exists                                                                                                                                                          
Digest: sha256:1dadf1a34c48f2f48454aa831841d45a569182baf18b7a5370a9eef4d804461b
Status: Downloaded newer image for codervibe/nodejsdocker:v1.0
docker.io/codervibe/nodejsdocker:v1.0

C:\Users\Administrator\Desktop\Nodejs_Docker>docker image ls                           
REPOSITORY               TAG       IMAGE ID       CREATED       SIZE
codervibe/nodejsdocker   v1.0      d8644d361b47   2 hours ago   173MB

  • 镜像创建完成了 就需要尝试在容器中运行镜像
  • 使用 docker run 命令
  • 运行的时候需要指定 运行那个镜像的名字即可 ,但是 如果直接执行的话 就需要占用当前的命令窗口, 可以 使用 -d 选项 可以 使 容器 在后台运行
  • -d 是 detached mode 的 缩写
  • 命令格式
docker run -d <imagename>
  • 运行之后 会返回 容器的 ID
C:\Users\Administrator\Desktop\Nodejs_Docker>docker run -d codervibe/nodejsdocker:v1.0
dfc4ee868b97972d42b4426ad84680baf1a751ae2cb71fdaec96215d86b7a975
  • 但是我们要怎么确认我们的容器在运行呢?
  • 这就需要用到 docker ps 命令
  • ps 表示 process status 的意思
  • 这个命令的结果显示 容器ID 使用的镜像 以及端口号信息

C:\Users\Administrator\Desktop\Nodejs_Docker>docker run -d codervibe/nodejsdocker:v1.0
310912d64d40fb392601ff037996631a36617305161e01812eab7d68806d800a

C:\Users\Administrator\Desktop\Nodejs_Docker>docker ps
CONTAINER ID   IMAGE                         COMMAND                  CREATED         STATUS         PORTS      NAMES
310912d64d40   codervibe/nodejsdocker:v1.0   "docker-entrypoint.s…"   4 seconds ago   Up 2 seconds   3000/tcp   sweet_ganguly
  • 此时 尝试 用浏览器 访问我们的服务器 结果当然 是不行的
  • 这是因为 本地的端口号和容器的端口号是不一样的
  • 虽然我们已经在配置文件中 写了 端口号为 3000 端口了但是其实这句话只有一个文档的作用
  • 实际开启3000 端口是 app.js 里写的内容 写在 Dockerfile 里的 EXPOSE 只是让人知道这个镜像用的端口。
  • 这个 EXPOSE 可能是Docker 十大迷惑指令之一
  • 要是想要访问 容器中的应用 就需要进行端口映射 也就是用 -p 选项
C:\Users\Administrator\Desktop\Nodejs_Docker>docker run -d -p 3000:3000 codervibe/nodejsdocker:v1.0
5f09e5345f7c29ea6eade03124862ba43b348aa6a5c5b5e2b48612fbb4645914
  • 如果要用别的端口也是可以的 只要端口不和其他应用冲突就好
  • 此外 还可以 使用 --name 选项来给这个 docker 容器 指定一个名字
C:\Users\Administrator\Desktop\Nodejs_Docker>docker run -d -p 3000:3000 --name codervib_nodejsdocker  codervibe/nodejsdocker:v1.0
2263e077332dda2fc9ad656804d5de056cd9f8fa69c4b71081292df557e35f7b
  • 如果不指定名字 docker 会自动给这个容器一个名字
  • 再次 使用 docker ps 查看一下 运行的容器
C:\Users\Administrator\Desktop\Nodejs_Docker>docker ps
CONTAINER ID   IMAGE                         COMMAND                  CREATED         STATUS         PORTS                    NAMES
48c80a257409   codervibe/nodejsdocker:v1.0   "docker-entrypoint.s…"   5 minutes ago   Up 5 minutes   0.0.0.0:3000->3000/tcp   busy_shamir
  • 如果要关闭这个容器 可以使用 dockers stop 命令 docker stop 容器ID 即可
C:\Users\Administrator\Desktop\Nodejs_Docker>docker ps
CONTAINER ID   IMAGE                         COMMAND                  CREATED          STATUS          PORTS                              NAMES
8325df245b17   codervibe/nodejsdocker:v1.0   "docker-entrypoint.s…"   4 seconds ago    Up 3 seconds    3000/tcp, 0.0.0.0:3001->3001/tcp   epic_johnson
48c80a257409   codervibe/nodejsdocker:v1.0   "docker-entrypoint.s…"   15 minutes ago   Up 15 minutes   0.0.0.0:3000->3000/tcp             busy_shamir

C:\Users\Administrator\Desktop\Nodejs_Docker>docker stop 832
832
  • 如果要查看所有的容器包括暂停运行的 可以在ps 命令下加 -a 表示 all
  • 对于不需要的容器时可以删除的和删除的命令很像 使用 docker rm 就可以了 -f 选项 可以强制移除在运行的容器 最后指明容器 ID 或者名字即可
  • 现在如果我在本地服务器里的文件做一下修改 修改 app.js 并且保存文件
const express = require("express");
const app = express();
const PORT = 3000;
const banner = [
 "  __                                                              " ,
 "    /| |         |       |          |/  |           /             " ,      
 "  ( | | ___  ___| ___     ___      |   | ___  ___ (     ___  ___  " ,
 "  | | )|   )|   )|___)  )|___      |   )|   )|    |___)|___)|   ) " ,
 "  | |/ |__/ |__/ |__   /  __/      |__/ |__/ |__  | \  |__  |   | " ,
 "                    __/        ---                                " 
]
app.get("/",(req,res)=>{
    res.send("<h1>Hello,Nodejs World</h1><hr> <h5>OK let's go!</h5>");
});
app.listen(PORT, ()=>{
    // 我这里就用了一个比较骚气的 控制台打印
    console.log(banner.join('\n'))
    console.log("服务已经启动 访问地址: http://localhost:"+PORT)
})
  • 此时我们的网页文件是不会跟着变动的,修改文件后就要生成新的镜像
  • 其实我们进去容器里面看看 app.js 内容 就会发现 和没有修改之前的内容是一样的
  • 容器正在后台运行 要访问他 就需要用的 docker exec 命令了 execute 是 执行的意思
  • 而 docker exec也可以指定模式 因为我们要进入到容器并且进行交互 可以 用 -i 选项 i 表示 interactive 交互 以终端的方式进行交互 是用 -t 选项 -t 表示pseudo-TTY 伪终端 i 和 t 可以连在一起写
  • 然后指明我们要执行的容器 最后加上 /bin/sh 表示 新的 bash shell 这是 Alpine 进入 shell 的方式 其实与容器交互还可以指定路径
C:\Users\Administrator\Desktop\Nodejs_Docker>docker ps -a
CONTAINER ID   IMAGE                         COMMAND                  CREATED             STATUS             PORTS                    NAMES
48c80a257409   codervibe/nodejsdocker:v1.0   "docker-entrypoint.s…"   About an hour ago   Up About an hour   0.0.0.0:3000->3000/tcp   busy_shamir

C:\Users\Administrator\Desktop\Nodejs_Docker>docker exec -it busy_shamir /bin/sh
/Nodejs_Docker # 
  • 可以看到这是一个简单 linux 终端 而且我们直接来到了 Nodejs_Docker 文件夹
  • 因为前面设置了工作目录 这里面我们可以正常的执行Linux 命令
/Nodejs_Docker # ls
app.js             node_modules       package-lock.json  package.json
/Nodejs_Docker # pwd
/Nodejs_Docker
/Nodejs_Docker #
  • 而且 使用 ls 命令可以看到 文件夹下的 内容
  • 尝试使用 cat 命令 查看 app.js的 内容
/Nodejs_Docker # cat ./app.js
const express = require("express");
const app = express();
const PORT = 3000;
const banner = [
 "  __                                                              " ,
 "    /| |         |       |          |/  |           /             " ,
 "  ( | | ___  ___| ___     ___      |   | ___  ___ (     ___  ___  " ,
 "  | | )|   )|   )|___)  )|___      |   )|   )|    |___)|___)|   ) " ,
 "  | |/ |__/ |__/ |__   /  __/      |__/ |__/ |__  | \  |__  |   | " ,
 "                    __/        ---                                "
]
app.get("/",(req,res)=>{
    res.send("<h1>Hello, Nodejs World</h1>");
});
app.listen(PORT, ()=>{
    // 我这里就用了一个比较骚气的 控制台打印
    console.log(banner.join('\n'))
    console.log("服务已经启动 访问地址: http://localhost:"+PORT)
})
/Nodejs_Docker #
  • 可以看到 并没有新添加的那句话
  • 容器里的app.js 是根据镜像构建的,如果每次本地文件有修改就要重新构建镜像 然后新建容器运行 显然是很麻烦的
  • 需要进行同步 就要用到 -v 选项了
  • 使用 exit 命令 退出这个容器的shell 然后 把运行中的容器给他销毁掉
/Nodejs_Docker # exit

C:\Users\Administrator\Desktop\Nodejs_Docker>docker ps -a
CONTAINER ID   IMAGE                         COMMAND                  CREATED       STATUS       PORTS                    NAMES
48c80a257409   codervibe/nodejsdocker:v1.0   "docker-entrypoint.s…"   2 hours ago   Up 2 hours   0.0.0.0:3000->3000/tcp   busy_shamir

C:\Users\Administrator\Desktop\Nodejs_Docker>docker rm -f 48c80a25740
48c80a25740
  • 在重新开启一个 容器 加上 -v 选项 v 是 volume 的 缩写 用这个选项 就可以把本地指定文件夹 和容器指定文件夹 进行绑定 也就是说 要指定路径
  • 但如果是在命令行窗口是需要使用绝对路径的 也就是 “本地文件夹路径:容器文件夹路径” 的 格式
  • 从本地文件夹到容器里 工作目录 这样的绑定
C:\Users\Administrator\Desktop\Nodejs_Docker>docker run -d -v C:\Users\Administrator\Desktop\Nodejs_Docker\:/Nodejs_Docker -p 3000:3000 --name codervibe_nodejsdocker  codervibe/nodejsdocker:v1.0
8fd392cc5d7aad5d1f614c7abeef6bcb3355b3c26a6de49af6b3454cfaf21feb
  • 当然本地路径也可以用环境变量的形式来写,只不过不同操作系统用的写法有所不同
  • 此时再次访问 就会发现 内容 已经更改了
  • 那么 如果我现在再次 更改 文件内容 页面 是否会更改 呢
  • 答案当然是 不会 因为现在虽然已经绑定目录 但因为我们根据镜像启动容器的时候 也就是用 node 执行app.js 的时候 是根据执行时的服务器文件来启动服务的
  • 如果文件有修改 我们需要重新 用 node 执行 app.js
  • 这里可以用 nodemon 这个工具来自动重启
  • 文件有改动后 就自动重启
  • 先把这个正在运行的容器删除掉 然后在本地 安装 nodemon
C:\Users\Administrator\Desktop\Nodejs_Docker>docker rm -f codervibe_nodejsdocker     
codervibe_nodejsdocker

C:\Users\Administrator\Desktop\Nodejs_Docker> npm i nodemon --save-dev

added 32 packages, and audited 90 packages in 2m

10 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

C:\Users\Administrator\Desktop\Nodejs_Docker>
  • 安装以后 package.json 文件 就会有更新
{
  "name": "nodejs_docker",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.2"
  },
  "devDependencies": {
    // 这里多了一个 nodemon
    "nodemon": "^2.0.20"
  }
}
  • 安装以后我们还要启动nodemon
  • 因此在package.json 文件 中设置一下 执行命令
// 在此处 修改
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
// 修改为
"scripts": {
   "test": "nodemon app.js"
},
// 如果是 windows 系统则修改为
"scripts": {
   "test": "nodemon -L  app.js"
},
// 即可
  • 要用 nodemon 运行 因此需要修改一下 Dockerfile
FROM node:18-alpine3.15
WORKDIR /Nodejs_Docker 
COPY package.json .
RUN npm install 
COPY . .
EXPOSE 3000
CMD ["node","app.js"]
  • 也就是修改 CMD ["node","app.js"]这句话
  • 将其修改为 CMD ["npm","run","dev"]
FROM node:18-alpine3.15
WORKDIR /Nodejs_Docker 
COPY package.json .
RUN npm install 
COPY . .
EXPOSE 3000
CMD ["npm","run","dev"]
  • 保存文件以后 先把原来的镜像删除 以防止弄混
C:\Users\Administrator\Desktop\Nodejs_Docker>docker rmi -f d8644d361b47
Untagged: codervibe/nodejsdocker:v1.0
Untagged: codervibe/nodejsdocker@sha256:1dadf1a34c48f2f48454aa831841d45a569182baf18b7a5370a9eef4d804461b
Deleted: sha256:d8644d361b47699737ba982baa6ebab28b52c67f37920e60fe98331b3636a127
  • 重新 建立镜像
C:\Users\Administrator\Desktop\Nodejs_Docker>docker build -t codervibe/nodejsdocker:v1.0 .
[+] Building 106.9s (10/10) FINISHED
 => [internal] load build definition from Dockerfile                                  0.0s
 => => transferring dockerfile: 32B                                                   0.0s 
 => [internal] load .dockerignore                                                     0.0s 
 => => transferring context: 34B                                                      0.0s 
 => [internal] load metadata for docker.io/library/node:18-alpine3.15                 1.2s 
 => [1/5] FROM docker.io/library/node:18-alpine3.15@sha256:cd3a7004267e419477bbfc50e  0.0s
 => [internal] load build context                                                     0.0s 
 => => transferring context: 98B                                                      0.0s 
 => CACHED [2/5] WORKDIR /Nodejs_Docker                                               0.0s 
 => CACHED [3/5] COPY package.json .                                                  0.0s 
 => [4/5] RUN npm install                                                           104.9s 
 => [5/5] COPY . .                                                                    0.1s
 => exporting to image                                                                0.6s
 => => exporting layers                                                               0.6s 
 => => writing image sha256:c353504d4537f2bfceea4190da51e4cac851ec54df2ca8910242eec3  0.0s
 => => naming to docker.io/codervibe/nodejsdocker:v1.0                                0.0s 

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

C:\Users\Administrator\Desktop\Nodejs_Docker>docker images
REPOSITORY               TAG       IMAGE ID       CREATED          SIZE
codervibe/nodejsdocker   v1.0      c353504d4537   54 seconds ago   174MB
  • 然后 再用前面的 -v 启动 容器
C:\Users\Administrator\Desktop\Nodejs_Docker>docker run -d -v C:\Users\Administrator\Desktop\Nodejs_Docker\:/Nodejs_Docker -p 3000:3000 --name codervibe_nodejsdocker  codervibe/nodejsdocker:v1.0
b66695770696bc3f43463c849404fd10355111022c3105aec24d88543e227b28
  • 此时注意 虽然 Dockerfile 会忽略dockerignore里的文件夹和文件
  • 使用 -v 选项 就会把两边的文件夹进行绑定,也就是说 本地的 node_moudeles 会覆盖掉容器里的
  • 本地的node_modules 如果没了或者修改了 容器里的也会同步修改或者删除 因此需要特别声明 容器里的某些文件夹是不能同步的
  • 加一个 -v /Nodejs_Docker/node_modules 就好 特别声明 /Nodejs_Docker/node_modules 不进行 同步
  • 如果容器中 有新增的文件或者文件夹 本地也是会同步新增的 要让本地变得 只读 readonly
  • 就可以在第一个 -v 选项后面 加上 :ro
  • 点击回车后启动容器
C:\Users\Administrator\Desktop\Nodejs_Docker>docker images
REPOSITORY               TAG       IMAGE ID       CREATED         SIZE
codervibe/nodejsdocker   v1.0      3f48cf69206a   4 seconds ago   174MB

C:\Users\Administrator\Desktop\Nodejs_Docker>docker run -d -v C:\Users\Administrator\Desktop\Nodejs_Docker\:/Nodejs_Docker:ro -v /Nodejs_Docker/node_modules -p 3000:3000 --name codervibe_nodejsdocker  codervibe/nodejsdocker:v1.0
073f0e7df7c23eb12cdf4252916723a9492c7295b26fdc6405bc9764f60c32a9

  • 此时再去 修改文件 保存文件 刷新页面 就可以同步成功了
  • 而在删除的时候需要加上 -v 选项 否则 对应的volume 会越来越多
  • 此时 如果要启动容器 就需要 写很长的命令 我们可以使用 docker-compose.yml
  • 创建一个 docker-compose.yml 文件
version: "3.8"
services:
   codervibe_nodejsdocker:
    build: .
    ports: 
      - "3000:3000"
    volumes:
     - ./:/Nodejs_Docker:ro
     - /Nodejs_Docker/node_modules
  • 在命令行 执行 docker-compose up
  • 如果想在后台运行 容器 就可以添加 -d 选项 docker-compose up -d
  • 除此之外 还可以加上 --build 选项 docker-compose up -d --build
  • 如果镜像有修改 docker-compose 就会重建 不加 build 选项 下次就会使用之前的缓存
  • docker-compose 清除容器也很简单 只需要 用 docker-compose down
  • 并且在后面加上 -v 表示清除对应的 volume docker-compose down -v
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值