Loading

6-Dockerfile常用指令

Dockerfile

Docker可以通过阅读Dockerfile来自动构建镜像,Dockerfile是一个文本文档,其中包含用户可以在命令行上调用的所有命令,使用docker build可以自动创建镜像。

Dockerfile的基本结构

Dockerfile一般分为4个部分:基础镜像信息、维护者信息、镜像操作指令、容器启动时指令

2、Dockerfile格式

# Comment
INSTUCTION arguments

说明:

  • Dockerfile指令不区分大小写,不过官方约定为大写,便于和参数区分

  • Dockfile文件名首字母必须大写。

  • Dockerfile按照顺序运行指令,Dockerfile中的所有shell命令都应是容器中支持的命令。

  • 开头表示为注释行

  • Dockerfile的第一个非注释行必须用FROM指令启动,指定要从哪里构建基础镜像。

  • 基于Dockerfile做镜像,且需要引用本地文件,工作目录必须为Dockerfile当前目录的子目录或者子目录中的内容。

  • .dockerignore文件

    • build时忽略.dockerignore文件中的文件
    # comment
    */temp*
    */*/temp*
    temp?
    

    此文件将发生以下行为:

    规则 行为
    # comment 忽略。
    */temp* 排除名称以temp根的任何直接子目录开头的文件和目录。例如,/somedir/temporary.txt排除纯文件,排除目录/somedir/temp
    */*/temp* 排除temp从根以下两个级别的任何子目录开始的文件和目录。例如,/somedir/subdir/temporary.txt被排除。
    temp? 排除根目录中名称为的一个字符扩展名的文件和目录temp。例如,/tempa/tempb被排除。

3、Dockerfile指令介绍

3.1、FROM

  • FROM指令用于为镜像文件构建过程中指定基准镜像,后续的指令运行基于此镜像所提供的运行环境。
  • 实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build会从docker主机上查找镜像文件,如不存在,则会从docker hub仓库上拉取
# Description: test image
FROM busybox:latest             

3.2、MAINTANIER、LABEL

  • 用于让Dockerfile制作者提供本人的详细信息

  • MAINTAIER指令已经被放弃,可使用LABEL

  • LABEL语法

    • syntax:LABEL =
    • 可以把MAINTAIER作为LABEL的一个键值
    # Description: test image
    FROM busybox:latest
    MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
    LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"
    

3.3、COPY

  • 用于从Docker主机复制文件至创建的新镜像文件
  • 语法:
    • COPY ...
    • COPY ["",...""]
      • : 要复制的源文件或者目录,支持通配符
      • :目标路径,既正在创建的image的文件系统路径,建议为绝对路径,否者COPY指令以WORKDIR为起始路径
      • 在路径中有空白字符时,通常使用第二种格式。
  • 文件复制准则
    • 必须是build上下文中的路径,不能是其父目录中的文件
    • 如果是目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制。
    • 如果指定了多个,或在中使用了通配符,则必须是一个目录,且必须以/结尾
    • 如果不存在,则会被自动创建,包括其父目录路径
# Description: test image
FROM busybox:latest
MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"
COPY ./sendEmail.py /data/app/
  • 基于Dockerfile创建镜像

    [root@localhost ~]# docker build  ./ -t busyhttpd:v0.1
    # 基于创建的镜像启动容器,验证
    [root@localhost ~]# docker run --name busyweb01 --rm busyhttpd:v0.1 ls /data/app/
    sendEmail.py
    

    可以看到文件已经copy至容器中。

3.4、ADD

  • ADD指令类似于COPY指令,ADD支持使用tar文件和url路径
  • 语法
    • ADD ...
    • ADD ["",...""]
  • 操作准则
    • 同COPY指令
    • 如果为URL且不以/结尾,则指定的文件将被下载并直接创建为,如果以/结尾,则文件名URL指定的文件将被直接下载并保存为/
    • 如果是一个本地系统上的压缩格式的tar文件,将被直接展开为一个目录,类似于tar -xf命令,但如果通过URL上获取的tar文件则不会自动展开
    • 如果有多个,间接或直接使用了通配符,则必须是一个以/结尾的目录路径
# Description: test image
FROM busybox:latest
MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"
COPY ./sendEmail.py /data/app/
# 会在build时下载并复制到容器中,但不会解压。
ADD http://nginx.org/download/nginx-1.16.1.tar.gz /data/app/nginx/
# 如果src在本地存在,则复制后会直接解压
ADD ./nginx-1.16.1.tar.gz /data/app/nginx/

3.5、WORKDIR

  • 用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD设定工作目录

  • 语法:

    • WORKDIR
      • 在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,为相对此前的一个WORKDIR指令指定的路径
      • 也可以调用由ENV定义的变量
    # Description: test image
    FROM busybox:latest
    MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
    LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"
    WORKDIR /data/app/ # 指定工作目录
    ADD nginx-1.16.1.tar.gz ./ # dest只需使用./即可
    

3.6、VOLUME

  • 用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其他容器上的卷
  • 语法:
    • VOLUME
    • VOLUME [""]
  • 注意
    • 如果挂载点目录路径下此前有文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中。
    • Dockerfile中只能使用Docker-managed volume类型,不可直接指定宿主机上的目录。
# Description: test image
FROM busybox:latest
MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"
WORKDIR /data/app/
ADD nginx-1.16.1.tar.gz ./
VOLUME /data/mysql/  # 指定容器挂载路径,但不可指定宿主机的目录

3.7、EXPOSE

  • 用于为容器打开指定要监听的端口以实现与外部通信。
  • 语法:
    • EXPOSE [/] [ [/]...]
      • 用于指定传输层协议,可为tcp或者udp二者之一,默认为tcp协议
    • EXPOSE指令可一次指定多个端口,例如:
      • EXPOSE 11211/udp 11211/tcp
  • 注意
    • EXPOSE并不会直接暴露端口让容器端口访问到主机,要使其可以访问,需要在docker run运行容器时通过-p发布这些端口,或者通过-P端口发布EXPOSE到处的所有端口。
# Description: test image
FROM busybox:latest
MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"
WORKDIR /data/app/
COPY ./index.html /data/app/www/
ADD nginx-1.16.1.tar.gz ./
VOLUME /data/mysql/

EXPOSE 80/tcp  # 暴露80端口

上面的Dockerfile默认创建容器后并不会直接暴露端口到宿主机

[root@localhost images]# docker build  ./ -t busyhttpd:v0.8
[root@localhost ~]# docker run --name busyweb01 --rm busyhttpd:v0.8 /bin/httpd -f -h /data/app/www
[root@localhost images]# docker port busyweb01    # 可以看到端口为空
[root@localhost images]# 

可以使用-P选项来发布端口

[root@localhost ~]# docker run -P --name busyweb01 --rm busyhttpd:v0.8 /bin/httpd -f -h /data/app/www    
[root@localhost images]# docker port busyweb01
80/tcp -> 0.0.0.0:32768

同时也可以在run的时候-p暴露其他端口

3.8、ENV

  • 用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其他指令(如ENV、ADD、COPY等)所调用
  • 调用格式为$variable_name或$
  • 语法:
    • ENV
    • ENV = ...
  • 注意:
    • 第一种格式,之后的所有内容均会被视作其的组成部分,因此,一次只能设置一个变量。
    • 第二种格式可用一次设置多个变量
# Description: test image
FROM busybox:latest
MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"

ENV DOCKER_ROOT /data/app/www/  # 指定ENV变量
ENV DOCKER_ROOT=/data/app/www/ \
    WEB_PACKAGE="nginx-1.16.1"

WORKDIR /data/app/
COPY ./index.html ${DOCKER_ROOT:-/data/web/html/}  # 引用
ADD ${WEB_PACKAGE}.tar.gz ./
VOLUME /data/mysql/

EXPOSE 80/tcp

同时也支持在docker run时传参。

[root@localhost ~]# docker run -P --name busyweb01 -e WEB_PACKAGE='nginx-1.15.1' --rm busyhttpd:v0.9 printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=ad48e338ff35
WEB_PACKAGE=nginx-1.15.1  # 传入的变量,但此变量只在docker run中改变,镜像中的变量还是使用dockerfile中的。
DOCKER_ROOT=/data/app/www/
HOME=/root

3.9、RUN

  • 用于在构建镜像容器中执行命令
  • 语法
    • RUN
    • RUN [""," ", ""]
    • 第一种格式中,通常是一个shell命令,且会以"/bin/sh -c"来运行,这意味着此进程在容器中的PID不为1,不能接收Unix信号,当容器停止时,此进程也会被shutdown。
    • 第二种语法格式中的参数是一个Json格式的数组,其中为要运行的命令,后面的为传递给命令的选项或者参数,然而,此格式指定的命令不会以"/bin/sh -c"来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行,不过,如果要运行的命令依赖此shell的话可以使用:
      • RUN ["/bin/sh", "-c", "", ""]
  • 注意:
    • RUN运行的命令都是基于基础镜像的,所以基础镜像中没有的命令无法运行。
# Description: test image
FROM busybox:latest
MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"

ENV DOCKER_ROOT /data/app/www/
ENV DOCKER_ROOT=/data/app/www/ \
    WEB_PACKAGE="nginx-1.16.1"
ADD http://nginx.org/download/nginx-1.16.1.tar.gz ${DOCKER_ROOT}
WORKDIR /data/app/
COPY ./index.html ${DOCKER_ROOT:-/data/web/html/}
VOLUME /data/mysql/

EXPOSE 80/tcp
# 运行RUN指令,解压修改包名
RUN cd ${DOCKER_ROOT} && \
    tar -xf ${WEB_PACKAGE}.tar.gz && \
    mv ${WEB_PACKAGE} webserver

3.10、CMD

  • 类似于RUN指令,用于设置容器启动后默认执行的命令及参数,CMD指令也可用于运行任何指令或者应用程序,不过,二者的运行时间点不同
    • RUN指令运行于构建镜像文件过程中,而CMD指令运行于基于Dockerfile构建出来的新文件启动一个容器时。
    • CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且运行结束后,容器也将终止。不过CMD指令的命令其可以被docker run的命令行选项所覆盖。
    • 在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效。
  • 语法:
    • CMD
    • CMD ["executable", "param1", "param2"]或
    • CMD ["<param1", "param2"]
    • 前两种语法格式的意义同RUN
    • 第三种则用于为ENTRYPOINT指令提供默认参数,需要结合ENTRYPOINT指令来使用。
  • 示例
# Description: test image
FROM busybox:latest
MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"

ENV DOCKER_ROOT=/data/app/www/ \
    WEB_PACKAGE="nginx-1.16.1"
WORKDIR /data/app/
COPY ./index.html ${DOCKER_ROOT:-/data/web/html/}

EXPOSE 80/tcp
RUN cd ${DOCKER_ROOT} && \
    mv ${WEB_PACKAGE} webserver

CMD /bin/httpd -f -h /data/app/www/ # 这里的CMD会调用/bin/sh来运行。

CMD ["/bin/sh", "-c","/bin/httpd", "-f", "-h ${DOCKER_ROOT}"] # 同时也支持这种方式。

3.11、ENTRYPOINT

  • 用于配置容器启动时的执行命令(不会被忽略,一定会执行,即时运行docker run时制定了其他命令)
  • 不过,可以使用--entrypoint选项来覆盖Dockerfile
  • ENTRYPOINT的exec格式用于设置容器启动时要执行的命令机器参数,同时可通过CMD命令或者命令行参数提供额外的参数。
  • 如果Dockerfile中同时提供了ENTRYPOINT和CMD。那么CMD会作为参数传给ENTRYPOINT
# Description: test image
FROM busybox:latest
MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"

# ENV DOCKER_ROOT /data/app/www/
ENV DOCKER_ROOT=/data/app/www/
COPY ./index.html ${DOCKER_ROOT:-/data/web/html/}

EXPOSE 80/tcp
RUN cd ${DOCKER_ROOT} && \
    mv ${WEB_PACKAGE} webserver

# CMD ["/bin/sh", "-c","/bin/httpd", "-f", "-h ${DOCKER_ROOT}"]
ENTRYPOINT /bin/httpd -f -h /data/app/www/

# 或者可同时指定CMD和ENTRYPOINT
CMD ["/bin/httpd", "-f", "-h /data/app/www/"]
ENTRYPOINT ["/bin/sh", "-c"]

3.12、USER

  • 用于指定运行image时或运行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序时的用户名或UID
  • 默认情况下,container的运行身份为root用户
  • 语法:
    • USER |
    • 需要注意的是可以是任意数字,但必须为/etc/passwd中某用户有效UID,否者,docker run会运行失败

3.13、HEALTHCHECK

  • 用于容器启动后的健康状况检查

  • 当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为 starting,在 HEALTHCHECK 指令检查成功后变为 healthy,如果连续一定次数失败,则会变为 unhealthy

  • 与CMD和ENTRYPOINT一样,只可以出现一次,如果写了多个,只有最后一个生效

  • 语法

    • HEALTHCHECK <参数> <命令>
  • 支持的选项

    • --interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
    • --timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
    • --retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。
    • --start-period=<时长>:当容器启动指定时长后,才开始健康检查,默认为0s,启动后就检查
  • 返回状态

    • 0:成功
    • 1:失败
    • 2:保留
# Description: test image
FROM nginx:stable-alpine
MAINTAINER "yull <liangliang.yu@onebank.com.cn>"
LABEL maintainer="yull <liangliang.yu@onebank.com.cn>"

ENV NGINX_ROOT="/data/app/nginx/"

ADD entrypoint.sh /bin/
COPY ./index.html ${NGINX_ROOT}

# 指定启动后自动检测容器状态
HEALTHCHECK --interval=5s --timeout=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/ || exit 1

CMD ["/usr/sbin/nginx", "-g", "daemon off;"]

ENTRYPOINT ["/bin/entrypoint.sh"]

启动成功后可以使用docker ps查看状态

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                   PORTS                   NAMES
fc19f4d7ced7        nginxweb02:v0.2.6   "/bin/entrypoint.sh …"   7 seconds ago       Up 6 seconds (healthy)   0.0.0.0:32776->80/tcp   nginxweb02

3.14、ARG

  • 构建参数和ENV的效果类似,都是设置环境变量,不同的是ARG所设置构建的环境变量,在将来容器运行时是不会存在这些环境变量的。
  • 可以在build时使用--build-arg <参数名>=<值>来向Dockerfile中传递参数。
# Description: test image
FROM nginx:stable-alpine
MAINTAINER "yull <liangliang.yu@onebank.com.cn>"

ARG author="yull <liangliang.yu@onebank.com.cn>"

LABEL maintainer=${author}
posted @ 2021-07-13 17:30  勤俭持家亮公子  阅读(199)  评论(0)    收藏  举报