程序通常通过与软件捆绑的配置来控制操作,环境变量允许用户在运行时设置它们。但是,在 Docker 容器中运行进程会使事情变得复杂,那么如何将环境变量传递给容器呢?
环境变量有什么用?
环境变量允许您将配置与应用程序的可执行文件分离。例如,您不想将生产数据库密码存储在您的代码库中——如果您这样做了,它将在 Git 中可见,并且任何有权访问您的代码的人都可以删除您的数据库。
相反,您使用环境变量对其进行设置,该变量存储一个简单的键值对,并允许您访问在同一 shell 会话中运行的任何应用程序中的值(它们不可全局访问)。这还具有能够为不同环境轻松定义不同配置的好处。例如,为开发和生产数据库使用单独的密钥,或者使用不同的 API 端点。
可以通过三种主要方式为 Docker 容器设置这些变量——使用 CLI 参数、.env配置文件或通过docker-compose.
使用命令行参数
用于启动 Docker 容器的命令docker run接受 ENV 变量作为参数。只需使用-e 标志、简写形式运行它–env,然后传入 key=value 对:
sudo docker run \
-e POSTGRES_USER='postgres' \
-e POSTGRES_PASSWORD='password' \
...
而且,如果您已经在运行该命令的环境中设置了这些环境变量,则可以直接按名称传递它们:
// set variable
POSTGRES_PASSWORD='password'
// use it later
docker run -e POSTGRES_PASSWORD -e POSTGRES_USER ...
.env 文件的额外安全性
使用 CLI 参数传递变量效果很好,但它有一个缺点——这些变量在主机上是可见的。它们记录在命令历史记录中,并且在已启动进程的进程列表中可见。
Linux 有一个内置的方法来管理这个权限——文件访问。将变量存储在 .env文件中允许您使用文件权限 ( chmod, chown)控制对该文件的访问。
.env 使用以下格式的变量创建一个文件,每个变量都在一个新行上:
POSTGRES_PASSWORD='password'
POSTGRES_USER='postgres'
APPLICATION_URL='example.com'
然后,将其docker run 与–env-file 标志一起传递给:
docker run --env-file ./envfile ...
使用 Docker-Compose
当然,很多人不会直接使用 Docker 启动容器docker run,而是选择使用一个docker-compose 文件来处理多个容器的配置,这些容器都代表一个应用程序。
要将环境变量传递给以这种方式启动的容器,您必须配置 compose 文件以将会话的变量传递给 Docker 容器。这里的配置将POSTGRES_USER 变量传递给构建环境和运行环境,如果不存在则设置一个默认值。
version: '3.1'
services:
my-service:
build:
context: .
args:
- POSTGRES_USER=${POSTGRES_USER:-default}
environment:
- POSTGRES_USER=${POSTGRES_USER:-default}
您需要在运行前设置环境变量docker-compose up,否则将无法访问它们。您可以将它们存储在 compose 文件中,但这通常是跟踪和版本化的,这违背了 env 变量的目的。
使用 Kubernetes
Kubernetes 是一个编排系统,可以处理跨网络运行的数百个容器。它仍然使用 Docker,但您只会接触配置,因此直接传递环境变量是行不通的。
相反,您可以在 Pod 的配置中定义它们:
apiVersion: v1
kind: Pod
metadata:
name: example
spec:
containers:
- ...
env:
- name: SERVICE_PORT
value: "80"
- name: SERVICE_IP
value: "172.17.0.1"
Kubernetes 很复杂,并且有很多不同的方式来处理环境变量。要了解更多信息,您可以阅读他们关于将数据注入 Pods 的指南。