Dockerfile 基础知识

「这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

Docker 可以通过读取 Dockerfile 中的指令自动构建镜像。Dockerfile 是一个文本文档,其中包含用户可以在命令行上调用以组合图像的所有命令。使用 docker build 用户可以创建一个连续执行多个命令行指令的自动构建。

首先来看一个标准的 Dockerfile 文本包含哪些内容:

FROM docker.io/bitnami/minideb:buster
LABEL maintainer "Bitnami <[email protected]>"

ENV HOME="/" \
    OS_ARCH="amd64" \
    OS_FLAVOUR="debian-10" \
    OS_NAME="linux" \
    PATH="/opt/bitnami/common/bin:/opt/bitnami/etcd/bin:$PATH"

COPY prebuildfs /
# Install required system packages and dependencies
RUN install_packages acl ca-certificates curl gzip jq procps tar
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "gosu" "1.14.0-0" --checksum 3e6fc37ca073b10a73a804d39c2f0c028947a1a596382a4f8ebe43dfbaa3a25e
RUN . /opt/bitnami/scripts/libcomponent.sh && component_unpack "etcd" "3.5.1-0" --checksum 912653e5c0879fd27c8bb0327bea171d7ae504611ec0a9c8fcc2ec6184766a63
RUN chmod g+rwX /opt/bitnami

COPY rootfs /
RUN /opt/bitnami/scripts/etcd/postunpack.sh
ENV BITNAMI_APP_NAME="etcd" \
    BITNAMI_IMAGE_VERSION="3.5.1-debian-10-r27" \
    ETCDCTL_API="3"

EXPOSE 2379 2380

WORKDIR /opt/bitnami/etcd
USER 1001
ENTRYPOINT [ "/opt/bitnami/scripts/etcd/entrypoint.sh" ]
CMD [ "/opt/bitnami/scripts/etcd/run.sh" ]
复制代码

就此来分析一下一个 Dockerfile 包含哪些常用指令

FROM 指令

FROM 是指定基础镜像,必须为第一个命令,格式为:FROM <image>:<tag> 其中 tag 或 digest 是可选的,如果没有写时,会默认使用 latest 版本的基础继续。 比如示例中的:FROM docker.io/bitnami/minideb:buster

MAINTAINER 指令

MAINTAINER 用来声明维护者信息,格式为:MAINTAINER <name> 该命令已过期,推荐使用 LABEL

LABEL 指令

LABEL 用于为镜像添加元数据,多用于声明构建信息,如:作者、机构、组织等。格式为:LABEL <key>=<value> <key=value> ... 如示例中:LABEL maintainer "Bitnami <[email protected]>" 使用 LABEL 时要注意,一条 LABEL 可以指定一个或多个元数据,指定多个元数据是不同元数据之间通过空格分割。建议将所有元数据通过一条 LABEL 指令合并,这样可以避免产生过多的中间镜像。

ENV 指令

ENV 用来设置环境变量,格式:ENV <key> <value> ,如果一次想设置多个环境变量,格式为

ENV <key>=<value> \
    <key>=<value> \
    <key>=<value>
复制代码

如示例中:

ENV HOME="/" \
    OS_ARCH="amd64" \
    OS_FLAVOUR="debian-10" \
    OS_NAME="linux" \
    PATH="/opt/bitnami/common/bin:/opt/bitnami/etcd/bin:$PATH"
复制代码

ARG 指令

ARG 用于指定传递给构建运行时的变量,格式:ARG <name>[=<default value>] 通过 docker run 中的 --build-arg <key>=<value> 来动态赋值,不指定将使用其默认值。

WORKDIR 指令

WORKDIR 用来指定工作目录,类似于我们通常使用的 cd 命令,格式:WORKDIR <PATH> 通过 WORKDIR 设置工作目录,Dockerfile 中的其它指令 RUN、CMD、ENTRYPOINT、ADD、COPY 等命令都会在该目录下执行。 在使用 docker run 运行容器时,可以通过 -w 参数来覆盖。 如示例中:

WORKDIR /opt/bitnami/etcd
复制代码

ADD 指令

ADD 用于将本地文件添加到镜像中,tar 类型文件会自动进行解压,可以访问网络资源。格式:

ADD <src> <dest>
# 如果路径中包含空格,使用下面写法
ADD ["<src>", "<dest>"]
复制代码

COPY 指令

COPY 的功能类似于 ADD,但不会自动解压文件、访问网络资源,格式:COPY <src> <dest> 如示例中:

COPY rootfs /
复制代码

RUN 指令

RUN 用来在构建镜像时执命令,有两种命令执行方式:

  1. shell 格式

RUN <command> 示例:RUN install_packages acl ca-certificates curl gzip jq procps tar 2. exec 格式 RUN ["executable", "param1", "param2"] 示例:RUN ["/dev/file", "p1", "P2"]

注意,RUN 指令创建的中间镜像会被缓存,并会在下次构建中重复使用,如果不想使用缓存镜像,可以在构建时指定--no-cache,示例:

docker build --no-cache

CMD 指令

CMD 设定在容器启动时执行的命令,格式:

CMD command param1 param2
CMD ["executable", "param1", "param2"]
# 设置了 ENTRYPOINT,直接调用ENTRYPOINT添加参数
CMD ["param1"]
复制代码

示例:CMD ["/usr/bin/bash", "--help"]

ENTRYPOINT 指令

ENTRYPOINT 用来配置容器,使其可执行话。可以配合 CMD 使用,格式:

ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
复制代码

如示例中:

ENTRYPOINT [ "/opt/bitnami/scripts/etcd/entrypoint.sh" ]
CMD [ "/opt/bitnami/scripts/etcd/run.sh" ]
复制代码

docker run 执行的命令不会覆盖 ENTRYPOINT,而 docker run 命令中指定的任何参数都会被当做参数再次传递给 ENTRYPOINT 指令。Dockerfile 中只有最后一个 ENTRYPOINT 命令起作用,也就是说如果你指定多个ENTRYPOINT,只执行最后的 ENTRYPOINT 指令。

EXPOSE 指令

EXPOSE 指定与外界交互的端口,格式:EXPOSE <port> [<port>...] 如示例在中:

EXPOSE 2379 2380
复制代码

EXPOSE 并不会主动让容器的端口映射主机。宿主机访问容器端口时,需要在 docker run 运行容器时通过 -p 来发布这些端口,或通过 -P 参数来发布 EXPOSE 导出的所有端口

VOLUME 指令

VOLUME 用于指定持久化目录, 格式:VOLUME ["<src>", ...] 示例:

VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
复制代码

和 EXPOSE 指令类似, VOLUME 并不会挂载的宿主机,需要通过 docker run 运行容器时通过 -v 来映射到宿主机的目录中。

USER 指令

USER 指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。当服务不需要管理员权限时,可以通过该命令指定运行用户。格式:

USER user
USER user:group
USER uid:group
USER uid
USER user:gid
USER uid:gid
复制代码

如示例中:

USER 1001
复制代码

使用 USER 指定用户后,Dockerfile 中其后的命令 RUN、CMD、ENTRYPOINT 都将使用该用户。你可以通过 docker run 运行容器时,可以通过 -u 参数来覆盖指定用户。

ONBUILD 指令

ONBUILD 作用是当所构建的镜像被其他镜像作为基础镜像是,ONBUILD 中的命令就会触发,格式:ONBUILD [INSTRUCTION] 示例:

ONBUILD RUN /usr/local/bin/on-build --dir /app/src
复制代码

Guess you like

Origin juejin.im/post/7031409474757722148