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

相关推荐
唐青枫12 小时前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
一个做软件开发的牛马13 小时前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户37215742613513 小时前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java
用户37215742613513 小时前
Java 打印 Word 文档:从基础打印到高级设置
java
用户3521802454751 天前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程
东坡白菜1 天前
破局全栈:一个前端开发的Java入门实战记录(1)
java·全栈
唐青枫1 天前
Java Tomcat 实战指南:从 Servlet 容器到 Spring Boot 部署
java
wsaaaqqq1 天前
roudan:自由选择实体、灵活操作数据、快速写入数据库的 Java 框架
java
plainGeekDev2 天前
null 判断 → Kotlin 可空类型
android·java·kotlin
糖拌西瓜皮2 天前
Java开发者视角:深入理解Node.js异步编程模型
java·后端·node.js