Docker系列(四):Dockerfile 配置详解
Docker 通过读取 Dockerfile
文件中的指令自动构建镜像,Docker 镜像包含只读层,每一层就代表 Dockerfile 中的一条指令,层与层是堆叠的,每一层是与前一层的变化的增量。使用 docker build
命令,用户可以创建一个自动构建,连续执行多条命令行的指令。
官方参考:Dockerfile官方最佳实践, Docker 中文站
概述
Dockerfile 由一行行命令语句组成,支持以#
开头的注释行,注释行不能换行。
Dockerfile 基本结构可划分为四个部分:
- 基础镜像信息:文件开始必须先指明所基于的基础像名称。
- 维护者信息:说明下维护者信息。
- 镜像操作指令:如
RUN
指令,每执行一条RUN指令,镜像就添加新的一层,并提交。 - 容器启动时执行指令:如
CMD
,用来指定运行容器时的操作命令。
指令
Dockerfile文件中的指令是按先后顺序执行,可以使用的指令有如下:
指令 | 说明 |
---|---|
FROM | 指定所创建镜像的基础镜像 |
MAINTAINER | 指定维护者(作者)信息 |
RUN | 运行命令 |
LABEL | 指定生成镜像的元数据标签信息 |
EXPOSE | 声明镜像内服务服务所监听的端口 |
ENV | 指定环境变量 |
ADD | 添加指定的<src> 路径下的内容到容器中的<dest> 路径下, <src> 可以为 URL,如果为 tar 文件,则会自动解压到<dest> 路径下 |
COPY | 复制本机的<dest> 路径下;一般推荐使用 COPY,而不是ADD |
ENTRYPOINT | 指定镜像的默认入口 |
VOLUME | 创建数据卷的挂载点 |
USER | 指定运行容器时的用户名或UID |
WORKDIR | 配置工作目录 |
ARG | 指定镜像内使用的参数(如版本号信息) |
ONBUILD | 配置当前所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令 |
STOPSIGNAL | 容器退出的信号值 |
HEALTHCHECK | 进行健康检查 |
SHELL | 指定使用 shell 时的默认 shell 类型 |
指令详解
FROM
一个 Dockerfile 以FROM
指令开始(启动)。指令指定指定了基础镜像,如果本地没有就会到远程仓库下载。基础镜像推荐官方发行版,理由是控制严格,保持最低文件大小(Debian 低于150M)。
RUN
在当前镜像新的层中执行命令并提交结果,生成新的镜像作为 Dockerfile 中下一步指令的基础镜像。该命令有shell
和 execform
两种形式。
- shell 方式:
RUN <cmomand>
在shell中运行,默认情况下,Linux是在 /bin/sh -c下运行, Windows是在 cmd /S /C下运行; 此方式可以使用\
将多行命令连接为为一行:RUN /bin/bash -c ‘source $HOME/.bashrc;
echo $HOME’连接后等同于一行,如下:
RUN /bin/bash -c ‘source $HOME/.bashrc; echo $HOME’ - exec form 方式:
RUN ["executable", "param1", "param2"]
该方式可以避免 shell 命令执行时发生字符串转换,并且可以不包含指定可执行shell文件,exec form 方式会被转换为 JSON 数组,命令和参数必须使用双引号括起来。如果是在 Widnows环境,路径中\
要\\
代替。
CMD
一份 Dockerfile 文件中只能有一条CMD
指令,若出现多条时,则只有最后一条CMD
指令生效,CMD指令有三种形式:
CMD ["executable","param1","param2"]
(exec form,首选方式)CMD ["param1","param2"]
(作为 ENTRYPOINT 的默认参数)
如果使用此方式,则必须使用 JSON 数组格式 同时指定 CMD 和 ENTRYPOINT 指令。
CMD command param1 param2(shell 方式)
如果用户在docker run
指令中指定的参数,则会覆盖掉CMD
中指定的默认参数。RUN
是执行命令并提交结果;而CMD
在构建时并不执行任何操作,是镜像的预期命令,在镜像构建完后执行。
MAINTAINER
用于指定镜像的维护者(作者)。
MAINTAINER kitty kitty@xxx.com
EXPOSE
设置容器必须监听的端口(暴露的端口):EXPOSE port [port ...]
此端口是用于与本地主机的通信,外部应用不能直接访问容器,只能通过访问本地主机的端口再转发到容器的端口。
在创建容器时,需要通过-p
参数来指定本地主机的端口与容器暴露的端口的映射关系。
ENV
用于设置环境变量。
语法:有两种方式
ENV <key> <value>
ENV <key>=<value> ...
如:ENV myName=”John Doe”
ENTRYPOINT
可以让容器像一个可执行程序一样运行,这样在执行docker run
命令时可以接收参数。最好的用法是用 ENTRYPOINT 来设置镜像的主要命令,用 CMD 来设置默认参数。
VOLUME
用于指明容器创建或配置的数据存储区域或创建的文件或目录所在路径。推荐使用。
WORKDIR
应该使用绝对路径,而不是繁琐的RUN cd .... && do-someting
。
ADD 或 COPY
这两个命令在功能上类似,推荐使用COPY
,COPY
只能将本地文件复制到容器中;ADD
额外支持可以将本地的tar
提交到镜像中,或添加远程URL
的文件。尽量不是使用ADD
命令从远程URL获取软件包,应该使用curl
或wget
代替。
不好的例子:
ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all推荐的例子:
RUN mkdir -p /usr/src/things
&& curl -SL http://example.com/big.tar.xz
| tar -xJC /usr/src/things
&& make -C /usr/src/things all
Dockerfile示例
centos-jdk镜像
- 编辑 Dockerfile 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#基础镜像
FROM centos:latest
#作者
MAINTAINER gxing gxing@163.com
#在镜像中创建目录
RUN mkdir -p /usr/local/jdk1.8
#在镜像中创建工作目录
RUN mkdir -p /work
#指定工作目录
WORKDIR /work
#复制目录
COPY jdk1.8.0_172 /usr/local/jdk1.8
#设置环境变量
ENV JAVA_HOME="/usr/local/jdk1.8"
ENV CLASSPATH=".:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar"
ENV PATH="$JAVA_HOME/bin:$PATH"
EXPOSE 80
EXPOSE 8080 - 执行构建包含jdk的镜像
$ docker build -t repos_local/centos-jdk1.8:1.0 .
说明:-t
设置 tag 命,通常规则定义是 库/镜像名:tag,tag一般用于表示版本,.
表示当前目录下的 Dockerfile 文件。
Docker系列(四):Dockerfile 配置详解