Docker学习之Dockerfile书写

Docker学习之Dockerfile书写

十二月 20, 2019

Dockerfile的定义

Dockerfile是一个包含用于组合映像的命令的文本文档, 
Docker通过读取Dockerfile中的指令自动生成映像。
构建镜像时使用docker build命令构建,
可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile。

Dockerfile文件说明

基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令
`#` 为Dockerfile的注释

为了指定基本映像,第一条指令必须是FROM。一个声明以#字符开头
则被视为注释。可以在Docker文件中使用RUN,CMD,FROM,EXPOSE,
ENV等指令.

Dockerfile指令

1
2
3
4
5
FROM: 
指定基础镜像,第一个命令必填.

e.g
FROM mysql:8.0
1
2
3
4
5
6
7
8
9
10
11
LABEL:
添加标签,帮助组织镜像、记录许可信息、辅助自动化构建等

e.g
LABEL com.example.version="0.0.1-beta"

LABEL vendor="ACME Incorporated"

LABEL com.example.release-date="2019-12-20"

LABEL com.example.version.is-production=""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
RUN:
用于在镜像容器中执行命令
有以下两种命令执行方式:
shell执行:
RUN <command>
e.g RUN ls /

exec执行:
RUN ["executable", "param1", "param2"]

e.g
RUN apk update
RUN ["/etc/execfile", "arg1", "arg1"]


注意:
RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。
如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,
如:docker build --no-cache
此外,不要使用 RUN apt-get(yum) upgrade 或 dist-upgrade,
因为许多基础镜像中的「必须」包不会在一个非特权容器中升级。
如果基础镜像中的某个包过时了,你应该联系它的维护者。
1
2
3
4
5
6
7
8
9
CMD:
用于执行目标镜像中包含的软件,可以包含参数
构建容器后调用,也就是在容器启动时才进行调用
格式: CMD ["executable", "param1", "param2"...]
e.g
CMD ["apache2", "-DFOREGROUND"]

多数情况下,CMD 都需要一个交互式的 shell (bash, Python, perl 等)
如 CMD ["PHP", "-a"]
1
2
3
4
EXPOSE:
指定于外界交互的端口

格式: EXPOSE 8080
1
2
3
4
5
6
7
ENV:
设置环境变量
为容器中安装的程序更新 PATH 环境变量

e.g
ENV JAVA_HOME /usr/local/java/jdk1.8
ENV PATH /usr/local/nginx/bin:$PATH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ADD 和 COPY :
ADD 和 COPY 功能类似,一般优先使用 COPY,它比 ADD 更透明
COPY 只支持简单将本地文件拷贝到容器中
ADD 有一些并不明显的功能(比如本地 tar 提取和远程 URL 支持)
ADD 的最佳用例是将本地 tar 文件自动提取到镜像中 (ADD rootfs.tar.xz)

如果Dockerfile中有多个步骤需要使用上下文中不同的文件。
单独COPY每个文件,而不是一次性的COPY所有文件,
这将保证每个步骤的构建缓存只在特定的文件变化时失效

为了让镜像尽量小,最好不要使用 ADD 指令从远程 URL 获取包,
而是使用 curl 和 wget
这样你可以在文件提取完之后删掉不再需要的文件来避免在镜像中额外添加一层

最好使用如下写法:
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

(上面使用的管道操作,所以没有中间文件需要删除,即不需要额外删除big.tar.xz。)

而不是
ADD http://example.com/big.tar.xz /usr/src/things/

对于其他不需要 ADD 的自动提取功能的文件或目录,你应该使用 COPY。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ENTRYPOINT:
配置容器,使其可执行化
ENTRYPOINT 的最佳用处是设置镜像的主命令,允许将镜像当成命令本身来运行
e.g:
ENTRYPOINT ["demo"]
CMD ["--help"]
docker run demo

ENTRYPOINT 指令也可以结合一个辅助脚本使用,和命令行风格类似
e.g
脚本被拷贝到容器,并在容器启动时通过 ENTRYPOINT 执行:
COPY ./demo.sh /
ENTRYPOINT ["/demo.sh"]
该脚本可以让用户用几种不同的方式和应用交互
1. 简单地启动 (docker run app)
2. 传递参数 (docker run app app --help)
3. 启动其他工具 (docker run --rm -it app bash)
1
2
3
4
5
VOLUME 指令用于暴露任何数据库存储文件,
配置文件,或容器创建的文件和目录

格式:
VOLUME ["/path/to/dir"]
1
2
3
4
5
6
7
8
9
10
11
12
13
USER:
指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户
使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合
当服务不需要管理员权限时,可以通过该命令指定运行用户,
并且可以在之前创建所需要的用户

格式:
  USER user
  USER user:group
  USER uid
  USER uid:gid
  USER user:gid
  USER uid:group
1
2
3
4
5
6
7
8
9
WORKDIR:
工作目录,类似于cd命令

格式:
WORKDIR /path/to/workdir

通过WORKDIR设置工作目录后,
Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令
都会在该目录下执行在使用docker run运行容器时 可以通过-w参数覆盖构建时所设置的工作目录。