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

相关推荐
宸津-代码粉碎机4 小时前
OpenAI 连夜迎战 Grok Bot 和 Muse:AI 智能体从 “会聊天” 到 “能办事”,现在入场还来得及吗
java·大数据·人工智能·分布式·python
chenbingjie_c5 小时前
C++ 进阶核心知识点总结:模板、内存分区、new/delete、内存池
开发语言·c++
噢,我明白了6 小时前
java中唯一键和幂等键的应用
java·后端
程序猿乐锅6 小时前
【黑马点评 | 第八篇】Redisson分布式锁
java·数据库·spring boot·redis·分布式·spring·缓存
考虑考虑6 小时前
synchronized字符串常量
java·后端·java ee
长谷深风1116 小时前
Tool与Skill:AI能力设计的分水岭
java·人工智能·ai·大模型·aiagent
m0_587383006 小时前
广州24小时自助健身房解决方案实战指南与系统部署要点
java·spring·小程序·架构·需求分析
Escalating_xu6 小时前
【C 语言】深入理解指针(1·下):指针运算、野指针、assert 与传址实战
java·c语言·开发语言
实心儿儿6 小时前
Qt — Qt 事件
开发语言·qt
周杰偷奶茶7 小时前
【Java】数据类型与变量
java·开发语言