我是 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
可以从当前环境中提取值,如果您只是在没有 { 的情况下提供它3}:
sudo PASSWORD='foo' docker run [...] -e PASSWORD [...]
如果您有许多环境变量,特别是如果它们是保密的,您可以use an env-file:
$ docker run --env-file ./env.list ubuntu bash
--env-file 标志将文件名作为参数,并期望每一行采用 VAR=VAL 格式,模仿传递给 --env 的参数。注释行只需要以# 为前缀
您可以使用 -e
参数与 docker run ..
命令一起传递,如 here 和 @errata 所述。
但是,这种方法可能的缺点是您的凭据将显示在您运行它的进程列表中。
为了使其更安全,您可以在配置文件中写入您的凭据,然后使用 --env-file
执行 docker run
,如提到的 here。然后您可以控制该配置文件的访问权限,以便其他有权访问该计算机的人看不到您的凭据。
--env-file
,当您使用 --env
时,您的 env 值将使用您正在使用的任何 shell 的标准语义进行引用/转义,但在使用 --env-file
时,您将在容器中获得的值会有所不同。 docker run 命令只是读取文件,进行非常基本的解析并将值传递给容器,它并不等同于你的 shell 的行为方式。如果您要将一堆 --env
条目转换为 --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
注意:确保将容器名称放在环境变量之后,而不是之前。
如果您需要设置许多变量,请使用 --env-file
标志
例如,
$ docker run --env-file ./my_env ubuntu bash
如需任何其他帮助,请查看 Docker 帮助:
$ docker run --help
官方文档:https://docs.docker.com/compose/environment-variables/
ubuntu bash
?它适用于使用 ubuntu 作为基础镜像创建的镜像还是每个镜像?
bash
为您提供了一个终端(尽管我认为您需要 -it 作为交互式终端)。
使用 docker-compose
,您可以继承 docker-compose.yml 中的环境变量,然后继承 docker-compose
调用的任何 Dockerfile(s) 以构建映像。这在 Dockerfile
RUN
命令应该执行特定于环境的命令时很有用。
(您的外壳 RAILS_ENV=development
已存在于环境中)
码头工人-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
我们还可以使用 -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
命令有问题,值得注意的是 env 变量 -e
必须在 -t
之前,如图所示。我把我的放在图像之后,但它不起作用。
有一个很好的 hack 如何将主机环境变量通过管道传输到 docker 容器:
env > env_file && docker run --env-file env_file image_name
非常小心地使用这种技术,因为 env > env_file 会将所有主机 ENV 变量转储到 env_file 并使其在运行的容器中可访问。
docker run --env-file =(env) image_name
我遇到的问题是我将 --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
另一种方法是使用 /usr/bin/env
的幂:
docker run ubuntu env DEBUG=1 path/to/script.sh
对于 Amazon AWS ECS/ECR,您应该通过私有 S3 存储桶管理您的环境变量(尤其是机密)。请参阅博文How to Manage Secrets for Amazon EC2 Container Service–Based Applications by Using Amazon S3 and Docker。
如果您在本地的 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
命令只是为了测试实际的源命令是否有效。当您确认源命令正常工作或环境变量将出现在您的 docker 日志中时,您可能应该将其删除。
--env-file
参数指定给 docker run
命令的选项。例如,如果您使用 Google 应用引擎部署应用程序,并且在容器内运行的应用程序需要在 docker 容器内设置环境变量,则您无法直接设置环境变量,因为您无法控制 { 2}命令。在这种情况下,您可以使用 KMS 解密 env 变量的脚本,并将它们添加到 env.sh
中,该 env.sh
可用于设置 env 变量。
sh
而不是 source
中可用的 POSIX .
(点)命令。 (source
与 .
相同)
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 run --rm -it --env-file <(bash -c 'env | grep AWS_')
运行 docker 将全部抓取并安全地传递它,以便从容器内访问。
使用 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)
docker run -e HOST_ENV="$env_as_json" <image>
?在我的情况下,当作为 docker args 传递时,Docker 似乎没有解析变量或子 shell(${}
或 $()
)。例如:A=123 docker run --rm -it -e HE="$A" ubuntu
然后在该容器内:root@947c89c79397:/# echo $HE root@947c89c79397:/#
.... HE
变量没有成功。
这就是我能够解决它的方法
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
为了通过 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 设置环境变量
manpage 有点不同:
-e, --env=[] 设置环境变量
docker run --help
再次给出了其他内容:
-e, --env list 设置环境变量
在任何可用文档中都不一定清楚的东西:
-e
或 --env
之后的尾随空格可以替换为 =
,或者在 -e
的情况下可以完全省略:
$ docker run -it -ekey=value:1234 ubuntu env
key=value:1234
我通过反复试验发现的一个技巧(以及上面的线索)......
如果您收到错误消息:
未知标志:--env
那么您可能会发现在 --env
中使用等号会很有帮助,例如:
--env=key=value:1234
启动容器的不同方法可能有不同的解析场景。
在各种组合配置中使用 Docker 时,这些技巧可能会有所帮助,例如 Visual Studio Code devcontainer.json,其中 runArgs
数组中不允许有空格。
您可以使用 -e 或 --env 作为参数,后跟键值格式,例如: docker build -f file_name -e MYSQL_ROOT_PASSWORD=root
不定期副业成功案例分享
export PASSWORD=foo
,变量将作为环境变量传递给docker run
,使docker run -e PASSWORD
工作。-e
和 Dockerfile 中的ENV
做同样的事情吗?-e
值,否则不会引发错误,并且所有变量都不会有值!