如何将环境变量传递给 Docker 容器?
How do I pass environment variables to Docker containers?
我是 Docker 的新手,不清楚如何从容器访问外部数据库。是在连接字符串中进行硬编码的最佳方式吗?
# Dockerfile
ENV DATABASE_URL amazon:rds/connection?string
您可以使用 -e
标志将环境变量传递给您的容器。
来自启动脚本的示例:
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
或者,如果您不想在命令行上使用 ps
显示的值,等等,-e
可以从当前的值中提取值环境如果你只是给它没有 =
:
sudo PASSWORD='foo' docker run [...] -e PASSWORD [...]
如果你有很多环境变量,特别是如果它们是秘密的,你可以 use an env-file:
$ docker run --env-file ./env.list ubuntu bash
The --env-file flag takes a filename as an argument and expects each line to be in the VAR=VAL format, mimicking the argument passed to --env. Comment lines need only be prefixed with #
您可以使用 -e
参数和 docker run ..
命令传递,如 here 和@errata 所述。
但是,这种方法可能存在的缺点是您的凭据将显示在您 运行 的进程列表中。
为了使其更安全,您可以将您的凭据写入配置文件,然后按照 here 中提到的 --env-file
执行 docker run
和 --env-file
。然后您可以控制该配置文件的访问权限,以便其他有权访问该机器的人不会看到您的凭据。
如果您使用 'docker-compose' 作为启动容器的方法,实际上有一种有用的方法可以将服务器上定义的环境变量传递给 Docker 容器。
在您的 docker-compose.yml
文件中,假设您正在启动一个基本的 hapi-js 容器,代码如下所示:
hapi_server:
container_name: hapi_server
image: node_image
expose:
- "3000"
假设您的 docker 项目所在的本地服务器有一个名为 'NODE_DB_CONNECT' 的环境变量,您想将其传递给您的 hapi-js 容器,并且您希望它的新名称是 'HAPI_DB_CONNECT'。然后在 docker-compose.yml
文件中,将本地环境变量传递给容器并重命名为:
hapi_server:
container_name: hapi_server
image: node_image
environment:
- HAPI_DB_CONNECT=${NODE_DB_CONNECT}
expose:
- "3000"
我希望这可以帮助您避免在容器中的任何文件中对数据库连接字符串进行硬编码!
使用-e
或--env
值设置环境变量(默认[])。
来自启动脚本的示例:
docker run -e myhost='localhost' -it busybox sh
如果您想从命令行使用多个环境,那么在每个环境变量之前使用 -e
标志。
示例:
sudo docker run -d -t -i -e NAMESPACE='staging' -e PASSWORD='foo' busybox sh
Note: Make sure put the container name after the environment variable, not before that.
如果需要设置很多变量,使用--env-file
标志
例如,
$ docker run --env-file ./my_env ubuntu bash
如需任何其他帮助,请查看 Docker 帮助:
$ docker run --help
官方文档:
https://docs.docker.com/compose/environment-variables/
对于 Amazon AWS ECS/ECR,您应该通过私有 S3 存储桶管理您的环境变量(尤其是机密)。请参阅博客 post How to Manage Secrets for Amazon EC2 Container Service–Based Applications by Using Amazon S3 and Docker。
使用 docker-compose
,您可以继承 docker-compose.yml 中的 env 变量,然后继承 docker-compose
调用的任何 Dockerfile 来构建图像。当 Dockerfile
RUN
命令应该执行特定于环境的命令时,这很有用。
(您的 shell 已在环境中存在 RAILS_ENV=development
)
docker-compose.yml:
version: '3.1'
services:
my-service:
build:
#$RAILS_ENV is referencing the shell environment RAILS_ENV variable
#and passing it to the Dockerfile ARG RAILS_ENV
#the syntax below ensures that the RAILS_ENV arg will default to
#production if empty.
#note that is dockerfile: is not specified it assumes file name: Dockerfile
context: .
args:
- RAILS_ENV=${RAILS_ENV:-production}
environment:
- RAILS_ENV=${RAILS_ENV:-production}
Dockerfile:
FROM ruby:2.3.4
#give ARG RAILS_ENV a default value = production
ARG RAILS_ENV=production
#assign the $RAILS_ENV arg to the RAILS_ENV ENV so that it can be accessed
#by the subsequent RUN call within the container
ENV RAILS_ENV $RAILS_ENV
#the subsequent RUN call accesses the RAILS_ENV ENV variable within the container
RUN if [ "$RAILS_ENV" = "production" ] ; then echo "production env"; else echo "non-production env: $RAILS_ENV"; fi
这样,我不需要在文件或docker-compose
build
/up
命令中指定环境变量:
docker-compose build
docker-compose up
如果您在本地 env.sh
中有环境变量并且想在容器启动时设置它,您可以尝试
COPY env.sh /env.sh
COPY <filename>.jar /<filename>.jar
ENTRYPOINT ["/bin/bash" , "-c", "source /env.sh && printenv && java -jar /<filename>.jar"]
此命令将以 bash shell 启动容器(我想要 bash shell 因为 source
是 bash命令),获取 env.sh
文件(设置环境变量)并执行 jar 文件。
env.sh
看起来像这样,
#!/bin/bash
export FOO="BAR"
export DB_NAME="DATABASE_NAME"
我添加 printenv
命令只是为了测试实际的 source 命令是否有效。当您确认 source 命令工作正常或者环境变量将出现在您的 docker 日志中时,您应该删除它。
另一种方法是使用/usr/bin/env
的权力:
docker run ubuntu env DEBUG=1 path/to/script.sh
如何将主机环境变量通过管道传输到 docker 容器有一个很好的技巧:
env > env_file && docker run --env-file env_file image_name
Use this technique very carefully, because env > env_file
will dump ALL host machine ENV variables to env_file
and make them accessible in the running container.
使用 jq 将 env 转换为 JSON:
env_as_json=`jq -c -n env`
docker run -e HOST_ENV="$env_as_json" <image>
这需要 jq 版本 1.6 或更高版本
这将主机环境设为 json,本质上与 Dockerfile 中的一样:
ENV HOST_ENV (all env from the host as json)
我们还可以使用主机环境变量使用 -e 标志和 $ :
在运行以下命令之前,需要导出(意味着设置)本地环境变量。
docker run -it -e MG_HOST=$MG_HOST \
-e MG_USER=$MG_USER \
-e MG_PASS=$MG_PASS \
-e MG_AUTH=$MG_AUTH \
-e MG_DB=$MG_DB \
-t image_tag_name_and_version
通过使用此方法,您可以使用给定的名称自动设置环境变量。就我而言(MG_HOST ,MG_USER)
此外:
如果您正在使用 python,您可以通过
在 docker 中访问这些环境变量
import os
host = os.environ.get('MG_HOST')
username = os.environ.get('MG_USER')
password = os.environ.get('MG_PASS')
auth = os.environ.get('MG_AUTH')
database = os.environ.get('MG_DB')
docker run --rm -it --env-file <(bash -c 'env | grep <your env data>')
是一种 grep 存储在 .env
中的数据并将它们传递给 Docker 的方法,而不会不安全地存储任何内容(因此您不能只查看 docker history
并获取密钥。
假设您的 .env
中有大量 AWS 内容,如下所示:
AWS_ACCESS_KEY: xxxxxxx
AWS_SECRET: xxxxxx
AWS_REGION: xxxxxx
运行 docker 和 docker run --rm -it --env-file <(bash -c 'env | grep AWS_')
将获取所有内容并安全地传递它以便从容器内访问。
我是这样解决的
docker run --rm -ti -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e AWS_SECURITY_TOKEN amazon/aws-cli s3 ls
再举一个例子:
export VAR1=value1
export VAR2=value2
$ docker run --env VAR1 --env VAR2 ubuntu env | grep VAR
VAR1=value1
VAR2=value2
我遇到的问题是我将 --env-file 放在命令的末尾
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-compose 传递多个环境变量,也可以在 docker-compose 文件中使用环境文件。
web:
env_file:
- web-variables.env
https://docs.docker.com/compose/environment-variables/#the-env_file-configuration-option
使用 docker run
.
设置环境变量的文档存在一些不一致之处
online referece 说了一件事:
--env , -e Set environment variables
manpage有点不同:
-e, --env=[] Set environment variables
docker run --help
又给出了一些东西:
-e, --env list Set environment variables
任何可用文档中不一定清楚的内容:
-e
或 --env
之后的尾随 space 可以替换为 =
,或者在 -e
的情况下可以完全省略:
$ docker run -it -ekey=value:1234 ubuntu env
key=value:1234
我通过反复试验发现的一个技巧(以及上面的线索)...
如果出现错误:
unknown flag: --env
然后 您可能会发现在 --env
中使用等号很有帮助,例如:
--env=key=value:1234
不同的容器启动方式可能会有不同的解析场景
在各种组合配置中使用 Docker 时,这些技巧可能会有所帮助,例如 Visual Studio Code devcontainer.json,其中 runArgs
数组中不允许使用 space。
我是 Docker 的新手,不清楚如何从容器访问外部数据库。是在连接字符串中进行硬编码的最佳方式吗?
# Dockerfile
ENV DATABASE_URL amazon:rds/connection?string
您可以使用 -e
标志将环境变量传递给您的容器。
来自启动脚本的示例:
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
或者,如果您不想在命令行上使用 ps
显示的值,等等,-e
可以从当前的值中提取值环境如果你只是给它没有 =
:
sudo PASSWORD='foo' docker run [...] -e PASSWORD [...]
如果你有很多环境变量,特别是如果它们是秘密的,你可以 use an env-file:
$ docker run --env-file ./env.list ubuntu bash
The --env-file flag takes a filename as an argument and expects each line to be in the VAR=VAL format, mimicking the argument passed to --env. Comment lines need only be prefixed with #
您可以使用 -e
参数和 docker run ..
命令传递,如 here 和@errata 所述。
但是,这种方法可能存在的缺点是您的凭据将显示在您 运行 的进程列表中。
为了使其更安全,您可以将您的凭据写入配置文件,然后按照 here 中提到的 --env-file
执行 docker run
和 --env-file
。然后您可以控制该配置文件的访问权限,以便其他有权访问该机器的人不会看到您的凭据。
如果您使用 'docker-compose' 作为启动容器的方法,实际上有一种有用的方法可以将服务器上定义的环境变量传递给 Docker 容器。
在您的 docker-compose.yml
文件中,假设您正在启动一个基本的 hapi-js 容器,代码如下所示:
hapi_server:
container_name: hapi_server
image: node_image
expose:
- "3000"
假设您的 docker 项目所在的本地服务器有一个名为 'NODE_DB_CONNECT' 的环境变量,您想将其传递给您的 hapi-js 容器,并且您希望它的新名称是 'HAPI_DB_CONNECT'。然后在 docker-compose.yml
文件中,将本地环境变量传递给容器并重命名为:
hapi_server:
container_name: hapi_server
image: node_image
environment:
- HAPI_DB_CONNECT=${NODE_DB_CONNECT}
expose:
- "3000"
我希望这可以帮助您避免在容器中的任何文件中对数据库连接字符串进行硬编码!
使用-e
或--env
值设置环境变量(默认[])。
来自启动脚本的示例:
docker run -e myhost='localhost' -it busybox sh
如果您想从命令行使用多个环境,那么在每个环境变量之前使用 -e
标志。
示例:
sudo docker run -d -t -i -e NAMESPACE='staging' -e PASSWORD='foo' busybox sh
Note: Make sure put the container name after the environment variable, not before that.
如果需要设置很多变量,使用--env-file
标志
例如,
$ docker run --env-file ./my_env ubuntu bash
如需任何其他帮助,请查看 Docker 帮助:
$ docker run --help
官方文档: https://docs.docker.com/compose/environment-variables/
对于 Amazon AWS ECS/ECR,您应该通过私有 S3 存储桶管理您的环境变量(尤其是机密)。请参阅博客 post How to Manage Secrets for Amazon EC2 Container Service–Based Applications by Using Amazon S3 and Docker。
使用 docker-compose
,您可以继承 docker-compose.yml 中的 env 变量,然后继承 docker-compose
调用的任何 Dockerfile 来构建图像。当 Dockerfile
RUN
命令应该执行特定于环境的命令时,这很有用。
(您的 shell 已在环境中存在 RAILS_ENV=development
)
docker-compose.yml:
version: '3.1'
services:
my-service:
build:
#$RAILS_ENV is referencing the shell environment RAILS_ENV variable
#and passing it to the Dockerfile ARG RAILS_ENV
#the syntax below ensures that the RAILS_ENV arg will default to
#production if empty.
#note that is dockerfile: is not specified it assumes file name: Dockerfile
context: .
args:
- RAILS_ENV=${RAILS_ENV:-production}
environment:
- RAILS_ENV=${RAILS_ENV:-production}
Dockerfile:
FROM ruby:2.3.4
#give ARG RAILS_ENV a default value = production
ARG RAILS_ENV=production
#assign the $RAILS_ENV arg to the RAILS_ENV ENV so that it can be accessed
#by the subsequent RUN call within the container
ENV RAILS_ENV $RAILS_ENV
#the subsequent RUN call accesses the RAILS_ENV ENV variable within the container
RUN if [ "$RAILS_ENV" = "production" ] ; then echo "production env"; else echo "non-production env: $RAILS_ENV"; fi
这样,我不需要在文件或docker-compose
build
/up
命令中指定环境变量:
docker-compose build
docker-compose up
如果您在本地 env.sh
中有环境变量并且想在容器启动时设置它,您可以尝试
COPY env.sh /env.sh
COPY <filename>.jar /<filename>.jar
ENTRYPOINT ["/bin/bash" , "-c", "source /env.sh && printenv && java -jar /<filename>.jar"]
此命令将以 bash shell 启动容器(我想要 bash shell 因为 source
是 bash命令),获取 env.sh
文件(设置环境变量)并执行 jar 文件。
env.sh
看起来像这样,
#!/bin/bash
export FOO="BAR"
export DB_NAME="DATABASE_NAME"
我添加 printenv
命令只是为了测试实际的 source 命令是否有效。当您确认 source 命令工作正常或者环境变量将出现在您的 docker 日志中时,您应该删除它。
另一种方法是使用/usr/bin/env
的权力:
docker run ubuntu env DEBUG=1 path/to/script.sh
如何将主机环境变量通过管道传输到 docker 容器有一个很好的技巧:
env > env_file && docker run --env-file env_file image_name
Use this technique very carefully, because
env > env_file
will dump ALL host machine ENV variables toenv_file
and make them accessible in the running container.
使用 jq 将 env 转换为 JSON:
env_as_json=`jq -c -n env`
docker run -e HOST_ENV="$env_as_json" <image>
这需要 jq 版本 1.6 或更高版本
这将主机环境设为 json,本质上与 Dockerfile 中的一样:
ENV HOST_ENV (all env from the host as json)
我们还可以使用主机环境变量使用 -e 标志和 $ :
在运行以下命令之前,需要导出(意味着设置)本地环境变量。
docker run -it -e MG_HOST=$MG_HOST \
-e MG_USER=$MG_USER \
-e MG_PASS=$MG_PASS \
-e MG_AUTH=$MG_AUTH \
-e MG_DB=$MG_DB \
-t image_tag_name_and_version
通过使用此方法,您可以使用给定的名称自动设置环境变量。就我而言(MG_HOST ,MG_USER)
此外:
如果您正在使用 python,您可以通过
在 docker 中访问这些环境变量import os
host = os.environ.get('MG_HOST')
username = os.environ.get('MG_USER')
password = os.environ.get('MG_PASS')
auth = os.environ.get('MG_AUTH')
database = os.environ.get('MG_DB')
docker run --rm -it --env-file <(bash -c 'env | grep <your env data>')
是一种 grep 存储在 .env
中的数据并将它们传递给 Docker 的方法,而不会不安全地存储任何内容(因此您不能只查看 docker history
并获取密钥。
假设您的 .env
中有大量 AWS 内容,如下所示:
AWS_ACCESS_KEY: xxxxxxx
AWS_SECRET: xxxxxx
AWS_REGION: xxxxxx
运行 docker 和 docker run --rm -it --env-file <(bash -c 'env | grep AWS_')
将获取所有内容并安全地传递它以便从容器内访问。
我是这样解决的
docker run --rm -ti -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e AWS_SECURITY_TOKEN amazon/aws-cli s3 ls
再举一个例子:
export VAR1=value1
export VAR2=value2
$ docker run --env VAR1 --env VAR2 ubuntu env | grep VAR
VAR1=value1
VAR2=value2
我遇到的问题是我将 --env-file 放在命令的末尾
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-compose 传递多个环境变量,也可以在 docker-compose 文件中使用环境文件。
web:
env_file:
- web-variables.env
https://docs.docker.com/compose/environment-variables/#the-env_file-configuration-option
使用 docker run
.
online referece 说了一件事:
--env , -e Set environment variables
manpage有点不同:
-e, --env=[] Set environment variables
docker run --help
又给出了一些东西:
-e, --env list Set environment variables
任何可用文档中不一定清楚的内容:
-e
或 --env
之后的尾随 space 可以替换为 =
,或者在 -e
的情况下可以完全省略:
$ docker run -it -ekey=value:1234 ubuntu env
key=value:1234
我通过反复试验发现的一个技巧(以及上面的线索)...
如果出现错误:
unknown flag: --env
然后 您可能会发现在 --env
中使用等号很有帮助,例如:
--env=key=value:1234
不同的容器启动方式可能会有不同的解析场景
在各种组合配置中使用 Docker 时,这些技巧可能会有所帮助,例如 Visual Studio Code devcontainer.json,其中 runArgs
数组中不允许使用 space。