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

相关推荐
八代臻1 小时前
docker代理
docker
JAVA社区1 小时前
Java高级全套教程(九)—— SpringCloud超详细实战详解
java·开发语言·后端·spring cloud·面试·职场和发展
wyjcxyyy1 小时前
java反序列化-cc1链
java·c语言·开发语言
山上三树1 小时前
Python 高频报错速查表(开发通用版)
开发语言·python
garmin Chen1 小时前
Elasticsearch(1):Elasticsearch核心原理与基础操作总结
java·大数据·笔记·elasticsearch·搜索引擎·全文检索
IT策士1 小时前
第17篇 Docker Compose 进阶实战:多 Compose 文件与环境覆盖
docker·容器·eureka
傻啦嘿哟2 小时前
解决DNS污染:防止OpenClaw解析API域名到虚假地址
开发语言·php
MY_TEUCK2 小时前
【MYTRUCK - AI 应用】MetaGPT 0.8.2 安装与排错完整实录(Python 3.10 + 虚拟环境)
开发语言·人工智能·python·ai
Devin~Y2 小时前
大厂Java面试实录:Spring Boot/Cloud、Kafka、Redis、K8s 可观测性 + RAG/Agent(小Y翻车版)
java·spring boot·redis·spring cloud·kafka·kubernetes·mybatis