Dockerfile简介
Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile快速创建自定义的镜像
Dockerfile有一行行命令语句组成,支持以#开头的注释行。
一般,Dockerfile分为四个部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令
Dockerfile常用指令
参考:https://docs.docker.com/engine/reference/builder/#usage
FROM
用法:
FROM [--platform=<platform>] <image> [AS <name>]
# 或
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
# 或
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
说明:
-
中括号
[]
中的之为可选值 -
Dockerfile必须从FROM指令开始(仅ARG可以先于FROM指令,可以用来指定FROM参数)
-
如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令
-
AS name
可以给镜像取名字,可以作为多阶段构建的基础镜像给予FROM
指令,或者COPY --from=<name>
-
--platform
可以用于指定镜像平台(如linux/amd64,linux/arm64);用于交叉编译构建
RUN
用法:
# shell模式,默认使用 /bin/sh -c 执行命令
RUN <command>
# exec模式,例如 RUN ["/bin/bash", "-c", "echo hello"]
RUN ["executable", "param1", "param2"]
说明:
-
RUN
指令在构建时将会生成一个新的镜像层并且执行RUN指令后面的内容 -
镜像层数会增加镜像大小,因此尽量将多个命令放在一个
RUN
指令中(使用&&
平均多个命令) -
当
RUN
指令后面跟的内容比较复杂时,建议使用反斜杠(\) 结尾并且换行 -
RUN
指令后面的内容尽量按照字母顺序排序,提高可读性。
LABEL
用法:
LABEL <key>=<value> <key>=<value> <key>=<value>
说明:
- 使用
LABEL
为镜像添加元数据以标识该镜像
CMD和ENTRYPOINT
用法:
CMD ["executable","param1","param2"] # exec形式,推荐模式
CMD ["param1","param2"] # 作为ENTRYPOINT的默认参数
CMD command param1 param2 # shell模式
ENTRYPOINT ["executable", "param1", "param2"] # exec模式,推荐模式
ENTRYPOINT command param1 param2 # shell模式
说明:
CMD
用来设置容器启动后默认执行的命令及其参数;ENTRYPOINT 用来配置容器启动时运行的命令。二者都可以作为容器的启动入口- 每个Dockerfile只能有一个
CMD
和ENTRYPOINT
,如果有多个,只有最后一个生效 - 如果
CMD
作为ENTRYPOINT
的默认参数,则CMD和ENTRYPOINT都必须使用json数组形式(也就是exec形式) - 使用 exec 模式启动容器时,容器的 1 号进程就是 CMD/ENTRYPOINT 中指定的命令,而使用 shell 模式启动容器时相当于我们把启动命令放在了 shell 进程中执行,等效于执行 /bin/sh -c “task command” 命令。因此 shell 模式启动的进程在容器中实际上并不是 1 号进程。
二者的区别:
-
Dockerfile 中如果使用了ENTRYPOINT指令,启动 Docker 容器时需要使用 --entrypoint 参数才能覆盖 Dockerfile 中的ENTRYPOINT指令 ,而使用CMD设置的命令则可以被docker run后面的参数直接覆盖。
-
ENTRYPOINT指令可以结合CMD指令使用,也可以单独使用,而CMD指令只能单独使用
ADD和COPY
用法:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
说明:
--chown
是可选的,用来修改复制文件的用户和用户组- ADD和COPY都是从外部往容器中添加文件。但是COPY只支持基本的文件和文件夹;而ADD支持更多的文件类型,比如可以是URL和压缩包(.tar.gz会自动解压)
- 尽量使用COPY指令,ADD指令较为复杂。二者区别
USER
用法:
USER <user>[:<group>]
USER <UID>[:<GID>]
说明:
- 指定运行容器时的用户名/用户组或者UID/GID;后续的 RUN等指令也会使用该用户
WORKDIR
用法:
WORKDIR /path/to/workdir
说明:
- 为后续的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目录。(可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径, 则会基于之前命令指定的路径)
ARG
用法:
ARG <name>[=<default value>]
说明:
ARG
指令用来定义了一个变量,用户可以在构建时docker build
使用带有--build-arg <varname>=<value>
标志的命令将其传递给构建器。如果用户指定了未在Dockerfile中定义的构建参数,则构建会输出警告。[Warning] One or more build-args [foo] were not consumed.
EXPOSE
用法:
EXPOSE <port> [<port>/<protocol>...]
说明:
- 指定Docker容器时监听的端口,可以指定协议是TCP还是UDP;默认是TCP
- EXPOSE并不会真的去启动该端口,容器的实际监听端口是应用的监听端口;EXPOSE主要是用来指导运行容器的人员该容器运行服务的发布的端口。
VOLUME
用法:
VOLUME ["/data"]
说明:
- 创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放需要持久化保存的数据
- 容器启动时,该挂载点会自动在宿主机上创建相应的目录(无法指定);可以通过
docker inspect id
查看挂载的目录
Dockerfile最佳实践
参考文档:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#exclude-with-dockerignore
单一职责
由于容器的本质是进程,一个容器代表一个进程,因此不同功能的应用应该尽量拆分为不同的容器,每个容器只负责单一业务进程。
提供注释信息
Dockerfile 也是一种代码,我们应该保持良好的代码编写习惯,晦涩难懂的代码尽量添加注释,让协作者可以一目了然地知道每一行代码的作用,并且方便扩展和使用。
精简容器
1、合理选择基础镜像,减少基础镜像大小(比如java应用只需要jre,而不是jdk)
2、不安装不必要的软件包,如vim,gcc等
3、减少镜像层数
RUN
,COPY
,ADD
指令会增加镜像层数;其他指令会创建临时镜像,不会增加镜像大小。
可以使用多阶段构建,仅仅将最终的工件复制到最终镜像中。
.dockerignore文件
使用.dockerignore
忽略不需要参与构建的文件
这是一个示例.dockerignore
文件:
# comment
*/temp*
*/*/temp*
temp?
此文件导致以下生成行为:
规则 | 行为 |
---|---|
# comment | 忽略了。 |
*/temp* | 排除名称以temp 根的任何直接子目录开头的文件和目录。例如,/somedir/temporary.txt 排除了普通文件,也排除了目录/somedir/temp 。 |
*/*/temp* | 排除temp 从根以下两个级别的任何子目录开始的文件和目录。例如,/somedir/subdir/temporary.txt 被排除。 |
temp? | 排除根目录中名称为的一个字符扩展名的文件和目录temp 。例如,/tempa 和/tempb 被排除。 |
使用构建缓存
默认会使用构建缓存加快构建速度
docker build
增加参数--no-cache=true
可以禁用缓存
正确设置时区
默认从docker.hub中获取的镜像都是UTC时区(世界标准时区),可以通过如下方式设置为东八区
Ubuntu 和Debian 系统可以向 Dockerfile 中添加以下指令:
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo "Asia/Shanghai" >> /etc/timezone
CentOS 系统则向 Dockerfile 中添加以下指令:
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
Dockerfile参考
官方Dockerfile参考链接