如何向Docker容器传递环境变量

如何向Docker容器传递环境变量

技术背景

在使用Docker容器时,常常需要为容器设置环境变量,以满足不同的配置需求。例如,设置数据库连接信息、API密钥等。环境变量的传递可以让容器在不同的环境中灵活运行,避免硬编码配置信息。

实现步骤

使用 -e--env 标志

可以使用 -e--env 的别名)标志将环境变量传递给容器。例如:

1
docker run -e xx=yy

具体示例:

1
2
3
4
5
6
7
8
9
sudo docker run -d -t -i -e REDIS_NAMESPACE='staging' \
-e POSTGRES_ENV_POSTGRES_PASSWORD='foo' \
-e POSTGRES_ENV_POSTGRES_USER='bar' \
-e POSTGRES_ENV_DB_NAME='mysite_staging' \
-e POSTGRES_PORT_5432_TCP_ADDR='docker-db-1.hidden.us-east-1.rds.amazonaws.com' \
-e SITE_URL='staging.mysite.com' \
-p 80:80 \
--link redis:redis \
--name container_name dockerhub_id/image_name

如果不想在命令行中显示环境变量的值,可以直接使用 -e 引用当前环境中的变量:

1
sudo PASSWORD='foo' docker run  [...] -e PASSWORD [...]

使用 --env-file 标志

当有许多环境变量,尤其是需要保密的变量时,可以使用 --env-file

1
docker run --env-file ./env.list ubuntu bash

--env-file 标志接受一个文件名作为参数,要求每行格式为 VAR=VAL

docker-compose.yml 中传递环境变量

如果使用 docker-compose,可以在 docker-compose.yml 文件中传递环境变量。例如,将本地环境变量 NODE_DB_CONNECT 传递给容器并重命名为 HAPI_DB_CONNECT

1
2
3
4
5
6
7
hapi_server:
container_name: hapi_server
image: node_image
environment:
- HAPI_DB_CONNECT=${NODE_DB_CONNECT}
expose:
- "3000"

继承环境变量

docker-compose.ymlDockerfile 中可以继承环境变量。示例如下:
docker-compose.yml

1
2
3
4
5
6
7
8
9
version: '3.1'
services:
my-service:
build:
context: .
args:
- RAILS_ENV=${RAILS_ENV:-production}
environment:
- RAILS_ENV=${RAILS_ENV:-production}

Dockerfile

1
2
3
4
5
6
FROM ruby:2.3.4

ARG RAILS_ENV=production
ENV RAILS_ENV $RAILS_ENV

RUN if [ "$RAILS_ENV" = "production" ] ; then echo "production env"; else echo "non-production env: $RAILS_ENV"; fi

核心代码

使用 -e 传递多个环境变量

1
sudo docker run -d -t -i -e NAMESPACE='staging' -e PASSWORD='foo' busybox sh

使用 --env-file 传递环境变量

1
docker run --env-file ./my_env ubuntu bash

docker-compose.yml 中传递环境变量

1
2
3
4
5
6
7
hapi_server:
container_name: hapi_server
image: node_image
environment:
- HAPI_DB_CONNECT=${NODE_DB_CONNECT}
expose:
- "3000"

最佳实践

  • 使用 --env-file:当有大量环境变量或敏感信息时,使用 --env-file 可以更好地组织和管理环境变量。
  • 使用 docker-compose:对于复杂的应用,使用 docker-compose 可以更方便地管理多个容器的环境变量。
  • 避免硬编码:尽量避免在容器内硬编码环境变量,而是通过传递环境变量的方式进行配置。

常见问题

docker run 中引号问题

docker run 子命令不接受格式为有效BASH脚本的 env 文件,会将引号视为环境变量值的一部分。可以使用以下解决方案:

  1. 创建 Dockerfile
1
2
3
4
5
6
7
FROM python:3.10-slim-buster
WORKDIR /some-name
COPY . /some-name/
RUN apt-get -y update \
&& apt-get -y upgrade \
[...]
ENTRYPOINT bash entrypoint.bash
  1. 创建 env 文件(.env):
1
2
3
4
5
#!/bin/bash

SOME_ENV_VAR_A="some value a"
SOME_ENV_VAR_B="some value b"
SOME_ENV_VAR_C="some value c"
  1. 创建 ENTRYPOINT 的BASH脚本文件(entrypoint.bash):
1
2
3
4
#!/bin/bash

set -a;source <(echo -n "$ENV_VARS");set +a
python main.py
  1. 使用 run 子命令注入环境变量:
1
docker run -it --name "some-ctn-name" --env ENV_VARS="$(cat ./.env)" "some-img-name:Dockerfile"

--env 标志错误

如果遇到 unknown flag: --env 错误,可以使用等号 --env=key=value

--env-file 位置问题

--env-file 应放在 docker run 命令中选项部分,而不是放在命令末尾。例如:

1
2
3
4
# 错误示例
docker run -it --rm -p 8080:80 imagename --env-file ./env.list
# 正确示例
docker run --env-file ./env.list -it --rm -p 8080:80 imagename

如何向Docker容器传递环境变量
https://119291.xyz/posts/how-to-pass-environment-variables-to-docker-containers/
作者
ww
发布于
2025年6月9日
许可协议