Dockerfile Tutorial

本文最后更新于:2024年8月9日 晚上

Very detailed tutorial on Dockerfile.

FROM

基础image的来源。

  • FROM <repository>:[tag]

    1
    2
    3
    FROM busybox # will pull latest tag by default
    FROM busybox:latest # 默认使用hub.docker.com 仓库image
    FROM registry.cn-shenzhen.aliyuncs.com/abo/devops:v1
  • FROM <repository>@<digest>

    1
    2
    3
    FROM alpine@sha256:d7342993700f8cd7aba8496c2d0e57be0666e80b4c441925fc6f9361fa81d10e
    # docker pull 通过digest方式
    docker pull alpine@sha256:d7342993700f8cd7aba8496c2d0e57be0666e80b4c441925fc6f9361fa81d10e

MAINTANTIER

添加维护者等信息。

  • MAINTANTIER <infomatin>

注意: MAINTANTIER语法已经被新的LABEL替代

1
2
# 维护着信息或者作者信息,可有可无
MAINTANTIER "Peter<westlife@aliyun.com>"

LABEL

作用和MAINTANTIER一摸一样

语法格式:LABEL <key>=<vale> <key>=<vale>

1
LABEL author="Peter<westlife@aliyun.com>"

COPY

复制文件或者目录.

  • COPY <src> <dest>

    1
    2
    # 所有的copy都指的是Dockerfile当前目录下的文件来讲的
    COPY test.tar.gz /data/web/
  • COPY ["<src>", …"<dest>"]

    1
    COPY ["test.tar.gz","/data/web/"]
  • 注意事项

    • src 支持通配符

    • dest 建议使用绝对路径

    • 路径中不能存在空白字符,常用第二种格式

    • src 是目录,只会复制其下层目录以及文件,不会复制src 目录本身到dest

    • 指定了多个src或者使用了通配符,dest必须是同一个,且dest必须以/结尾

ADD

复制添加文件或者目录.

  • ADD <src> <dest>

    1
    2
    3
    4
    5
    # 复制压缩包以及index.html文件到/data/web/目录下,并且压缩包会被自动解压,仅仅本地src才会被解压
    ADD test.tar.gz index.html /data/web/
    # 支持SRC为URL,请注意dest后面带/和不带区别
    ADD http://aliyun.com/test.tar.gz /data/web # 添加文件并且被命名为web
    ADD http://aliyun.com/test.tar.gz /data/web/ # 添加文件到/data/web/
  • ADD ["<src>", ..."<dest>"]

    1
    2
    3
    4
    # 添加URL的压缩文件和本地index文件到目标目录
    ADD ["http://5.5.5.100:8000/software/linux/nginx-1.18.0.tar.gz","index.html","/data/web/"]
    # 添加本地的两个文件到目标目录
    ADD ["test.tar.gz","index.html","/data/web/"]

VOLUME

用于在image中创建一个挂载点,以挂载docker host上的卷或者其他容器上的卷

  • VOLUME <mointpoint>

    1
    VOLUME /data/mydata/ 
  • VOLUME ["<mountpoint>"]

    1
    VOLUME ["/data/mydata/"]

注意:如果挂载点路径此前存在文件,``docker run`后会在挂载完成后将此前文件复制到新的挂载卷中

EXPOSE

容器运行起来向外需要暴露的端口。

EXPOSE <port>/<[tcp|udp]>

1
2
# 可以定义多个端口暴露
EXPOSE 80/tcp 2222/udp

ENV

容器定义环境变量,可以被ENV ADD COPY 所调用

  • ENV <key> <value>

    1
    2
    #  这种方式中,key后面的所有内容都会被认为是value的值,因此这种只能定义一个变量
    ENV HTTP_ROOT /usr/local/nginx/html/
  • ENV <key>=<value>

    1
    2
    3
    4
    # 此种方式可以定义多个变量
    ENV HTTP_ROOT="/usr/local/nginx/html/" \
    WORKDIR="/data/web/"
    PORT=80

    调用方式:$HTTP_ROOT or ${HTTP_ROOT}

RUN

**docker build**过程中需要运行的命令.

  • RUN <command>

    1
    2
    # 这种方式是以 /bin/sh -c 来运行mkdir,容器PID不为1,不能接受unix信号
    RUN mkdir -p /data/web
  • RUN [“<command>“,”<参数1>“,”<参数n>“]

    1
    2
    3
    4
    5
    6
    7
    8
    # 这种方式不是以 /bin/sh -c 来运行mkdir
    ENV HTTP_ROOT="/data/test/"
    # 以下三种方式均可创建指定目录
    RUN ["mkdir","-p","$HTTP_ROOT"]
    RUN ["mkdir","-p $HTTP_ROOT"]
    RUN ["mkdir","p ${HTTP_ROOT}"]
    # 如果要依赖shell特性以这种方式运行运行,请参照下面的格式,标准写法,推荐用以下方式
    RUN ["/bin/bash",-c","mkdir", "-p","$HTTP_ROOT"]

CMD

docker run过程中,容器运行起来需要执行的命令,注意和RUN做对比.RUN是构建过程需要的命令,CMD是容器运行起来运行的命令.

  • CMD <完整的命令以及参数>

    CMD指定的命令可以被docker run后面的命令覆盖!!!

    1
    2
    ENV HTTP_ROOT="/data/test/"
    CMD /bin/httpd -f -h $HTTP_ROOT
  • CMD [“<command>“,”<参数1>“,”<参数n>“]

    这种方式 方括号内无法读取环境变量参数

    1
    2
    3
    4
    5
    6
    ENV HTTP_ROOT="/data/test/"
    # 错误写法
    CMD ["/bin/httpd","-f","-h","$HTTP_ROOT"] # 这种方式CMD无法获取变量参数,
    # 正确写法
    CMD ["/bin/httpd","-f","-h /data/web/html/"]
    CMD ["/bin/httpd","-f","-h","/data/web/html/"]
  • CMD [“<参数1>”,”<参数2>“,”<参数n>“]

    此种方式用于为ENTRYPOINT 提供默认参数

ENTRYPOINT

功能和CMD一样,但是有差异,**ENTRYPOINT 运行的命令不可以被docker run后面的命令覆盖**

  • ENTRYPOINT ["<command>"]

    1
    2
    3
    # 为ENTRYPOINT提供运行参数,作用等于 CMD ["/bin/httpd","-f","-h","/data/web/html"]
    CMD ["-f","-h","/data/web/html"]
    ENTRYPOINT ["/bin/httpd"]
  • 示例

    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
    ####
    vim entrypoint.sh
    #!/bin/sh
    cat >/etc/nginx/conf.d/www.conf << EOF
    server {
    server_name $HOSTNAME;
    listen ${IP:-0.0.0.0}:${PORT:-80}; # -80和-0.0.0.0均为预设变量语法格式,如果未有变量输入将启动默认参数
    root ${NGX_ROOT:-/usr/share/nginx/html};
    }
    EOF
    exec "$@" # 此脚本运行完成后进程将被其所有参数替换
    #####
    vim Dockerfile
    FROM nginx:1.18-alpine
    LABEL author="Jason Hu"
    ENV NGX_ROOT="/data/nginx/html/"
    ADD entrypoint.sh /bin/
    ADD index.html $NGX_ROOT
    RUN chmod +x /bin/entrypoint.sh
    ENTRYPOINT ["/bin/entrypoint.sh"]
    CMD ["/usr/sbin/nginx","-g","daemon off;"]
    ####
    docker build -t nginx:lab .
    # use build image but web page still is the default not the one we defined, I'm thinking where did I miss?
    docker run --rm -itd -p 80:80 nginx:lab && curl localhost

HEALTHCHECK

用于容器的健康检查.

  • HEALTHCHECK [options] CMD <command>

    • options 可以有以下几种:
      1. --interval=<value> # default 30s
      2. --timeout=<value> # default 30s
      3. --start-period=<value> # default 0s
      4. —retries=<value> # default 3

    在容器内部运行命令检查健康状态,检查的结果状态值有以下三种:

    1. 0succeed healthy
    2. 1unhealthy
    3. 2reserved
  • HEALTHCHECK NONE

1
2
3
HEALTHCHECK --interval=5m --timeout=3s --start-period=5s \
CMD wegt -O - -q http://${IP:-0.0.0.0}:{PORT:-80}/
# CMD curl -f http://localhost/ || exit 1

SHELL

指定默认shell来运行命令,Linux 不指定默认是 ["/bin/sh","-c"] , Windows 默认不指定是["CMD","/S","/C"],SHELL可以在Dockerfil中出现多次

SHELL ["<command>","<参数>"]

  • STOPSIGNAL

    容器接受的unix信号来退出容器.

    STOPSIGNAL <signal>

  • ARG

    docker build 过程中定义的变量,可以使用--build-arg <key>=<value>来引入

    ARG <key>=<value>

    1
    2
    3
    4
    ARG author=scofield
    LABEL maintainer=${author}
    docker build --build-arg author=westlife -t test:v10 .
    # 新创建的出来的镜像 maintainer=westlife
  • ONBUILD

    用于在Dockerfile中定义一个触发器,自己创建的image 被另外一个Dockerfile用作基础镜像时会执行的指令

    语法格式:

    ONBUILD <Dockerfile指令>

    1
    ONBUILD ADD http://nginx.org/download/nginx-1.19.4.tar.gz /data/nginx/

Dockerfile Tutorial
https://git.msft.vip/2023/01/14-Dockerfile-How-to/
作者
Jas0n0ss
发布于
2023年1月15日
更新于
2024年8月9日
许可协议