Dockerfile使用的整理
最近使用Dockerfile构建docker镜像,总结了一下一些指令规范,整理如下:
Dockerfile 书写原则
(1)Dockerfile 的指令是忽略大小写的,建议使用大写
(2)提供注释信息
Dockerfile 也是一种代码,我们应该保持良好的代码编写习惯,晦涩难懂的代码尽量添加注释,让协作者可以一目了然地知道每一行代码的作用,并且方便扩展和使用。
(3)保持容器最小化
应该避免安装无用的软件包。
(4)合理选择基础镜像
(5)使用 .dockerigonre 文件
使用 .dockerignore 文件,允许我们在构建时,忽略一些不需要参与构建的文件,避免将不必要的文件, 拷贝到镜像中, 比如 .git,.java等,如此,构建镜像的过程通常会更快, 生成的镜像通常会更小, 整个部署过程耗时更少, 也避免k8s work nodes磁盘被大量镜像文件占用。
因此,需要在项目中,在 Dockerfile 工作的根目录下添加 .dockerignore 文件,文件里面包含内容如下:
**/*.git **/*.java |
其中,**/*.java 仅后端项目需要。
注:请严格按照上述格式编写,可以保证任意层级存在 .git 或 .java 文件均被排除在打包镜像之外。
其他使用方式可参加官方文档:.dockerfile file
在无法优化构建流程时, 可使用镜像压缩工具docker-squash,
(6)尽量使用构建缓存
Docker 构建过程中,每一条 Dockerfile 指令都会提交为一个镜像层,下一条指令都是基于上一条指令构建的。如果构建时发现要构建的镜像层的父镜像层已经存在,并且下一条命令使用了相同的指令,即可命中构建缓存。
因此,基于 Docker 构建时的缓存特性,我们可以把不轻易改变的指令放到 Dockerfile 前面(例如安装软件包),而可能经常发生改变的指令放在 Dockerfile 末尾(例如编译应用程序)。
(7)最小化镜像层数
在构建镜像时尽可能地减少 Dockerfile 指令行数,尽量在一个 RUN 指令中运行更多的命令,以此提高性能,减少 IO 损耗。
Dockerfile 指令书写建议
(1)RUN
RUN 指令在构建时将会生成一个新的镜像层并且执行 RUN 指令后面的内容。
使用 RUN 指令时,应尽量遵循以下原则:
1. 指令后面的内容比较复杂时,建议使用反斜杠(\)结尾并换行;
2. 使用 ‘yum install …’ 时, 建议在同一个 RUN 命令中, 使用 ‘yum clean all && rm -rf /var/cache/yum’ 来清理多余文件.
(2)CMD 和 ENTRYPOINT
这两个指令都是容器的入口,这两个指令的相同之处在于:
1. 使用格式基本分为两种:
第一种称为 exec 模式(推荐使用),书写格式为:
CMD / ENTRYPOINT [“command”, “param”] |
指令后面跟 json 数组,是 Docker 推荐的使用格式,也是我们项目建议使用的格式。
第二种称为 shell 模式,当时使用 shell 模式时,Docker 会以 /bin/sh -c command 的方式执行命令。
CMD 和 ENTRYPOINT 区别在于:
1. Dockerfile 中如果使用了 ENTRYPOINT 指令,启动 Docker 容器时,只有使用 --entrypoint 参数才能覆盖 Dockerfile 中的 ENTRYPOINT 指令;而使用 CMD 设置的命令,则可以被 docker run 后面的参数直接覆盖。
CMD 和 ENTRYPOINT 指令可以单独使用,也可以组合使用。
综上,如果在构建 Docker 容器时,需要执行单一的具体程序,不希望用户在执行 docker run 时覆盖默认程序,建议使用 ENTRYPOINT;如果需要镜像足够灵活,建议使用 CMD 指令。
(3)ADD 和 COPY
两个指令功能类似,都是从外部向容器中添加文件。但是 COPY 命令只支持基本的文件和目录的拷贝, ADD 支持更多的文件类型,所以若需要将外部的压缩文件解压到镜像中, 请使用 ADD 指令, 而不是 COPY + RUN untar … 组合指令, 因为 ADD 指令可自动解压 + 复制。
(4)WORKDIR
用来指定容器的工作路径。
(5)ENV
用于设置环境变量,书写格式推荐写为:
ENV <key>=<value> |
当有多组环境变量,书写多行 ENV 即可。
若 build 镜像时, 需要通过代理访问网络, 可尝试使用 ENV http_proxy … 和 ENV https_proxy … 指令, 并在使用后销毁。
日常可使用 docker image prune 和 docker container prune 来清理无用空间。
Docker 容器内的配置
1.除配置性质的文件外, 请不要在容器自身的文件系统中写数据, 转而使用外接volume;
2.stdout仅输出重要提示信息, 请勿当做常规日志数据通道.
参考文档
https://stackoverflow.com/questions/45142528/what-is-a-dangling-image-and-what-is-an-unused-image
https://docs.docker.com/engine/reference/commandline/image_prune/
https://docs.docker.com/engine/reference/commandline/container_prune/