英语好的同学可以去docker官网看dockerfile的官方文档,很详细:Dockerfile reference
一、为什么要用Dockerfile
其实在搭建完环境后,docker有一个命令可以直接将容器做成镜像:docker commit [OPTIONS] CONTAINERID [REPOSITORY[:TAG]]
很简单,就一条命令直接完成。为什么还要用Dockerfile来做镜像?Dockerfile的出现是有原因的。先讲一下这两种制作镜像的方法的区别:
a.docker commit : ①需要在docker容器内操作,很麻烦,效率低;②搭好环境直接将容器做成镜像后,其他人使用这个镜像的时候,不知道这个镜像是怎么做出来的,都安装了什么,后面环境的继续搭建和维护很困难,如果不写说明文档,那么这个镜像基本上就只有作者自己知道怎么用了;③这个命令一般都使用在基础镜像的制作和镜像的发布上。
b.docker build . (Dockerfile) : ① 仅需编辑Dockerfile文件,不用进入容器内就可以配置环境,可读性比较强;②后续的升级和维护相对简单,可以直接在Dockerfile中更改并增加特性;③一般在团队,或者个人环境搭建中。
具体选择哪种制作方式来制作镜像需要结合实际情况选择。
二、Dockerfile的使用
Docker通过读取Dockerfile文件,可以自动创建镜像。在大多数情况下,最好将Dockerfile单独放到一个文件夹中,一般包括Dockerfile文件、构建镜像所需要的文件、.dockerignore文件(里面存放构建镜像不需要的额文件)。Docker Daemon将一步步执行你的指令,创建成功后,将会输出新的镜像的ID;在Docker守护进程运行Dockerfile中的指令之前,它会对Dockerfile进行初步验证,如果语法不正确,则返回一个错误。
指定一个私有仓库和tag,以保存构建成功后的镜像,多个-t可以上传多个仓库: docker build -t XXX/xxx . ;
指定路径的Dockerfile制作镜像:docker build -f /path/to/a/Dockerfile .;
三、Dokerfile的命令
命令不区分大小写,大写只是为了区分命令和变量。命令行和注释符(#)不能在同一行
1.#syntax= [remote image reference]
指定解析器 ,只能在第一行,否则不生效,如:
# syntax=docker/dockerfile # syntax=docker/dockerfile:1.0 # syntax=docker.io/docker/dockerfile:1 # syntax=docker/dockerfile:1.0.0-experimental # syntax=example.com/user/repo:tag@sha256:abcdef...
2.#escape= (backslash) /
#escape=` (backslash)
指定转义符号 ,通常在将转义字符设置为'在Windows上特别有用,其中是目录路径分隔符。
3..dockerignore
文件:
# comment */temp* */*/temp* temp?
规则 | 功能 |
# comment
|
注释被忽略。 |
*/temp* |
排除名称以temp开头的文件和目录在根目录的任何直接子目录中。例如,排除了普通文件/somedir/temporary.txt,以及/somedir/temp目录。 |
*/*/temp* |
从根目录下两层的任何子目录中排除以temp开头的文件和目录。例如,/somedir/subdir/temporary.txt被排除在外。 |
temp? |
排除根目录中名称为temp的单字符扩展名的文件和目录。例如,排除/tempa和/tempb。 |
4. FROM [--platform=<platform>] <image> [AS <name>] /
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>] /
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
FROM指令初始化一个新的基础镜像。因此,一个有效的Dockerfile必须以FROM指令开始。镜像可以是任何镜像,公共基础镜像pull下来很容易。
5.ENV
FROM busybox ENV foo /bar WORKDIR ${foo} # WORKDIR /bar ADD . $foo # ADD . /bar COPY $foo /quux # COPY $foo /quux
6.RUN <command>
(shell form, the command is run in a shell, which by default is /bin/sh -c
on Linux or cmd /S /C
on Windows)
RUN ["executable", "param1", "param2"]
(exec form)
exec form和shell form不同,exec form不调用命令shell,这就意味着不会发生正常的shell处理,如RUN ["echo", "$HOME"]不会对$HOME执行变量替换。如果想要shell处理,那么要么使用shell form,要么直接执行shell,例如:exec form运行["sh", "-c", "echo $HOME"]。RUN命令适用于在 docker build 构建docker镜像时执行的命令。
注意“”的转义:RUN ["c:\windows\system32\tasklist.exe"]
7. CMD ["executable","param1","param2"]
(exec form, this is the preferred form)
CMD ["param1","param2"]
(as default parameters to ENTRYPOINT)
CMD command param1 param2
(shell form)
CMD的主要用途是为执行容器提供默认值。这些缺省值可以包括可执行文件,也可以省略可执行文件,在这种情况下,您还必须指定一个ENTRYPOINT。如果希望容器每次都运行相同的可执行文件,那么应该考虑将ENTRYPOINT与CMD结合使用。Dockerfile中的CMD命令最终可以被在执行 docker run命令时添加的命令所覆盖。
8.ENTRYPOINT ["executable", "param1", "param2"]
(exec form, preferred)
ENTRYPOINT command param1 param2
(shell form)
使用ENYRYPOINT,可以在运行容器的时候执行该命令。在将容器用作可执行文件时,应该定义ENTRYPOINT。在一个Dockerfile
中只有最后一个ENTRYPOINT
指令是有效的。CMD应该用作定义ENTRYPOINT命令的默认参数或在容器中执行特别命令的方法,当运行带有可选参数的容器时,CMD将被覆盖。
这里推荐要使用exec form的格式,官方上说是这样运行容器,退出是彻底退出,而使用shell form是被迫退出。
9.VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME /var/log /var/db
宿主主机的文件挂载到指定容器的文件中,如果不指定宿主主机文件,Docker将自动创建一个匿名的volume,并将其挂载到cotainer的/var/log目录,匿名vilume在host机器上的目录路径类似:/var/lib/docker/volumes/300c2264cd0acfe862507eedf156eb61c197720f69e7e9a053c87c2182b2e7d8/_data
10.USER <user>[:<group>] or
USER <UID>[:<GID>]
用来设置在Dockerfile中要使用的宿主主机的用户名或者UID
11.WORKDIR /path/to/workdir
在Dockerfile中声明工作路径,此目录如果不存在就会被自动创建,即使这个目录不被使用,接下来的操作都是基于这个路径工作的。可以在 docker run命令中用 -w参数覆盖掉WORKDIR指令的设置。
12.ARG <name>[=<default value>]
构建镜像时将命令行的参数值传递到Dockerfile文件中,如下Dockerfile文件:
1 FROM busybox 2 USER ${user:-some_user} 3 ARG user 4 USER $user
构建镜像命令:$ docker build --build-arg user=what_user .
此时Dockerfile的文件中USER的值为what_user。
13.SHELL ["executable", "parameters"]
指定shell的环境,例如:
FROM microsoft/windowsservercore # Executed as cmd /S /C echo default RUN echo default # Executed as cmd /S /C powershell -command Write-Host default RUN powershell -command Write-Host default # Executed as powershell -command Write-Host hello SHELL ["powershell", "-command"] RUN Write-Host hello # Executed as cmd /S /C echo hello SHELL ["cmd", "/S", "/C"] RUN echo hello
14.HEALTHCHECK [OPTIONS] CMD command
(check container health by running a command inside the container)
HEALTHCHECK NONE
(disable any healthcheck inherited from the base image)
健康检查,例如,每隔5分钟左右检查一次,使web服务器能够在3秒钟内为站点的主页提供服务:
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
15.ONBUILD [INSTRUCTION]
ONBUILD在此次镜像制作时不发挥作用,当这次做成的镜像被其他镜像当成基础镜像,是就会触发ONBUILD命令,但是这种ONBUILD命令不会被继承。例如:
[...] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
16.COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"](this form is required for paths containing whitespace)
拷贝宿主主机的文件到镜像中
17.ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
(this form is required for paths containing whitespace)
向镜像中拷贝文件,源文件可以是url链接文件
18.EXPOSE <port> [<port>/<protocol>...]
声明向外暴露的网络端口
19.MAINTAINER <name>
维护者信息
20.LABEL <key>=<value> <key>=<value> <key>=<value> ...
向镜像中添加元数据,其实就是添加镜像的相关信息,只是以键值对的形式创建。