1. 首页
  2. Docker
  3. 正文

Dockerfile的详细配置

2019年8月20日 299点热度 0人点赞 0条评论

Dockerfile 是一个用来描述构建自定义镜像的文本文件,内容中包含了用于构建自定义镜像所需的原镜像、环境变量、镜像内部的应用、配置项、shell命令等等。这篇文章将会介绍Dockefile各项指令的详细配置。

FROM

用于指定构建自定义镜像所需要的源镜像,例如 FROM node 表示构建一个基于debian镜像的自定义镜像。

RUN

用于定义构建镜像过程中需要执行的命令,这些命令通常用于安装软件包、配置环境、下载文件等等。

在镜像构建过程中(docker build)每个 RUN 指令都会创建一个新的临时容器,在其中运行RUN指定的命令,也就是说每执行一次RUN命令的操作会生成新的镜像层,这些层将在最终的镜像中组合在一起,这些过多无意义的镜像层,会造成镜像膨胀过大。

多个RUN指令:

FROM debian
RUN yum install nginx
RUN systemctl enabled nginx.service
RUN systemctl start nginx.service

简化为一个RUN指令:

FROM debian
RUN yum install nginx && \ 
    systemctl enabled nginx.service && \
    systemctl start nginx.service

RUN指令可以使用两种格式的命令:

shell格式命令

使用 shell 格式时,Docker 会启动一个新的 shell 进程(默认为 /bin/sh -c),然后在 shell 中执行命令。命令和参数可以直接以字符串的形式传递给 RUN 指令。
可以使用 export 命令来设置环境变量。
RUN yum install -y nginx

exec格式命令

使用 exec 格式时,Docker 不会启动新的 shell 进程来执行命令,而是直接执行指定的命令,这可以减少不必要的额外 shell 进程。命令和参数需要以 JSON 数组的形式传递给 RUN 指令。环境变量需要通过 -e 选项传递给 RUN 指令,而不能使用 export 命令来设置。
RUN ["yum", "install", "-y", "nginx"]

CMD

指定容器启动时(docker run)执行的命令和参数,如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

这种情况可被 docker run 命令行参数中指定要运行的命令所覆盖。

CMD ["echo" "Hello world!" ]
docker run debian

该镜像被实例化创建容器第一次运行时,即执行 docker run debian时输出Hello world!,但是如果指定 docker run debian的命令行参数,则会覆盖CMD中的命令。
docker run debian echo hi! #输出hi!

ENTRYPOINT

指定运行容器的入口点程序,用于定义容器启动时的主要命令,与CMD结合使用,存在多个 ENTRYPOINT 时仅最后一个生效。ENTRYPOINT存在以下特点:

  1. 不会被 docker run 的命令行参数指定的指令所覆盖,而是会把它当作入口点程序的参数传递到容器内部执行。除非 docker run 时使用了 --entrypoint 选项参数,这将会覆盖 ENTRYPOINT 指令。
  2. CMD 指令指定的参数将会被追加到 ENTRYPOINT 指令指定的命令后面。

示例:

FROM nginx
ENTRYPOINT ["nginx", "-c"] # 不会被覆盖,除非显示指定 --entrypoint。
CMD ["/etc/nginx/nginx.conf"] # 会被覆盖
docker run nginx:test -c /etc/nginx/new.conf

最终结果只是CMD被覆盖了,在容器内部最终会运行以下命令:
nginx -c /etc/nginx/new.conf

通常,CMD 用于定义容器的默认行为,但允许在运行容器时通过传递参数来覆盖它。而 ENTRYPOINT 用于定义容器的主要执行命令,它通常不会被覆盖,但可以与 CMD 结合使用以提供默认参数。这允许用户在运行容器时指定不同的参数,而不必覆盖整个主要命令。

SHELL

SHELL 指令用于指定在构建镜像时使用的 shell。

默认情况下,Docker 使用 /bin/sh -c 作为默认shell来执行RUN、CMD、ENTRYPOINT等命令。这是构建过程的一部分,用于执行Dockerfile中定义的命令以创建镜像的不同层。

ENV

在镜像构建过程中设置环境变量。


这些变量在容器运行时也会存在。所以RUN、CMD、ENTRYPOINT以及容器内部的应用程序都可以使用这里定义的环境变量。
ENV MY_VAR=my_value

在docker run命令中使用-e选项项来动态设置、覆盖环境变量。
docker run -e MY_VAR=my_value my-image

ARG

定义构建镜像时的参数,定义在镜像构建过程中传递给构建器的变量。

与 ENV 用法类似,不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 有效,也就是说只有docker build 的过程中有效,而构建好的镜像,也就是容器运行时不存在此环境变量。
ARG PORT=8080

也可以在构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来传递、覆盖 ARG 中定义的参数。
docker build --build-arg PORT=8081 .

通过ENV与ARG的特性,我们可以实现动态传递变量值。

ARG PORT=8080
ENV APP_PORT=$PORT
docker build --build-arg PORT=8081 .

ARG 指令适合用于在构建镜像时传递值,例如应用程序的版本号。ENV 指令适合用于在容器启动时设置环境变量,例如应用程序的配置参数。

COPY

将文件或目录从构建上下文复制到镜像中,构建上下文是 Dockerfile 所在的目录及其子目录。如果目标文件存在,则会覆盖替换。


COPY [源路径] [目标路径]
源路径:基于构建上下文的相对路径
目标路径:镜像内部路径,如果路径不存在的话,会自动创建。


还可以手动改变复制到镜像内文件的用户和用户组
COPY [--chown=<user>:<group>] [源路径] [目标路径]

ADD

与COPY基本一致,区别在它可以接收一个远程URL复制到镜像中。当目标文件是压缩包时,ADD命令会尝试解压文件。如果目标文件存在,不会覆盖替换。

VOLUME

在实例化容器时自动创建匿名数据卷并挂载到容器内部,以便于用来存储容器运行时的数据。
VOLUME /var/lib/mysql

数据卷允许容器之间共享数据,其他容器可以通过 --volumes-from 将这个匿名数据卷挂载到相同的挂载点,当该容器删除后数据仍然存在于其他容器中。
docker run -it --volumes-from mysql-container my-app-container

当运行容器时,可以使用 -v 或 --volume 选项来将物理主机上的目录挂载到容器中的挂载点上。这样,容器内的数据就可以与主机上的数据进行交互。

VOLUME /var/lib/mysql
docker run -v /data:/var/lib/mysql my-image

USER

用于指定执行后续命令(位于USER之后的RUN、CMD、ENTRYPOINT)以及容器内部执行命令的用户和用户组。

USER nginx:nginx
# 指定用户和用户组,用户组不是必须的
USER 1000
# 使用用户ID
  • USER 指令必须在容器的第一个 RUN 或 CMD 指令之前。
  • USER 指令可以多次使用,后面的 USER 指令将覆盖前面的 USER。
  • 在没有指定 USER 指令的情况下,容器中命令的默认用户是 root。
  • 需要注意的是用户和用户组必须已经创建存在。

WORKDIR

用于指定工作目录,如果目录不存在会自动创建。它有两个作用。

一是对于容器内部而言,设置容器中执行命令的默认工作路径。WORKDIR 指令通常用于设置容器中应用程序的工作目录。例如,如果容器中运行的是 Web 应用程序,则可以使用 WORKDIR 指令将工作目录设置为应用程序的根目录。

WORKDIR /app
RUN npm install
# 容器中的命令将在 /app 目录中运行。

二是用于Dockerfile中的 RUN、CMD、ENTRYPOINT 和 COPY 指令设置上下文。
WORKDIR 指令必须在容器的第一个 RUN 或 CMD 指令之前,同时 WORKDIR 指令可以多次使用,后面的 WORKDIR 将覆盖前面的 WORKDIR。换句话说每一个使用了相对路径的命令将相对于前一个 WORKDIR 指令设置的路径进行执行。

EXPOSE

声明容器运行时需要暴露的端口
EXPOSE 80 443 8080/TCP

EXPOSE 指令的主要作用是提供容器的元数据信,用于文档和标记容器的网络端口信息,它并不会实际打开或映射宿主机的端口.当其他开发人员或运维人员查看 Docker 镜像的信息时,可以通过 EXPOSE 指令了解容器应该监听哪些端口。

要实现端口映射,需要在运行容器时使用 -p 或 -P 选项。例如,要将容器的 80 端口映射到宿主机的 8080 端口:

docker run -p 8080:80 my-image
# 物理宿主机通过 http://localhost:8080 访问容器中运行的应用程序。

ONBUILD

用来指定当该镜像被用作另一个构建过程的基础时执行的命令。
ONBUILD <触发操作>

其中 <触发操作> 可以是任何合法的 Dockerfile 指令,如 RUN、COPY、CMD 等。

FROM debian
RUN apt-get update && apt-get install -y nodejs
ONBUILD RUN npm install

在这种情况下,如果其他镜像基于该镜像进行二次构建,则将在构建过程中运行 npm install 命令。

HEALTHCHECK

定义周期性检查容器健康状态的命令,并在容器发生问题时进行自动重启。
HEALTHCHECK [选项] CMD <命令>

选项有以下几个参数:

  • --interval=<间隔时间>:指定健康检查的间隔时间,默认值为 30 秒。
  • --timeout=<超时时间>:指定健康检查的超时时间,默认值为 30 秒。
  • --retries=<重试次数>:指定容器在健康检查失败后重试的次数,默认值为 3 次。
  • --start-period=<启动周期>:指定容器启动后第一次健康检查之前的等待时间,默认为 0 秒。

命令:可以是任何合法的 Shell 命令或可执行文件,根据在容器内部执行的返回结果判断,如果返回非零退出码,容器将被标记为不健康。

以下 Dockerfile 定义了一个健康检查:
HEALTHCHECK --interval=10s --timeout=5s --retries=5 CMD curl -fs http://localhost/

每 10 秒检查一次,超时时间为 5 秒,容器在健康检查失败后重试 5 次。如果5次容器都无法成功连接到该端口,则容器将被重启。

LABEL

该指令以键值对的形式为镜像添加元数据标签,这些标签提供有关镜像的信息,如作者、版本、描述等,以便用户更容易了解和管理镜像。

  • 添加作者信息: 使用 maintainer 标签指定镜像的作者或维护者。
  • 添加版本信息: 使用 version 标签指定镜像的版本号。
  • 添加描述信息: 使用 description 标签提供有关镜像用途和描述的信息。
  • 添加自定义标签: 可以根据需要添加自定义的元数据标签,以提供更多有关镜像的信息。
# 添加作者信息
LABEL maintainer="John Doe <johndoe@example.com>"
# 添加描述信息
LABEL description="This is a Docker image for my web application."
# 添加版本信息
LABEL version="1.0"
# 添加自定义标签
LABEL release-date="2022-05-12"

STOPSIGNAL

用来指定在停止容器时使用的信号。容器可以通过发送信号来请求停止,而 STOPSIGNAL 指令用于定义容器接受的信号类型。该指令通常使用不多,除非有特定的需求或应用程序需要使用不同于默认的停止信号,大多数容器可以依赖于默认的 SIGTERM 信号来停止,这足以满足大多数的使用场景。

如何使用 Dockerfile

在 Dockerfile 文件的所在的目录下执行命令行命令:
docker build -t custom-nginx:v1 .

  • -t:表示使用Dockerfile文本文件来构建镜像。
  • custom-nginx:v1:custom-nginx表示新构建的镜像名称,v1表示镜像tag标签。
  • ".":表示 Dockerfile 文件位置位于当前执行命令所处目录中 。
标签: Docker Dockerfile
最后更新:2023年10月22日

Evans Ann

It's no use crying over spilt milk.

点赞

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

归档

  • 2023 年 11 月
  • 2023 年 10 月
  • 2021 年 1 月
  • 2020 年 8 月
  • 2020 年 1 月
  • 2019 年 8 月

分类目录

  • Docker
  • JavaScript
  • Kubernetes
  • Linux
  • PHP
  • Windows
  • 基础
  • 正则表达式
  • 英语

COPYRIGHT © 2018-2024 秋雨沥沥. ALL RIGHTS RESERVED.

赣ICP备18001671号-3