第九篇:《Dockerfile 指令精讲(二):WORKDIR、ENV、ARG、EXPOSE》
继续 Dockerfile 的学习。本文将讲解 WORKDIR、ENV、ARG、EXPOSE 这四个指令,它们在设置工作目录、环境变量、构建参数和声明端口方面发挥着关键作用。掌握这些指令可以让你的 Dockerfile 更灵活、更安全、更易维护。
一、WORKDIR:设置工作目录
语法:
dockerfile
WORKDIR /path/to/dir
作用:为后续的 RUN、CMD、ENTRYPOINT、COPY、ADD 指令设置工作目录。如果目录不存在,Docker 会自动创建。
特性:
可以多次使用,后续的相对路径会基于上一个 WORKDIR。
支持环境变量引用(如 WORKDIR $APP_HOME)。
示例:
dockerfile
WORKDIR /app
RUN pwd # 输出 /app
WORKDIR src
RUN pwd # 输出 /app/src
WORKDIR /root
RUN pwd # 输出 /root
最佳实践:
每个 Dockerfile 中至少使用一个 WORKDIR,避免默认的根目录(/)导致文件混乱。
建议使用绝对路径,避免相对路径带来的歧义。
将 WORKDIR 放在 COPY 之前,以便使用相对路径复制文件。
二、ENV:设置环境变量
语法:
dockerfile
ENV
ENV = = …
作用:设置环境变量,在构建过程和容器运行时均可使用。
特性:
变量值可以在后续指令中通过 $VARIABLE 或 ${VARIABLE} 引用。
持久化到最终镜像中,容器启动时也会包含这些变量。
示例:
dockerfile
ENV NODE_VERSION=18.17.0
ENV APP_HOME=/app
WORKDIR $APP_HOME
RUN echo $NODE_VERSION > version.txt
覆盖方式:
构建时可通过 --build-arg 覆盖 ENV(但需要先定义 ARG)。
运行时可通过 docker run -e KEY=value 覆盖。
最佳实践:
将需要频繁修改的值(如版本号)定义为环境变量,便于维护。
避免在 ENV 中存储敏感信息(密码、密钥),因为镜像层可以被 docker history 查看。可使用 Docker Secret 或构建时传入 ARG 并多阶段清理。
三、ARG:构建参数
语法:
dockerfile
ARG <变量名>[=<默认值>]
作用:定义构建时的变量,仅在构建过程中有效,不会保留在最终镜像中。
与 ENV 的区别:
示例:
dockerfile
ARG VERSION=latest
FROM alpine:$VERSION
ARG BUILD_DATE
RUN echo “Built on: $BUILD_DATE” > /build-info
ENV APP_VERSION=$VERSION # 将 ARG 传递给 ENV
构建时传递参数:
dockerbuild --build-argVERSION=3.18--build-argBUILD_DATE=$(date+%Y-%m-%d)-tmyimage.最佳实践:
使用 ARG 定义可配置的版本号、基础镜像标签、代理设置等。
敏感信息可通过 ARG 传入,但请注意 --build-arg 的值会在构建历史中可见(docker history),多阶段构建可以清理。
定义默认值,使构建仍可无参运行。
四、EXPOSE:声明端口
语法:
dockerfile
EXPOSE [/…]
作用:声明容器运行时监听的端口,主要用于文档目的和与编排工具(如 Docker Compose)的协作。它并不会实际发布端口。
协议默认为 TCP,可指定 /udp。
可以多次 EXPOSE 或多个端口写在一行。
示例:
dockerfile
EXPOSE 80
EXPOSE 443/tcp
EXPOSE 53/udp
与 -p 和 -P 的关系:
docker run -P:随机映射所有 EXPOSE 的端口到宿主机。
docker run -p 8080:80:手动映射端口,无论是否 EXPOSE 都可以。
最佳实践:
显式声明应用监听的端口,方便协作和自动化工具(如 Kubernetes 识别端口)。
即使不使用 -P,建议仍写 EXPOSE 作为文档。
五、综合示例:结合多个指令
dockerfile
构建参数
ARG BASE_IMAGE=node:18-alpine
ARG APP_HOME=/app
FROM $BASE_IMAGE
设置环境变量(持久化)
ENV NODE_ENV=production
APP_HOME=${APP_HOME}
创建工作目录并切换
WORKDIR $APP_HOME
复制依赖文件并安装(利用缓存)
COPY package*.json ./
RUN npm ci --only=production
复制源代码
COPY . .
声明端口
EXPOSE 3000
运行命令
CMD [“node”, “server.js”]
构建并运行:
dockerbuild --build-argBASE_IMAGE=node:20-alpine-tmyapp.dockerrun-d-p3000:3000 myapp六、常见问题与解决
七、小结
WORKDIR 设置工作目录,建议使用绝对路径。
ENV 定义环境变量,持久化到镜像和容器中。
ARG 定义构建参数,仅构建时有效,适用于可配置的构建行为。
EXPOSE 声明端口,是文档和工具协作的好习惯。
这些指令让 Dockerfile 更灵活、更清晰。结合上一讲的 FROM、RUN、COPY、ADD,你已经可以编写复杂的生产级 Dockerfile。
