dockerfile文件之指令解析
常见指令
FROM
- 作用:指定构建镜像所基于的基础镜像。
- 基础镜像格式:镜像仓库地址/镜像名称:镜像标签,例如以下内容
mcr.microsoft.com/dotnet/aspnet:8.0 AS base
- 镜像仓库地址:mcr.microsoft.com 是微软容器注册表(Microsoft Container Registry)的地址,微软会将其官方的容器镜像发布到这个注册表中。
- 镜像名称:dotnet/aspnet 表示该镜像是 .NET 框架的 ASP.NET 运行时环境镜像。ASP.NET 是用于构建 Web 应用程序的开源框架,这个镜像包含了运行 ASP.NET 应用程序所需的所有依赖项。
- 镜像标签:8.0 是镜像的标签,它指定了使用的 .NET 版本为 8.0。标签通常用于区分不同版本的镜像。
- AS base:AS 关键字用于为当前使用的基础镜像定义一个别名,这里将其命名为 base。在多阶段构建的 Dockerfile 中,别名非常有用,后续的构建阶段可以通过这个别名来引用这个基础镜像,避免重复指定完整的镜像名称。
USER
- 作用:指定在执行后续 RUN、CMD、ENTRYPOINT指令时所使用的用户和用户组。
在 Docker 容器中,默认情况下进程是以 root 用户身份运行的。root 用户拥有最高权限,若容器被攻击,攻击者可利用 root 权限对系统造成严重破坏。使用 USER 指令可以切换到一个非 root 用户来运行应用程序,从而限制容器内进程的权限,提高容器的安全性。
- 格式
USER <user>[:<group>]
USER <UID>[:<GID>]
- user:指定用户名。
- group:指定用户组名,可选参数。如果不指定,Docker 会尝试使用与用户名相同的用户组。
- UID:用户的数字 ID。
- GID:用户组的数字 ID,可选参数。
- 常见配置
# 创建一个名为 app 的用户和用户组
RUN groupadd -r app && useradd -r -g app app
# 切换到app用户
USER app
# 创建一个具有特定 UID 和 GID 的用户
RUN addgroup -g 1001 appgroup && adduser -D -u 1001 -G appgroup appuser
# 切换到指定 UID 和 GID 的用户
USER 1001:1001
- 注意事项
- 在使用 USER 指令切换用户之前,需要确保指定的用户和用户组已经存在,否则可能会导致后续操作失败。
- 如果没有指定用户组,Docker 会尝试使用与用户名相同的用户组,如果该用户组不存在,可能会引发错误。
- 在多阶段构建中,每个阶段的用户设置是独立的,即一个阶段的 USER 指令不会影响其他阶段。
WORKDIR
- 作用:为后续 RUN、CMD、ENTRYPOINT、COPY、ADD指令设置容器内的工作目录。
- 格式
WORKDIR /path/to/directory
- /path/to/directory:工作目录的路径,既可以是绝对路径,也可以是相对路径。若使用相对路径,它会基于之前 WORKDIR 指令设置的目录来确定。
- 常见配置
这里将工作目录设置为 /app,后续的相对路径操作都会基于这个 /app 目录。
# 设置工作目录
WORKDIR /app
# 在工作目录下创建一个文件
RUN touch test.txt
第一个 WORKDIR 将工作目录设置为 /app,第二个 WORKDIR 使用相对路径 subdir,这意味着会进入 /app 目录下的 subdir 子目录,最终的工作目录为 /app/subdir。
# 首次使用绝对路径设置工作目录
WORKDIR /app
# 使用相对路径进入子目录
WORKDIR subdir
# 在工作目录下创建一个文件
RUN touch test.txt
- 使用场景
- 简化指令编写:使用 WORKDIR 可以避免在每个 RUN、COPY 等指令中都写完整的路径,使 Dockerfile 更加简洁易读。
- 确保操作路径一致性:确保所有操作都在指定的工作目录下进行,避免因路径问题导致的错误。
- 注意事项
- 目录不存在会自动创建:如果指定的工作目录在容器中不存在,WORKDIR 指令会自动创建该目录。
- 多阶段构建中独立设置:在多阶段构建里,每个阶段的 WORKDIR 设置是相互独立的,一个阶段的 WORKDIR 不会影响其他阶段。
- 相对路径的使用:如果使用相对路径,要确保之前已经正确设置了工作目录,否则可能会导致路径错误。另外
要避免路径冲突和错误引用,像 ../(返回上一级目录)可能会使工作目录跳到预期之外的位置。例如
WORKDIR /app
# 不恰当的相对路径操作,返回上一级目录,这会使工作目录从 /app 回到根目录 /
WORKDIR ../
EXPOSE
- 作用:向 Docker 表明容器在运行时会监听指定的网络端口。
- 格式
EXPOSE <port> [<port>/<protocol>...]
- port:指定要暴露的端口号。
- protocol:可选参数,指定端口使用的协议,默认为 TCP,也可以指定为 UDP。
例如,EXPOSE 5000 表示暴露 TCP 协议的 5000 端口;EXPOSE 5000/udp 则表示暴露 UDP 协议的 5000 端口。
- 使用场景
- 提示信息:当其他人使用你构建的 Docker 镜像时,EXPOSE 指令可以让他们清楚知道容器需要使用哪些端口,方便他们进行端口映射和网络配置。
- 自动化部署:在使用 Docker Compose 或 Kubernetes 等工具进行自动化部署时,这些工具可以根据 EXPOSE 指令自动进行端口映射和网络配置。
- 常见配置
EXPOSE 5000
EXPOSE 5000 声明了容器会监听 5000 端口。当你使用 docker run 命令启动容器时,可以通过 -p 选项将容器的 5000 端口映射到宿主机的某个端口。
- 注意事项
- 仅为声明:EXPOSE 指令只是一个声明,不会实际打开端口或进行端口映射。要实现端口映射,需要在运行容器时使用 -p 或 -P 选项。
- 多端口暴露:可以在 Dockerfile 中使用多个 EXPOSE 指令来暴露多个端口,也可以在一条 EXPOSE 指令中指定多个端口,例如 EXPOSE 5000 5001。
- 协议指定:如果需要暴露 UDP 端口,必须明确指定协议,例如 EXPOSE 5000/udp。
COPY
- 作用:将宿主机上的文件或目录复制到 Docker 容器内部。
- 格式
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
- --chown=
: :可选参数,用于指定复制到容器内的文件或目录的所有者和所属组。 - <源路径>:可以是单个文件、目录,或者使用通配符指定多个文件。可以是相对路径或绝对路径,相对路径是相对于构建上下文的。
- <目标路径>:容器内的目标路径,可以是相对路径或绝对路径。如果是相对路径,则相对于容器内的当前工作目录。
- 常见配置
# 设置工作目录
WORKDIR /app
# 复制宿主机当前目录下的所有文件和目录到容器的 /app 目录
COPY . .
- 使用场景
- 部署应用程序:在构建应用程序的 Docker 镜像时,通常需要将应用程序的代码、配置文件等复制到容器内,以便容器能够运行应用程序。
- 测试环境搭建:在搭建测试环境的 Docker 镜像时,可以将测试脚本、测试数据等复制到容器内,方便进行测试。
- 注意事项
- 构建上下文:构建上下文是指在执行 docker build 命令时指定的目录,COPY 指令的源路径是相对于这个构建上下文的。确保在执行 docker build 命令时指定了正确的构建上下文目录。
- 文件排除:可以使用 .dockerignore 文件来排除不需要复制到容器内的文件和目录,提高构建效率。
- 权限问题:如果需要指定复制到容器内的文件或目录的所有者和所属组,可以使用 --chown 选项。
ENV
- 作用:设置环境变量。
- 设置容器内的环境变量:ENV 指令会在容器构建过程中设置环境变量,这些环境变量会在容器运行时持续存在。容器内的应用程序可以读取这些环境变量来获取配置信息。
- 简化后续指令:在 Dockerfile 后续的 RUN、CMD、ENTRYPOINT等指令中,可以直接使用已设置的环境变量,避免重复输入相同的值。
- 格式
# 一次设置一个环境变量
ENV <key> <value>
# 一次设置多个环境变量
ENV <key1>=<value1> <key2>=<value2> ...
- key:环境变量的名称。
- value:环境变量的值。
- 常见配置
3.1 设置一个环境变量
FROM ubuntu:latest
# 设置一个环境变量
ENV APP_VERSION 1.0
# 在 RUN 指令中使用环境变量
RUN echo "The application version is $APP_VERSION"
# 定义容器启动时执行的命令,打印环境变量的值
CMD ["sh", "-c", "echo $APP_VERSION"]
3.2 设置多个环境变量
FROM alpine:latest
# 一次设置多个环境变量
ENV DB_HOST=localhost DB_PORT=5432 DB_USER=admin
# 在 RUN 指令中使用环境变量
RUN echo "Connecting to database at $DB_HOST:$DB_PORT as $DB_USER"
# 定义容器启动时执行的命令,打印环境变量的值
CMD ["sh", "-c", "echo Database host: $DB_HOST, port: $DB_PORT, user: $DB_USER"]
- 使用场景
- 应用程序配置:通过设置环境变量,可以在不修改应用程序代码的情况下,动态配置应用程序的行为,例如数据库连接信息、API 密钥等。
- 多环境部署:在不同的环境(开发、测试、生产)中,可以使用不同的环境变量值来部署相同的 Docker 镜像,提高部署的灵活性。
- 注意事项
- 环境变量的作用域:ENV 指令设置的环境变量在整个 Dockerfile 以及基于该 Dockerfile 构建的容器中都有效。
- 安全性:如果环境变量包含敏感信息(如密码、密钥等),要注意保护这些信息,避免在日志或其他地方泄露。可以考虑使用 Docker 的秘密管理功能或在运行容器时通过 -e 选项动态设置环境变量。
- 变量替换:在 Dockerfile 中使用环境变量时,要注意变量替换的规则。例如,在 RUN 指令中使用环境变量时,需要使用 $ 符号引用变量。
RUN
- 作用:在构建镜像时执行各种命令,完成一系列操作,如安装依赖包、配置环境、编译代码等。每一个 RUN 指令都会在当前镜像的基础上创建一个新的中间层,该中间层包含了执行命令后的文件系统变化。
- 格式
格式一:exec,命令以 JSON 数组的形式指定,不会通过 shell 执行。
RUN ["可执行文件", "参数1", "参数2", ...]
格式二:shell
RUN <命令>
ENTRYPOINT
- 作用:配置容器启动时执行的命令。
- 格式
格式一:exec,命令以 JSON 数组的形式指定,不会通过 shell 执行。推荐此格式。
ENTRYPOINT ["可执行文件", "参数1", "参数2", ...]
格式二:shell,这种形式下,命令会在 shell 中执行,在基于 Linux 的镜像里,默认使用 /bin/sh -c 来执行命令。
ENTRYPOINT <命令>
- 常见配置
# 使用 .NET 运行时基础镜像
FROM mcr.microsoft.com/dotnet/aspnet:8.0
# 设置容器内的工作目录
WORKDIR /app
# 将宿主机上 publish 目录下的所有文件和文件夹复制到容器内的 /app 目录
COPY ./publish .
# 容器启动时,在 /app 目录下执行 dotnet XX.Service.Api.dll 命令来运行应用程序。
ENTRYPOINT ["dotnet", "XX.Service.Api.dll"]
- 使用场景
- 封装可执行程序:把一个应用程序封装成 Docker 镜像,让容器像一个可执行程序一样运行。
- 提供默认配置:为应用程序提供默认的配置选项。
- 注意事项
- 优先使用 exec 形式:exec 形式的 ENTRYPOINT 不会启动一个额外的 shell 进程,因此效率更高,并且可以更好地处理信号。例如,当你向容器发送 SIGTERM 信号时,exec 形式的 ENTRYPOINT 可以直接接收到该信号,而 shell 形式可能会导致信号处理异常。
- 命令路径问题:在使用 exec 形式时,需要确保指定的可执行文件路径是正确的。如果可执行文件不在系统的 PATH 环境变量中,需要提供完整的路径。
常见配置
- 配置上海时区
# 添加时区环境变量,亚洲,上海
ENV TimeZone=Asia/Shanghai
# 使用软连接,并且将时区配置覆盖/etc/timezone
RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone
- 官方镜像
# 使用官方的 .NET 8 运行时镜像作为基础镜像
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
# 使用官方的 .NET 8 SDK 镜像作为构建镜像
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
- 程序文件复制到容器
WORKDIR /app
# 把宿主机上构建上下文目录下的 XX.csproj 文件复制到容器内的当前工作目录app中。
COPY ["XX.csproj", "./"]
# dockerfile文件和publish文件夹是同级情况,将publish目录及其所有子目录和文件复制到容器app工作目录中
COPY publish/ /app
- 暴露端口
EXPOSE 80
EXPOSE 8080
EXPOSE 443
人生如逆旅
我亦是行人

浙公网安备 33010602011771号