三大概念
容器(Container)
容器是应用程序层的抽象,可以将代码和依赖项打包在一起。容器不虚拟化整个物理机,仅虚拟化主机操作系统。
镜像(Image)
镜像是分层的自包含文件,充当创建容器的模板。它们就像容器的冻结只读副本,可以通过仓库进行共享。
仓库(Registry)
一个集中式的位置,可以在其中上传镜像,也可以下载其他人创建的镜像。Docker Hub是Docker的默认公共仓库,MICR就是小米的一个镜像仓库
Docker架构
Docker引擎包括三个主要组件:
- Docker守护程序:守护程序是一个始终在后台运行并等待来自客户端的命令的进程,守护程序能够管理各种Docker对象。
- Docker客户端:客户端是一个命令行界面程序,主要负责传输用户发出的命令。
- REST API:REST API充当守护程序和客户端之间的桥梁,使用客户端发出的任何命令都将通过API传递,最终到达守护程序。
“ Docker 使用客户端-服务器体系结构。Docker client 与 Docker daemon 对话,daemon 繁重地构建、运行和分发 Docker 容器”。
作为用户,通常使用客户端组件执行命令。然后,客户端使用 REST API 来访问长期运行的守护程序并完成工作。
容器的操作命令
查看当前正在运行或过去运行的所有容器
docker ps -a
运行容器
docker run <image name>
docker container run <image name>
公开端口 :--publish 或 -p
容器是隔离的环境,要允许从容器外部访问运行在容器内部的应用程序,必须将容器内的相应端口发布到本地网络上的端口
--publish <host port>:<container port>
分离模式:--detach 或-d
默认情况下,必须将终端窗口保存打开状态来使容器继续运行,关闭终端窗口会停止正在运行的容器。为了覆盖此行为并保持容器在后台运行,可以使用--detach
docker container run --detach --publish 8080:80 fhsinchy/hello-dock
这意味着发送到主机系统端口8080的任何请求都将转发到容器内的端口80
停止后立即被移除:--rm
该参数也可用在container start命令中
docker container run --rm --detach --publish 8888:80 --name hello-dock-volatile fhsinchy/hello-dock
命名:--name
默认情况下,容器有两个标识符:
CONTAINER ID:一个64个字符的随机字符串
NAME:两个随机词的组合,下划线连接
可以使用--name选项来命名容器
docker container run --detach --publish 8888:80 --name hello-dock-container fhsinchy/hello-dock
列表展示容器
docker container ls
重命名容器
docker rename <old name> <new name>
停止或杀死运行中的容器
docker container stop <container identifier>
其中,container identifier可以使容器的ID或名称。
如果使用 name 作为标识符,则 name 将作为输出返回。stop 命令通过发送信号SIGTERM 来正常关闭容器。如果容器在一定时间内没有停止运行,则会发出 SIGKILL 信号,该信号会立即关闭容器。
如果要发送 SIGKILL 信号而不是 SIGTERM 信号,则可以改用 docker container stop <container identifier> 命令
重新启动已停止或终止的容器
docker container start <container identifier>
重新启动正在运行的容器
docker container restart <container identifier>
创建而不运行容器
docker container create <image name>
因此,docker container run实际上是container create和container start两个命令的组合
移除挂起的容器
已被停止或终止的容器仍保留在系统中可以使用container rm命令删除停止的容器
docker container rm <container identifier>
也可以使用container prune命令来一次性删除所有挂起的容器
在容器里执行命令
docker container run <image name> <command>
在container run命令中,镜像名称后传递的任何内容都将传递到镜像的默认入口里。入口点就是通往镜像的网关。除可执行镜像外的大多数镜像使用shell或sh作为默认入口点,因此,任何有效的shell命令都可以作为参数传递给它们。
注:可执行镜像的入口点设置为自定义程序。
绑定挂载 :--volume 或 -v
是一种授予容器直接访问本地文件系统的一种方法。
绑定挂载可以在本地文件系统目录(源)与容器内另一目录(目标)之间形成双向数据绑定。这样,在目标目录中进行的任何更改都将在源目录上生效,反之亦然。
--volume <local file system directory absolute path>:<container file system directory absolute path>:<read write access>
第三个字段是可选的,但必须传递本地目录的绝对路径和容器内目录的绝对路径。
--volume 或 -v 选项对 container run 以及 container create 命令均有效
Dockerfile文件
Dockerfile是指定的集合,该指令会被守护进程生成镜像。
示例:
FROM ubuntu:latest
EXPOSE 80
RUN apt-get && \
apt-get install nginx -y && \
apt-get clean && rm -rf /var/lib/apt/lists/*
CMD ["nginx", "-g", "daemon off;"]
镜像是一个多层文件,在Dockfile文件中,编写的每一行都将为镜像创建一个层。
- 每个有效的Dockerfile均以
FROM指令开头,该指令为生成的镜像设置基本镜像。此处将ubuntu:latest设置为基本镜像,因此在自定义镜像中可以使用ubuntu的所有功能,比如下面使用apt-get命令安装软件包。 - EXPOSE指定表示需要发布的端口。
- RUN指令在shell内部执行命令。
apt-get clean && rm -rf /var/lib/apt/lists/*用于清楚程序包缓存,因为不希望镜像中出现任何不必要的文件。 - CMD指定为镜像设置了默认命令。这里,
nginx是指 NGINX 可执行文件。-g和daemon off是 NGINX 的选项。
.dockerignore文件
类似于.gitignore,用来排除不需要上传到 docker 容器的文件或目录
镜像的操作命令
使用Dockerfile构建镜像
docker image build .
docker image build --file <docker filename> .
docker image build是用于构建镜像的命令。守护程序在上下文中找到任何名为 Dockerfile 的文件。
- 最后的
.设置了此构建的上下文。上下文是指在构建过程中守护程序可以访问的目录。
现在要使用此镜像运行容器,可以将 container run 命令与在构建过程中收到的镜像 ID 结合使用。
标记docker镜像
不使用随机生成的ID,为镜像分配自定义标识符
--tag <image repository>:<image tag>
repository 通常指镜像名称,而 tag 指特定的构建或版本。
例如:docker image build --tag custom-nginx:packaged .
列表展示镜像
docker image ls
删除镜像
docker image rm <image identifier>
还可以使用image prune 命令来清除所有未标记的挂起的镜像
可视化镜像的分层
docker image history <image identifier>
镜像的每一层都会占据内存,如果需要删除某些文件,最好在一次RUN中使用后就删除,不要单独使用一次RUN命令来做删除操作
案例分析
开发模式,用npm run server命令启动一个开发服务器,该服务器将应用程序提供给用户
FROM node:lts-alpine #使用node:lts-alpine作为基础镜像
EXPOSE 80 # 表示要发布的端口为80,但是运行容器时仍需要--publish选项
USER node # node镜像会附带一个名为node的非root用户,USER命令将镜像的默认用户设置为node
RUN mkdir /home/node/vue-app # 创建目录
WORKDIR /home/node/vue-app # 设置工作目录,默认情况下,任何镜像的工作目录都是根目录
COPY ./package.json . # 将主机文件系统当前目录下的package.json复制到镜像的工作目录中
RUN npm install # 基于package.json安装依赖
COPY . . # 将当前目录下的文件全部复制到镜像中
CMD ["npm", "run", "dev"] # 设置了镜像的默认命令
但是,在生产环境下,npm run build命令将所有JavaScript代码编译为一些静态HTML、CSS和JavaScript文件。要运行这些文件,不需要node或任何其他运行时依赖项,只需要一个像nginx这样的服务器。
让应用程序以生产模式运行时创建镜像,可以执行以下步骤:
- 使用node作为基础镜像并构建应用程序
- 在node镜像中安装nginx并使用它来提供静态文件
# 方式1: 在容器中安装软件包再npm run build
FROM node:lts-alpine as builder #使用node:lts-alpine作为基础镜像开始构建的第一阶段
RUN mkdir /home/node/vue-app
WORKDIR /home/node/vue-app
COPY ./package.json .
RUN npm install
COPY . .
RUN npm run build # 在镜像中编译项目
FROM nginx:stable-alpine #使用nginx:stable-alpine作为基础镜像开始构建的第二阶段
EXPOSE 80 # 暴露接口为80
# --from=builder表示要从builder阶段复制一些文件。这里的/usr/share/nginx/html 是nginx的默认站点路径,因此放置在其中的任何静态文件都将自动提供
COPY --from=builder /home/node/vue-app/dist /usr/share/nginx/html
除了在镜像中编译代码,还可以在本地npm run build后,将编译好的产物放在镜像中
# 方式2:直接将构建产物复制到容器里
FROM nginx:stable-alpine
EXPOSE 80
RUN mkdir /app
WORKDIR /app
# 或者COPY ./dist/* /usr/share/nginx/html/
COPY ./dist /usr/share/nginx/html
docker运行nginx
nginx服务器静态资源目录:/usr/share/nginx/html
nginx配置文件目录:/etc/nginx/nginx.conf
nginx log目录:/var/log/nginx