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存在以下特点:
- 不会被 docker run 的命令行参数指定的指令所覆盖,而是会把它当作入口点程序的参数传递到容器内部执行。除非 docker run 时使用了 --entrypoint 选项参数,这将会覆盖 ENTRYPOINT 指令。
- 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 文件位置位于当前执行命令所处目录中 。
文章评论