如何将环境变量传递给Docker容器?

我是Docker新手,不清楚如何从容器访问外部数据库。在连接字符串中硬编码的最佳方法是什么?

# DockerfileENV DATABASE_URL amazon:rds/connection?string
1450535 次浏览

您可以使用-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 [...]

如果你有很多环境变量,特别是如果它们是秘密的,你可以使用env文件

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

--env-file标志将文件名作为参数,并期望每行采用VAR=VAL格式,模仿传递给--env的参数。注释行只需以#为前缀

您可以使用-e参数和docker run ..命令传递,如这里和@errata所述。

但是,这种方法可能存在的缺点是,您的凭据将显示在运行它的进程列表中。

为了使其更安全,您可以在配置文件中写入您的凭据,并按照这里所述对--env-file执行docker run操作。然后您可以控制该配置文件的访问权限,以便有权访问该机器的其他人不会看到您的凭据。

如果您使用“docker-compose”作为启动容器的方法,实际上有一种有用的方法可以将服务器上定义的环境变量传递给Docker容器。

docker-compose.yml文件中,假设您正在启动一个基本的hapi-js容器,代码如下所示:

hapi_server:container_name: hapi_serverimage: node_imageexpose:- "3000"

假设您的docker项目所在的本地服务器有一个名为“NODE_DB_CONNECT”的环境变量,您想将其传递给hapi-js容器,并且您希望其新名称为“HAPI_DB_CONNECT”。然后在docker-compose.yml文件中,您将本地环境变量传递给容器并将其重命名为:

hapi_server:container_name: hapi_serverimage: node_imageenvironment:- 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

注意:确保将容器名称放在环境变量之后,而不是之前。

如果您需要设置许多变量,请使用--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存储桶管理环境变量(尤其是秘密)。

使用docker-compose,您可以继承docker-compose.yml中的env变量,然后继承docker-compose调用的任何Dockerfile来构建映像。当DockerfileRUN命令应该执行特定于环境的命令时,这很有用。

(您的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: Dockerfilecontext: .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 = productionARG 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 containerENV RAILS_ENV $RAILS_ENV
#the subsequent RUN call accesses the RAILS_ENV ENV variable within the containerRUN if [ "$RAILS_ENV" = "production" ] ; then echo "production env"; else echo "non-production env: $RAILS_ENV"; fi

这样,我不需要在文件或docker-composebuild/up命令中指定环境变量:

docker-compose builddocker-compose up

如果环境变量在本地env.sh中,并且想在容器启动时设置它,您可以尝试

COPY env.sh /env.shCOPY <filename>.jar /<filename>.jarENTRYPOINT ["/bin/bash" , "-c", "source /env.sh && printenv && java -jar /<filename>.jar"]

此命令将使用bash shell启动容器(我想要一个bash shell,因为source是bash命令),获取env.sh文件(设置环境变量)并执行jar文件。

env.sh看起来像这样。

#!/bin/bashexport FOO="BAR"export DB_NAME="DATABASE_NAME"

我添加printenv命令只是为了测试实际的源命令是否有效。当您确认源命令正常工作或环境变量将出现在您的docker日志中时,您可能应该删除它。

另一种方法是使用/usr/bin/env的幂:

docker run ubuntu env DEBUG=1 path/to/script.sh

有一个很好的hack如何将主机环境变量管道到docker容器:

env > env_file && docker run --env-file env_file image_name

非常小心地使用这种技术,因为env > env_file所有主机ENV变量转储到env_file并使它们在运行的容器中可访问。

使用jq将env转换为JSON:

env_as_json=`jq -c -n env`docker run -e HOST_ENV="$env_as_json" <image>

这需要jq版本1.6或更高版本

这将主机env设置为json,本质上与Dockerfile中的类似:

ENV HOST_ENV  (all env from the host as json)

我们还可以使用-e标志和$使用主机环境变量:

在运行以下命令之前,需要导出(意味着设置)本地env变量。

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: xxxxxxxAWS_SECRET: xxxxxxAWS_REGION: xxxxxx

使用docker run --rm -it --env-file <(bash -c 'env | grep AWS_')运行docker将获取所有内容并安全地传递它以从容器内访问。

我是这样解决的

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=value1export VAR2=value2
$ docker run --env VAR1 --env VAR2 ubuntu env | grep VARVAR1=value1VAR2=value2

我遇到的问题是我把--env文件放在命令的末尾

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-com含传递多个环境变量,一个环境文件也可以在docker-com含文件中使用。

web:env_file:- web-variables.env

https://docs.docker.com/compose/environment-variables/#the-env_file-configuration-option

使用docker run设置环境变量存在一些留档不一致。

在线裁判说了一件事:

--env,-e设置环境变量

manpage有点不同:

-e,--env=[]设置环境变量

docker run --help再次给出了其他东西:

-e,--env list设置环境变量


在任何可用的留档中不一定清楚的东西:

-e--env之后的尾随空格可以替换为=,或者在-e的情况下可以完全省略:

$ docker run -it -ekey=value:1234 ubuntu envkey=value:1234

我通过反复试验发现的一个技巧(以及上面的线索)…

如果你得到错误:

未知标志:--env

然后您可能会发现使用#0的等于号很有帮助,例如:

--env=key=value:1234

启动容器的不同方法可能有不同的解析方案。


在各种组合配置中使用Docker时,这些技巧可能会有所帮助,例如Visual Studio Codedevcontainer.json,其中runArgs数组中不允许空格。

您可以使用-e或--env作为参数,后跟键值格式例如:docker build-ffile_name-eMYSQL_ROOT_PASSWORD=root

要将环境导入容器,您可以在docker-compose.yaml中使用env_file:,或者您可以将.env文件复制到容器,然后使用扩展库读取。

python项目

您可以使用python-dotenv包:

pip install python-dotenv

然后在代码中:

import osfrom dotenv import load_dotenv    
load_dotenv()SECRET_KEY = os.getenv("MY_SECRET")

Golang项目

github.com/joho/godotenv包:

go get github.com/joho/godotenv

在您的代码中:

package main
import ("github.com/joho/godotenv""log""os")
func main() {err := godotenv.Load()if err != nil {log.Fatal("Error loading .env file")} 
secretKey := os.Getenv("MY_SECRET")
}