Docker 的核心思想就是将应用整合到容器中, 并且在容器中实际运行.
8.1 应用的容器化-简介
容器化过程:
- 编写应用代码
- 创建 Dockerfile
- 执行 docker image build
- 等待镜像生成
8.2 应用的容器化-详解
8.2.1 单体应用容器化
- 获取应用代码
分析Dockerfile
- 包含应用文件的目录被称为构建上下文 (Build Context)
Dockerfile 的内容:
FROM alpine
LABEL maintainer="xxx"
RUN apk add --update nodejs nodejs-npm
COPY . /src
WORKDIR /src
RUN npm install
EXPOSE 8080
ENTRYPOINT ["node", "./app.js"]
不会创建镜像层的指令:
- label
- workdir
- expose
- entrypoint
构建后的镜像层:
- 容器化当前应用/构建具体的镜像
$ docker image build -t web:latest .
- 推送镜像到仓库
登录:
$ docker login
推送镜像需要如下信息:
- Registry (镜像仓库服务), 默认为
Registry=docker.io
- Repository (镜像仓库)
- Tag (镜像标签), 默认为
Tag=latest
重打标签:
- 并没有覆盖
$ docker image tag web:latest nigelpoulton/web:latest
推送:
$ docker image push nigelpoulton/web:latest
- 运行应用程序
$ docker container run -d --name c1 -p 80:8080 web:latest
- app 测试
- 详述
- Dockerfile 中的注释使用
#
- 指令不区分大小写
- 解析是按照行的书写顺序
- Dockerfile 中的注释使用
8.2.2 生产环境中的多阶段构建
- 对于生产环境来说, 应该使镜像体积尽量小
- 不同的 Dockerfile 写法会对镜像大小产生显著影响
- 多在
RUN
指令一行中使用&&
连接多个命令和\
换行 RUN
指令在运行指定程序后, 会在镜像中残留构建文件- 建造者模式 (Builder Pattern) 需要至少两个 Dockerfile (开发, 生产)
- Dockerfile.dev
- Dockerfile.prod
多阶段构建:
- 多阶段构建使用一个 Dockerfile
- 包含多个 FROM 指令, 每一个都是构建阶段 (Build Stage)
注意:
FROM xxx:yyy AS zzz
COPY --from
查看多阶段构建方式生成的镜像:
$ docker image ls
8.2.3 最佳实践
- 利用构建缓存, 将易于变化的指令放在最后
docker image build --nocache=true
禁用缓存
- 合并镜像
- 利弊参半
- Docker 会将正常构建的各镜像层合并
- 基础镜像最好进行合并
- 无法共享镜像层, 镜像体积大
docker image build --squash
合并镜像- push 时, 合并的镜像需要发送全部内容
- 使用 no-install-recommends
- 不要安装 MSI 包 (Windows)