Docker Dockerfile

ABEE · 2022年01月07日 · 1601 次阅读

Dockerfile 是由一系列指令和参数构成的脚本,一个 Dockerfile 里面包含了构建整个镜像的完整命令。

工作中,由于业务水平与技术选型不同,在使用 Docker 起服务时,需要定制项目镜像。通过两种方式:

  • Docker commit
  • Dockerfile
Docker commit

基于一个运行状态的容器,在容器内安装项目运行所需要的环境依赖,再创建出一个新的镜像。

$ docker commit -a "author" -m "commit info" container_id image_name:tag

使用这种方式制作的镜像,对外不可解释,不知道镜像内的环境组成,不方便排查问题,可维护性差。

Dockerfile

Dockerfile 是一个文本文档,通过 docker build 命令去执行文件内部定义的指令,自动构建镜像。推荐使用这种方法,可以直观的看到镜像构建记录。

构建镜像时,Dockerfile 的目录最好不要放其他文件,因为构建时会将该目录下全部文件传输到 docker daemon,文件过大时,影响构建性能。

构建命令如下:

  • -t 指定镜像名称和标签
  • -f 指定 Dockerfile 文件路径
  • . 代表当前路径,千万别忘记写 bash $ docker build -t pytest:v1 -f Dockerfile .

Dockerfile 常用指令

指令不区分大小写,为方便区分指令和参数,约定指令统一大写。

FROM    # 指定基础镜像,Dockerfile 必须以 FROM 指令开始(除 ARG)
LABEL   # 标签信息,作者、版本等;<key>=<value> <key>=<value> ...
ENV     # 容器启动的环境变量;<key>=<value> ...
ARG     # 仅作用于 Dockerfile 的环境变量,可以出现在 FROM 指令之前
USER    # 指定运行容器时的用户名或 UID,默认管理员用户,后续 RUN 也会使用指定用户
WORKDIR # 设置工作目录,作用于 RUN、CMD、ENTRYPOINT、ADD 指令
ADD     # 添加压缩文件到镜像中,自动解压缩
COPY    # 复制文件到镜像中
VOLUME  # 挂载目录
RUN     # 运行命令,每条 RUN 指令在当前基础镜像上执行,并且会提交一个新的镜像层
EXPOSE  # 对外暴漏端口号,可以被容器运行时的 -p 参数覆盖掉
CMD     # 容器启动时执行的默认命令
ENTRYPOINT   # 容器启动时指定参数
HEALTHCHECK  # 容器健康状态检查

编写 Dockerfile 的最佳实践参考官方文档:

Best practices for writing Dockerfiles

这里简单列出几点:

  • 多行参数使用换行符
  • 不要安装非必要的包
  • 每个容器只干一件事,解耦应用程序
  • 尽量减少镜像层数
  • 充分利用构建缓存

镜像制作过程中,每个指令代表一层,镜像是由多层镜像累加起来的。指令会产生缓存,构建过程中会优先使用缓存,所以当开发镜像时,先用多个 RUN 命令,充分利用下载的缓存,提高调试的效率。当然也可以指定 --no-cache 参数禁用缓存。

Dockerfile 开发完成后,用 && 符号把 RUN 指令合并换行,作为同一层镜像进行构建。因为镜像的分层原理,每多一层就会多一次 IO 开销,当指令过多,可能会影响系统性能。

演示

使用 Dockerfile 构建 nginx 容器。

# index.html
<h1>Hello Nginx!</h1>
# Dockerfile

# 导入基础镜像
FROM nginx:latest

# 指定信息
LABEL Description="Nginx Testing Service."

# 设置环境变量
ENV WELCOME "hello, nginx!"

# ARG 设置的环境变量只在 dockerfile 生效
ARG dir=/usr/share/nginx

# 设置工作目录
WORKDIR $dir/html

# 切换用户
USER root

# 执行安装命令
RUN apt-get -y update && apt-get install -y curl

# 复制 index.html 文件到工作目录下
COPY index.html .

# 映射 80 端口
EXPOSE 80

# 容器启动参数
CMD ["nginx", "-g", "daemon off;"]

# 健康检查,通过访问 Nginx 服务 80 端口,来判断容器是否正常运行
HEALTHCHECK --interval=5s --timeout=3s \
  CMD curl -fs http://localhost/ || exit 1
构建并验证
# 构建镜像
$ docker build -t nginx:test .
...
# 启动容器
$ docker run -d -p 80:80 --name demo nginx:test
...

# 访问 IP 地址,即可看到自定义的欢迎页

# 进入容器
$ docker exec -it demo bash
# 用户为 root
# 开始目录为设置的工作目录
# 执行 env 命令,出现设置的环境变量
root@*:/usr/share/nginx/html $ env
WELCOME=hello, nginx!

# 查看容器日志;健康检查生效
$ docker logs -f demo
127.0.0.1 - - [07/Jan/2022:09:52:12 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.74.0" "-"

以上内容在官方文档都可以找到详细的介绍,这里摘要出来,方便查阅。

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册