Docker 入门学习笔记 04:环境变量到底在做什么,为什么很多容器都依赖它

本专栏文章导航

这一篇开始进入 Docker 运行配置里非常重要的一部分:

环境变量

如果前面端口映射解决的是“服务怎么暴露出来”,那么环境变量解决的就是:

服务运行时需要的配置,怎么传进去?

这个问题会一直贯穿后面的学习,包括:

  • Docker Compose
  • 数据库和缓存镜像的启动参数
  • 应用服务的运行模式
  • Kubernetes ConfigMap
  • Kubernetes Secret

所以环境变量不是一个小参数,而是容器运行时配置的核心方式之一。

一、为什么需要环境变量

同一个应用,在不同环境中通常需要不同配置。

例如:

  • 开发环境和生产环境的数据库地址不同
  • 服务监听端口不同
  • 日志级别不同
  • 是否开启调试模式不同
  • 第三方服务地址不同

如果把这些配置都写死在代码里,会带来很多问题:

  • 切换环境需要改代码
  • 容易把错误配置提交进仓库
  • 同一个镜像不方便复用

所以更合理的方式是:

镜像尽量保持通用,配置在容器启动时动态传入。

二、什么是环境变量

环境变量可以先理解成:

程序启动时能够读取的一组键值对配置。

例如:

APP_ENV=prod
APP_PORT=8088
DB_HOST=mysql

程序运行时可以读取这些值,然后决定:

  • 自己监听哪个端口
  • 连接哪个数据库
  • 使用什么运行模式

所以环境变量并不是 Docker 发明的。
它本来就是操作系统和程序运行时里非常常见的一种配置方式。

Docker 做的事情只是:

在启动容器时,把这些变量传给容器里的进程。

三、Docker 里怎么传环境变量

最常见的方式是:

-e 变量名=

例如:

docker run -e APP_ENV=dev -e APP_PORT=3000 my-app

这表示:

  • 给容器传一个 APP_ENV=dev
  • 再传一个 APP_PORT=3000

所以 -e 的本质就是:

把运行时配置传给容器里的程序。

四、先用最小实验验证:变量是否真的传进去了

理解环境变量时,最直接的实验方式之一是让容器把自己收到的变量直接打印出来。

例如:

docker run --rm -e APP_ENV=dev -e APP_PORT=3000 ubuntu env

这里可以顺手认识几个点:

  • --rm:容器退出后自动删除
  • -e:传入环境变量
  • ubuntu:使用 ubuntu 镜像
  • env:在容器里打印当前环境变量

如果运行成功,输出里通常能看到类似:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=b3a3d7eb4625
APP_ENV=dev
APP_PORT=3000
HOME=/root

这个实验说明了一件事:

环境变量确实已经被传进了容器。

五、再进一步验证:程序能不能真正读取这些变量

只看到变量被打印出来,还不够说明问题。

更关键的是:

容器里的程序会不会真正读取并使用这些变量?

可以用下面这个更贴近真实行为的实验:

docker run --rm -e APP_ENV=prod -e APP_PORT=8088 ubuntu bash -c 'echo APP_ENV=$APP_ENV; echo APP_PORT=$APP_PORT'

如果运行成功,会看到类似输出:

APP_ENV=prod
APP_PORT=8088

这一步比单纯执行 env 更重要,因为它证明了:

  • 变量不只是“存在于容器里”
  • 容器里的程序也确实能读取这些值

这才更接近真实应用的行为。

六、envbash -c 两种方式有什么区别

这两个实验都能帮助理解环境变量,但它们关注的重点不同。

1. env

例如:

docker run --rm -e APP_ENV=dev -e APP_PORT=3000 ubuntu env

它关注的是:

容器当前有哪些环境变量

这是在验证:

变量有没有被传进去

2. bash -c

例如:

docker run --rm -e APP_ENV=prod -e APP_PORT=8088 ubuntu bash -c 'echo APP_ENV=$APP_ENV; echo APP_PORT=$APP_PORT'

它关注的是:

容器里的程序能不能主动读取并使用这些变量

这是在验证:

变量能不能真正被程序消费

所以可以这样记:

  • env:看变量有没有进来
  • bash -c 'echo ...':看程序能不能读到它

七、--rm 在这里为什么很适合

在这类短平快的实验中,--rm 非常合适。

例如:

docker run --rm -e APP_ENV=prod ubuntu env

它表示:

容器执行完命令后,自动删除这个容器对象。

这样做的好处是:

  • 不会在 docker ps -a 里留下大量临时容器
  • 不会占用多余的容器名字
  • 非常适合验证型实验

这里也要注意一个边界:

--rm 删除的是容器,不是镜像。`

也就是说:

  • 容器会被清理掉
  • 镜像仍然保留在本地

八、环境变量这一块最容易混淆的地方

1. 环境变量不是 Docker 独有概念

Docker 只是把它带到了容器启动流程里。
它本质上还是程序运行时配置的一种常见方式。

2. 环境变量不会修改镜像本身

环境变量作用在容器运行时。
它不会直接把配置写回镜像。

也就是说:

  • 同一个镜像
  • 可以因为传入不同环境变量
  • 跑出不同配置效果

3. 环境变量不只是简单参数

很多真实应用都严重依赖环境变量,例如:

  • 数据库地址
  • 用户名和密码
  • 端口
  • 运行环境
  • 调试开关
  • 第三方服务地址

所以环境变量不是可有可无的补充,而是容器运行配置的重要入口。

九、这一部分学完后应该掌握什么

如果这一部分真正掌握了,应该能清楚表达这些内容:

  • 环境变量用于在容器启动时传递动态配置
  • -e 变量名=值 是最常见的传递方式
  • env 能验证变量是否传进了容器
  • bash -c 'echo ...' 能验证程序是否真的读取了变量
  • --rm 适合这类一次性实验,因为它会在容器退出后自动删除容器对象
  • 环境变量作用在运行时,不会直接修改镜像

十、这一部分最值得记住的一句话

如果只记一句话,最值得记住的是:

环境变量的关键不只是“传进去”,而是“容器里的程序会读取它”。

十一、下一步要学什么

环境变量讲清楚之后,下一步最自然的延伸就是:

数据卷

因为接下来会遇到另一个非常关键的问题:

如果容器删掉了,数据为什么会丢?

而这正是学习卷、持久化和后续数据库容器时必须理解的起点。

本专栏文章导航

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐