闲话不多说,dokerfile常用指令解析奉上
FROM
作用:指定基础镜像,必须放在DOckerfile的第一行,表示从哪个baseimage开始构建
格式:
FROM :[tag]
FROM @
MAINTAINER
作用:指定作者信息,该指令已被废弃但是目前还可以使用,可以用LABEL指令代替。
格式:
MAINTAINER
eg.
MAINTANER "cx55887 "
LABEL
作用:设定一些添加镜像的元数据,LABEL是一对key-value值
格式:
LABEL = = = ...
eg.
LABEL version="2.1"
LABEL creator="cx55887"
镜像可以有多个LABEL,来指定多个标签,Docker建议在可能的情况下将 标签组合到单个LABEL指令中,
因为每一个LABEL指令都会产生一个新的层,而层数越多就会导致执行花费时间越长。
LABEL version="2.1" \
creator="cx55887" \
other="value"
LABEL中如果key已存在,后面添加相同的key那么新的value会覆盖掉前面的。
COPY
作用:将工作目录下的文件复制到所做的镜像中的文件系统中
格式:
COPY [--chown=:] <源路径>... <目标路径>
COPY [--chown=:] ["<源路径1>",... "<目标路径>"]
COPY --chown=cx55887:cx55887 files* /mydir/
COPY --chown=cx55887 files* /mydir/
COPY --chown=1 files* /mydir/
COPY --chown=10:11 files* /mydir/
ADD
作用:和COPY类似,可以实现将文件和目录复制到镜像中,但是区别是可以实现:
如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
如果<源路径>是一个URL,Docker引擎会去下载这个链接的文件放到<目标路径>,下载后文件的权限自动设置为600。注意:下载的tar包不会自动解压
格式:
ADD [--chown=:] <源路径>... <目标路径>
ADD [--chown=:] ["<源路径1>",... "<目标路径>"]
使用ADD指令的时候也可以通过--chown=
选项廖改变文件的属主和属组
ADD --chown=cx55887:cx55887 files* /mydir/
ADD --chown=cx55887 files* /mydir/
ADD --chown=1 files* /mydir/
ADD --chown=10:11 files* /mydir/
WORKDIR
作用:设置镜像中的工作目录,相当于cd命令
格式:
WORKDIR <工作目录路径>
VOLUME
作用:指定数据卷的挂载点,若不存在会自动创建
格式:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
eg.
VOLUME /data
这样/data目录就会在运行的自动挂载,任何向/data写入的信息都不会记录进容器储存层,从而保证容器储存层的无状态化,当然运行时可以覆盖掉这个挂载设置:
docker run -d -v mydata:/data xxxx
在这条命令中,就使用了mydata 这个命名卷改在到了/data这个位置,替代了 Dockerfile中定义的匿名卷的挂在配置
EXPOSE
作用:告诉 Docker 服务端 容器对外映射的本地端口。
格式:
EXPOSE <端口1> [<端口2>...]
EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在dockerfile中声名有两个好处:
docker run -P
时,会随机映射EXPOSE
中声明的端口。EXPOSE
和在运行时使用-p <宿主端口>:<容器端口>
区分开,-p
是映射宿主端口和容器端口,也就是说将容器的对应端口服务公开给外界访问,而EXPOSE
仅仅是声名容器打算使用那些端口而已,并不会自动在宿主机进行端口映射ENV
作用:设置环境变量
格式:
ENV
ENV = = ...
eg.
ENV VERSION=1.0 DEBUG=no \
NAME="cx baby"
通过ENV所定义的变量是可以传递到容器之中,但是,在创建容器的时候,如果手动指定了变量的值,那么这个值会覆盖掉镜像中原有的值
RUN
作用:RUN指令会在当前镜像的基础上指定命令,并提交为新镜像
格式:
RUN
RUN ["executable","param1","param2"]
前者将在shell终端中运行命令,即/bin/sh -c
;后者则使用exec执行。指定使用其它终端可以通过第二种方式实现,例如RUN ["/bin/bash", "-c", "echo hello"]
。
CMD
作用:定义容器启动以后要默认运行的程序,即pid为1的程序
格式:
shell 格式:CMD <命令>
exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
参数列表格式:CMD ["参数1", "参数2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
我们知道Docker不同于虚拟机,容器就是进程,既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD指令就是指定容器主进程启动命令的。
在运行的时候可以指定新的命令来替代镜像设置中的这个默认命令,比如ubuntu镜像的默认的CMD是/bin/bsah,如果我们直接docker run -it ubuntu的话,会进入bash 。我们也可以在运行时指定运行别的命令,如 docker run ubuntu cat /etc/os-release。这就是用 cat /etc/os-release 命令替换了默认的/bin/bash 命令输出了系统版本信息。
在指令格式上,推荐使用exec格式,这类格式在解析是会被解析成JOSN数组,因此一定要使用双引号,而不要使用单引号。
如果使用 shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行执行。比如:
CMD echo $NAME
在实际执行中,会将其变更为:
CMD [ "sh" ,"-c", "echo $NAME"]
这就是为什么我们可以使用环境变量的原因,因为这些环境变量会被 shell 进行解析处理。
提到 CMD 就不得不提容器中应用在前台执行和后台执行的问题。这是初学者常出现的一个混淆。
Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 upstart/systemd 去启动后台服务,容器内没有后台服务的概念。
一些初学者将CMD写为:
CMD server nginx start
然后发现容器执行后就立即退出了。甚至在容器内去使用 systemctl 命令结果却发现根本执行不了。这就是因为没有搞明白前台、后台的概念,没有区分容器和虚拟机的差异,依旧在以传统虚拟机的角度去理解容器。
对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。
而使用 service nginx start 命令,则是希望 upstart 来以后台守护进程形式启动 nginx 服务。而刚才说了 CMD service nginx start 会被理解为 CMD [ “sh”, “-c”, “service nginx start”],因此主进程实际上是 sh。那么当 service nginx start 命令结束后,sh 也就结束了,sh 作为主进程退出了,自然就会令容器退出。
正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。比如:
CMD [“nginx”, “-g”, “daemon off;”]
ENTRYPOINT
作用:ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数
格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2(shell中执行)
ARG
作用:定义在构建镜像时候所使用的变量,在将来容器运行时是不会存在这些环境变量的。
格式:
ARG <参数名>[=<默认值>]
Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。
USER
作用:定义容器中的进程以哪个用户的身份运行
格式:
USER <用户名>[:<用户组>]
该用户必须存在于容器的用户空间中(容器的文件系统的中的/etc/passwd中)
HEALTHCHECK
作用:HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常
格式:
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为 starting,在 HEALTHCHECK 指令检查成功后变为 healthy,如果连续一定次数失败,则会变为 unhealthy。命令的返回值决定了该次健康检查的成功与否:0:成功;1:失败;2:保留,不要使用这个值。
HEALTHCHECK 支持下列选项:
--interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
--timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
--retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。
ONBULID
作用:定义一个触发器,用来实现当基于这个这个镜像做新镜像的时候要执行的命令
格式:
ONBUILD <其它指令>
ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
------做运维之前很矫情的小年轻-----