Dockerfile详解
Dockerfile是一个组合映像命令的文本,Docker通过dockerfile中的指令自动生成镜像。
编写规则
- 文件名必须是
Dockerfile Dockerfile中所用的所有文件一定要和Dockerfile文件在同一级父目录下Dockerfile中相对路径默认都是Dockerfile所在的目录Dockerfile中一能写到一行的指令,一定要写到一行,因为每条指令都被视为一层,层多了执行效率就慢Dockerfile中指令大小写不敏感,但指令都用大写(约定俗成)Dockerfile非注释行第一行必须是FROMDockerfile工作空间目录下支持隐藏文件(.dockeringore),类似于git的.gitingore
指令详解
FROM # 基础镜像,一切从这里开始构建
MINTAINER # 镜像是谁写的,姓名+邮箱
LABEL # 现在推荐写 LABEL,代替上面的那个
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤:如果要加一个tomcat镜像,就是加这个tomcat压缩包!1、添加内容 2、添加同目录
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留的端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承的DockerFile 时,这时就会运行ONBUILD的指令,触发别的指令。
COPY # 类似ADD,将我们的文件拷贝到镜像中
ENV # 构建的时候设置环境变量
FROM:基础镜像
FROM <image>:<tag> [as other_name] # tag可选;不写默认是latest版
FROM是Dockerfile文件开篇第一个非注释行代码- 用于为镜像文件构建过程指定基础镜像,后续的指令都基于该基础镜像环境运行
- 基础镜像可以是任何一个镜像文件
as other_name是可选的,通常用于多阶段构建(有利于减少镜像大小)- 使用是通过
--from other_name使用,例如COPY --from other_name
LABEL:镜像描述信息
LABEL author="RobertChao<xxxxxxxxxx@qq.com>"
LABEL describe="create test image"
# 或
LABEL author="RobertChao<xxxxxxxxxx@qq.com>" describe="create test image"
# 或
LABEL author="RobertChao<xxxxxxxxxx@qq.com>" \
describe="create test image"
LABEL指令用来给镜像以键值对的形式添加一些元数据信息- 可以替代
MAINTAINER指令 - 会集成基础镜像中的
LABEL,key相同会被覆盖
MAINTAINER:添加作者信息
MAINTAINER RobertChao<xxxxxxxxxx@qq.com>
COPY:从构建主机复制文件到镜像中
COPY <src> <dest>
COPY ["<src>", "<src>", ... "<dest>"]
<src>:要复制的源文件或目录,支持通配符<src>必须在build所在路径或子路径下,不能是其父目录
<src>是目录。其内部的文件和子目录都会递归复制,但目录本身不会被复制
- 如果指定了多个
<src>或使用了通配符,这<dest>必须是一个目录,且必须以/结尾
<dest>:目标路径,即镜像中文件系统的路径<dest>如果不存在会自动创建,包含其父目录路径也会被创建
ADD:从构建宿主机复制文件到镜像中
ADD <src> <dest>
ADD ["<src>","<src>"... "<dest>"]
<src>如果是一个压缩文件(tar),被解压为一个目录,通过URL下载一个文件不会被解压。
<src>如果是多个,或使用了通配符,则<dest>必须是以/结尾的目录,否则<src>会被作为一个普通文件,<src>的内容将被写入到<dest>
WORKDIR:设置工作目录
WORKDIR /opt
- 使用上类似于
cd命令,进入到opt文件目录。之后执行的所有操作命令都在当前目录中进行。 - 目录不存在会自动创建
- 一个
Dockerfile中WORKDIR可以出现多次,其路径也可以为相对路径,相对路径是基于前一个WORKDIR路径
ENV:设置镜像中的环境变量
# 一次设置一个
ENV <key> <value>
# 一次设置多个
ENV <key>=<value> <key1>=<value1> <key2>=<value2> .....
- 和
linux系统中使用环境变量的方式是一样的
echo $varname
echo ${varname}
echo ${varname:-default value} # 设置一个默认值,如果varname未被设置,值为默认值
echo ${varname:+default value} # 设置默认值;不管值存不存在都使用默认值
USER:设置启动容器的用户
# 使用用户名
USER testuser
# 使用用户的UID
USER UID
RUN:镜像构建时执行的命令
# 语法1,shell 形式
RUN command1 && command2
# 语法2,exec 形式
RUN ["executable","param1","[aram2]"]
# 示例
RUN echo 1 && echo 2
RUN echo 1 && echo 2 \
echo 3 && echo 4
RUN ["/bin/bash","-c","echo hello world"]
-
RUN在下一次建构期间,会优先查找本地缓存,若不想使用缓存可以通过--no-cache解除docker build --no-cache
-
RUN指令指定的命令是否可以执行取决于基础镜像-
shell形式
- 默认使用
/bin/sh -c执行后面的command
- 可以使用
&&或 `` 连接多个命令
- 默认使用
-
exec形式
- exec形式被解析为JSON序列,这意味着必须使用双引号
""
- 与 shell 形式不同,exec 形式不会调用shell解析。但exec形式可以运行在不包含shell命令的基础镜像中
- 例如:
RUN ["echo","$HOME"];指令$HOME并不会被解析,必须RUN ["/bin/sh","-c","echo $HOME"]
- exec形式被解析为JSON序列,这意味着必须使用双引号
-
EXPOSE:为容器打开指定的监听端口以实现与外部通信
EXPOSE <port>/<protocol>
EXPOSE 80
EXPOSE 80/http
EXPOSE 2379/tcp
<port>:端口号<protocol>:协议类型,默认TCP协议,tcp/udp/http/httpsdocker run -p 80:2379
VOLUME:实现挂载功能,将宿主机目录挂载到容器中
VOLUME ["/data"] # [“/data”]可以是一个JsonArray ,也可以是多个值
VOLUME /var/log
VOLUME /var/log /opt
docker run -v /suzhuji /jingxiang
CMD:为容器设置默认启动命令或参数
# 语法1,shell形式
CMD command param1 param2 ...
# 语法2,exec形式
CMD ["executable","param1","param2"]
# 语法3,还是exec形式,不过仅设置参数
CMD ["param1","param2"]
CMD运行结束后容器将终止,CMD可以被docker run后面的命令覆盖
- 一个
Dockerfile只有顺序向下的最后一个CMD生效
语法1,shell形式,默认/bin/sh -c
- 此时运行为shell的子进程,能使用shell的操作符(
if、环境变量、? *通配符等) - 注意: 进程在容器中的 PID != 1,这意味着该进程并不能接受到外部传入的停止信号
docker stop
语法2,exec形式CMD ["executable","param1","param2"]
- 不会以
/bin/sh -c运行(非shell子进程),因此不支持shell的操作符 - 若运行的命令依赖shell特性,可以手动启动
CMD ["/bin/sh","-c","executable","param1"...]
语法3,exec形式CMD ["param1","param2"]
- 一般结合ENTRYPOINT指令使用
ENTRYPOINT:用于为容器指定默认运行程序或命令
# 语法1,shell形式
ENTRYPOINT command
# 语法2,exec形式
ENTRYPOINT ["/bin/bash","param1","param2"]
- 主要用于指定启动的父进程
ENTRYPOINT设置默认命令不会被docker run命令行指定的参数覆盖,指定的命令行会被当做参数传递给ENTRYPOINT指定的程序。docker run命令的--entrypoint选项可以覆盖ENTRYPOINT指令指定的程序- 一个Dockerfile中可以有多个
ENTRYPOINT,但只有最后一个生效 ENTRYPOINT主要用于启动父进程,后面跟的参数被当做子进程来启动
ARG:指定环境变量用于构建过程
ARG name[=default value]
ARG arg_name
ARG arg1_name=robert
-
ARG指令定义的参数,在构建过程以docker build --build-arg arg_name=robert形式赋值 -
若
ARG中没有设置默认值,构建时将抛出警告:[Warning] One or more build-args..were not consumed -
Docker默认存在的ARG参数,可以在--build-arg时直接使用HTTP_PROXY/http_proxy/HTTPS_PROXY/https_proxy/FTP_PROXY/ftp_proxy/NO_PROXY/no_proxy
ONBUILD:为镜像添加触发器
ONBUILD <dockerfile_exec> <param1> <param2>
ONBUILD RUN mkdir mydir
- 对于使用
Dockerfile构建的镜像并不会生效,只有当其他Dockerfile以当前镜像作为基础镜像时被触发 - 例如:
Dockfile A构建了镜像A,Dockfile B中设置FROM A,此时构建镜像B是会运行ONBUILD设置的指令
STOPSINGAL:设置停止时要发送给PID=1进程的信号
STOPSIGNAL signal
- 默认的停止信号为:
SIGTERM,也可以通过docker run -s指定 - 主要目的是为了让容器内的应用程序在接收到
signal之后可以先做一些事情,实现容器的平滑退出,如果不做任何处理,容器将在一段时间之后强制退出,会造成业务的强制中断,时间默认是10s。
HEALTHCHECK:指定容器健康检查命令
HEALTHCHECK [OPTIONS] CMD command
# 示例
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1 # 如果执行不成功返回1
-
出现多次,只有最后一次生效
-
OPTIONS选项--interval=30:两次健康检查的间隔,默认为 30 秒;--timeout=30:健康检查命令运行的超时时间,超过视为失败,默认30秒;--retries=3:指定失败多少次视为unhealth,默认3次
-
返回值
0:成功;1:失败;2:保留
创建镜像
Dockerfile需要一个基础镜像,取决于第一行的FROM
FROM scratch:表示使用一个空镜像镜像
centos:alpine
# 基础镜像
FROM centos:alpine
LABEL author="RobertChao<xxxxxxxxxx@qq.com>" describe="create test image"
# 添加 JDK 与 TOMCAT8 到指定文件路径
ADD jdk8.tar.gz /usr/local
ADD tomcat8 /usr/local
# ENV 设置环境变量
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV JAVA_HOME /usr/local/jdk8
ENV CATALINA_HOME /usr/local/tomcat8
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
# EXPOSE 映射端口
EXPOSE 8080
# 容器启动时执行命令
CMD ["/usr/local/tomcat8/bin/catalina.sh", "run"]