第九篇:《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

构建时传递参数:

bash 复制代码
docker build --build-arg VERSION=3.18 --build-arg BUILD_DATE=$(date +%Y-%m-%d) -t myimage .

最佳实践:

使用 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"

构建并运行:

bash 复制代码
docker build --build-arg BASE_IMAGE=node:20-alpine -t myapp .
docker run -d -p 3000:3000 myapp

六、常见问题与解决

七、小结

WORKDIR 设置工作目录,建议使用绝对路径。

ENV 定义环境变量,持久化到镜像和容器中。

ARG 定义构建参数,仅构建时有效,适用于可配置的构建行为。

EXPOSE 声明端口,是文档和工具协作的好习惯。

这些指令让 Dockerfile 更灵活、更清晰。结合上一讲的 FROM、RUN、COPY、ADD,你已经可以编写复杂的生产级 Dockerfile。

相关推荐
IKUN家族5 小时前
Spring MVC(一)
java·spring·mvc
老马识途2.07 小时前
关于跨域问题的总结
java·前端
魔力女仆7 小时前
分享一个 JS 鼠标跟随贪吃蛇背景库
开发语言·javascript·计算机外设
都叫我大帅哥8 小时前
Java日期时间三十年战争:从Date考古到LocalDateTime革命,以及数据库与前端的那点事儿
java
Muscleheng8 小时前
SpringBoot 集成 DeepSeek 实现 RAG 文档问答
java·spring boot·ai·springai
2401_894915538 小时前
GEO 搜索优化完整源码从零部署:环境配置、集群搭建全流程
开发语言·python·tcp/ip·算法·unity
2501_936415698 小时前
可变参数&综合练习&斗地主游戏
java·windows·游戏
麻瓜老宋8 小时前
AI开发C语言应用按步走,表达式计算器calc的第二十二步,分号赋值链式修复、TOKEN_ASSIGN
c语言·开发语言·atomcode
极客先躯9 小时前
高级java每日一道面试题-2026年05月03日-实战篇[Docker]-如何实现容器化环境的数据加密?
java·运维·docker·容器·金融·加解密·高级面试
xqqxqxxq10 小时前
Java Socket 多人聊天室(私聊+群聊)技术笔记(V4版本)
java·网络·笔记