Dockerfile
Dockerfile 是一个文本格式的配置文件,用户可以使用 Dockerfile 来快速创建自定义的镜像
--内容参考 《Docker技术入门与实战第2版》
Dockerfile 由一行行命令语句组成,并且支持 # 开头的注释行
目录
1.预览
一般而言,Dockerfile 分为四个部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
# This Dockerfile uses the centos image
# VERSION 2 - EDITION 1
# Author : Dcpnet
# Command dormat : Instruction [arguments / command] ..
# Base image to user , this must be set as the first line
FROM ubuntu
# Maintainer : dcpnet <dcpnet at email.com> (@dcpnet)
MAINTAINER dcpnet dcpnet@815787213@qq.com
# Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
# Commands when creating a new container
CMD /usr/sbin/nginx
2.指令说明
指令的一般格式为 INSTRUCTION arguments
指令包括:FROM
、 MAINTAINER
、 RUN
等
指令 | 说明 |
---|---|
FROM | 指定所创建镜像的基础镜像 |
MAINTAINER | 指定维护者的信息 |
RUN | 运行命令 |
CMD | 指定启动容器时默认执行的命令 |
LABEL | 指定生成镜像的元数据标签信息 |
EXPOSE | 生命镜像内服务所监听的端口 |
ENV | 指定环境变量 |
ADD | 复制指定的 <src> 路径下的内容到容器中的 <dest> 路径下,<src>可以为URL;如果为tar文件,会自动解压到<dest>路径下 |
COPY | 复制本地主机的 <src> 路径下的内容到镜像中的 <dest> 路径下;一般情况下推荐使用 COPY,而不是 ADD |
ENTRYPOINT | 指定镜像的默认入口 |
VOLUME | 创建数据卷挂载点 |
USER | 指定运行容器时的用户名或UID |
WORKDIR | 配置工作目录 |
ARG | 指定镜像内使用的参数(例如版本信息等) |
ONBUILD | 配置当所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令 |
STOPSIGNAL | 容器退出时的信号值 |
HEALTHCHECK | 如何进行健康检查 |
SHELL | 指定使用 shell 时的默认 shell 类型 |
2.1 FROM
指定所创建镜像的基础镜像,如果本地不存在,则默认会去 Docker Hub 下载指定镜像
三种格式
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
任何 Dockerfile 中的第一条指令必须为 FROM 指令。并且,如果在同一个 Dockerfile 中创建多个镜像,可以使用多个 FROM 指令(每个镜像一次)
2.2 MAINTAINER
指定维护者信息
格式 MAINCONTAINER <name>
MAINCONTAINER dcpnet@815787213@qq.com
该信息会写入 镜像的 Author 属性域中
2.3 RUN
格式为 : RUN <command>
或 RUN["executable","param1","param2"]
。
注意,后一个指令会被解析为 Json 数组,因此必须使用双引号。
前者默认将在 shell 终端中运行命令 , 即 /bin/sh -c
后者则使用 exec 执行,不会启动 shell 环境
指定使用其他终端类型可是使用第二种方式实现:
RUN ["/bin/bash","-c","echo Hello"]
每条 RUN 指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时,可以使用 \
来换行:
RUN apt-get update \
&& apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \
&& rm -rf /var/cache/apt
2.4 CMD
CMD 指令用来指定启动容器时默认执行的命令
支持三种格式:
-
# 使用 exec 执行,是推荐使用的方式 CMD ["executable","param1","param2"]
-
# 在 /bin/sh 中执行,提供给需要交互的应用 CMD command param1 param2
-
# 提供给 ENTRYPOINT 的默认参数 CMD ["param1","param2"]
每个 Dockerfile 只能有一条 CMD 命令,如果有多条,则只有最后一条有效
如果拥堵启动容器时收订制定了运行的命令(作为 run 的参数),则会覆盖掉 CMD 指定的命令
2.5 LABEL
LABLEL 指令用来指定生成井下过的元数据标签信息
格式 LABEL <key>=<value><key>=<value><key>=<value>...
LABEL version="1.0"
LABEL description="This is a Test Label."
2.6 EXPOSE
生命镜像内服务所监听的端口
格式 EXPOSE <port>[<port>...]
EXPOSE 22 80 8443
该指令只是起到神明的作用,并不会自动完成端口映射
在启动容器的时候需要
-
使用 -P ,Docker 著聚会自动分配一个宿主注解临时端口转发到指定的端口
-
使用-p,则可以具体指定那个宿主机的本地端口会映射过来
2.7 ENV
指定环境变量,在镜像生成过程中会被后续 RUN 指令使用,在镜像启动的容器中也会存在
格式 ENV <key> <value>
或 ENV <key>=<value>
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-^PG_VERSION.tar.xz | tar -xJC /usr/src/posrfres && ...
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
指令指定的环境变量在运行时可以被覆盖掉 ,如 docker run --env <key>=<value> build_image
2.8 ADD
该命令将复制指定的 <src> 路径下的内容到容器中的 <dest> 路径下
格式 ADD <src> <dest>
其中 <src> 可以实 Dockerfile 所在目录的一个相对路径(文件或目录),也可以是一个 URL,还可以是一个 tar 文件 (如果是 tar 文件,会自动解压到 <dest> 路径下)。<dest> 可以实镜像内的绝对路径,或者是相对于工作目录 (WORKDIR) 的相对路径.
路径支持正则格式
ADD *.c /code/
2.9 COPY
格式为 COPY <src> <dest>
复制本地的 <src> (为 Dockerfile 所在目录的相对路径、文件或目录) 下的内容到镜像中 <dest> 下。目标路径不存在时,会自动创建。
路径同样支持正则格式
当使用本地目录为源目录是,推荐使用 COPY
2.10 ENTRYPOINT
指定镜像的默认入口命令,该入口命令会在启动容器时作为跟命令执行,所有传入值作为该命令的参数
支持两种格式
# 第一种 exec 调用执行
ENTRYPOINT ["executable","param1","param2"]
# 第二种 shell 中执行
ENTRYPOINT command param1 param2
此时 ,CMD 指令指定值将作为根命令的参数
【注】每个 Dockerfile 中只能有一个 ENTRYPOINT ,当指定多个,只有最后一个生效
在运行时,可以被 --entrypoint 参数覆盖掉,如
docker run --entrypoint
2.11 VOLUME
创建一个数据卷挂载点
格式为 VOLUME ["/data"]
可以从本地主机或者其他容器挂载数据卷,一般用来存放数据库和需要保存的数据等。
2.12 USER
指定运行容器时的用户名或 UID,后续的 RUN 等指令也会使用指定的用户身份。
格式 USER daemon
放服务不需要管理员权限时,可以通过命令指定运行用户,并且可以在之前创建所需要的用户
RUN troupadd -r postgres && useradd -r -g postgres postgres
幺零是获取管理员权限可以使用 gosu 或者 sudo
2.13 WORKDIR
为后续的 RUN、CMD和 ENTRYPOINT 指令配置工作目录
格式为 WORKDIR /path/to/workdir
可以使用多个 WORKDIR 指令,后续指令如果参数时相对路径,则会基于之前命令指定的路径:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
# 最终路径 /a/b/c
2.14 ARG
制定一些镜像内使用的参数(版本号信息等),这些参数在指定 docker build
命令时才以 --build-arg <varname>=<value>
格式传入
格式为 ARG <name>[=<default value>]
则可以使用 docke build-build-arg <name>=<value>
2.15 ONBUILD
配置当所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令
格式为 ONBUILD [INSTRUCTION]
例如,Dockerfile 使用如下的内容创建了镜像 image-A
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]
如果基于 image-A 创建新的竟像是,新的 Dockerfile 中使用 From image-A
指定基础镜像自动执行 ONBUILD 指定的那日容,等价于在后面添加了两条指令
FROM image-A
# Auromatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src
使用ONBUILD 指令的镜像,推荐在标签中注明: dcpnet:1.9-onbuild
2.16 STOPSIGNAL
指定所创建镜像启动的容器接受退出的信号值
STOPSIGNAL signal
2.17 HEALTHCHECK
配置所启动容器如何进行健康检查(如何判断健康与否),自 Docker 1.12开始支持
格式
# 根据所执行命令返回值是否为 0 来判断
HEALTHCHECK [OPTONS] CMD command
-
HEALTHCHECK [OPTIONS ] CMD command : 根据所执行命令返回值是否为 0 来判断
-
HEALTHCHECK NONE:禁止基础镜像中的健康检查
OPTION :
--interval=DURATION (默认为30s):过多久检查一次
--timeout=DURATION(默认为30s):每次检查等待结果的超时
--retries(默认为3):如果失败了,重试几次才确定失败
2.18 SHELL
指定其他命令使用 shell 时的默认 shell 类型
默认值为 ["/bin/bash","-c"]
对于 Windows 系统,建议在 Dockerfile 开头添加
#escape=
来指定转义信息
3.创建镜像
编写完 Dockerfile 之后,可以通过 docker build 命令来创建镜像。
基本的格式为 : docker build [选项] 内容 路径
该命令读取指定路径下(包括子目录)的 Dokcerfile ,并将给路径下的所有内容发送给 Docker 服务端,由服务端来创建镜像。因此除非生成镜像需要,否则一般建议放置 Dockerfile 的目录为空目录。
如果使用非内容路径下的 Dockerfile ,可以通过 -f 选项来指定其路径
要指定生成镜像的标签信息,可以使用 -t 选项
eg. 指定 Dockerfile 所在路径为 /temp/docker_builder/ ,并且希望申城镜像标签为 build_repo/first_image:
docker build -t build_repo/first_image /temp/docker_builder/
4.使用 .dockerignore 文件
可以通过 .dockerignore 文件(每一行添加一条匹配模式) 来让 Docker 忽略匹配模式路径下的目录和文件:
# comment
*/temp*
*/*/temp*
temp?
~*
5.实践经验
在实际开发中,根据需求要对镜像等进行配置和选择。
所以要对每个指令的含义和执行效果要有一个比较清晰的理解,自己多编写一些例子进行测试,弄清楚了在撰写正式的 Dockerfile 。此外,Docker Hub 官方仓库提供了大量的优秀镜像和对应的 Dockerfile,可以通过阅读他们来学习如何撰写高效的 Dockerfile
经验
-
精简镜像用途:尽量让每个镜像的用途都比较机中、单一,避免构造大而复杂、多功能的镜像
-
选用合适的镜像:过大的基础镜像会造成臃肿的镜像,一般推荐较小的 debian 镜像
-
提供足够清晰的命令注释和维护者信息:Dockerfile 也是一种代码,需要考虑方便后续拓展和他人使用
-
正确使用版本号:使用明确的版本号信息,如 1.0、2.0,而非 latest,将避免内容不一致可能引发的惨案
-
减小镜像层数:如果希望所生成镜像的层数尽量少,则要尽量合并指令,例如多个 RUN 指令可以合并为一条。
-
及时删除临时文件和缓存文件: 特别是在执行
apt-get
指令后,/var/cache/apt
下会缓存一些安装包 -
提高生成速度:如合理使用缓存,减少内容目录下的文件,或使用 .dockerignore 文件指定等
-
调整合理的指令顺序:在开启缓存的情况下,内容不变的指令尽量放在前面,这样可以尽量复用
-
减少外部源的干扰:如果确实要从外部引入数据,需要指定持久的地址,并带有版本信息,让他人可以重复而不出错