我是Docker的新手,并且不清楚如何从容器访问外部数据库。是连接字符串中硬编码的最佳方法吗?
pause.png
答案 0 :(得分:933)
您可以使用-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
--env-file标志将文件名作为参数,并期望每一行都是VAR = VAL格式,模仿传递给--env的参数。注释行只需要以#
为前缀
答案 1 :(得分:82)
您可以使用-e
命令传递docker run ..
参数here,如@errata所述。
但是,这种方法的可能缺点是您的凭据将显示在您运行它的流程列表中
为了使其更安全,您可以在配置文件中编写凭据,并按照here的docker run
进行--env-file
。然后,您可以控制该配置文件的访问权限,以便有权访问该计算机的其他人无法查看您的凭据。
答案 2 :(得分:43)
如果您使用'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"
我希望这可以帮助您避免在容器中的任何文件中对数据库连接字符串进行硬编码!
答案 3 :(得分:20)
使用-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/
答案 4 :(得分:17)
使用docker-compose
,下面的示例显示了如何在docker-compose.yml中继承shell env变量,以及由docker-compose
调用以构建映像的任何Dockerfile。我发现这很有用,如果在Dockerfile
RUN
命令中我需要执行特定于环境的命令。
(您的shell已在环境中存在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
答案 5 :(得分:6)
有一个不错的技巧,如何将主机环境变量通过管道传递给docker容器:
env > env_file && docker run --env-file env_file image_name
请非常小心地使用此技术,因为
env > env_file
会将 ALL 主机ENV变量转储到env_file
并使它们在运行的容器中可访问。
答案 6 :(得分:4)
对于Amazon AWS ECS / ECR,您应该通过专用S3存储桶管理环境变量(特别是机密)。请参阅博客文章 How to Manage Secrets for Amazon EC2 Container Service–Based Applications by Using Amazon S3 and Docker 。
答案 7 :(得分:4)
另一种方法是使用data.frame
:
/usr/bin/env
答案 8 :(得分:2)
如果您在本地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日志中时,您应该删除它。
答案 9 :(得分:1)
我们还可以使用-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
通过这种方法,在我的情况下,使用您的给定名称自动设置env变量(MG_HOST,MG_USER)
如果您使用的是python,则可以通过以下方式在docker内部访问这些envment变量
import os
host,username,password,auth,database=os.environ.get('MG_HOST'),os.environ.get('MG_USER'),os.environ.get('MG_PASS'),os.environ.get('MG_AUTH'),os.environ.get('MG_DB')
答案 10 :(得分:1)
这是我解决问题的方式
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
答案 11 :(得分:0)
使用jq将环境转换为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)
答案 12 :(得分:0)
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会将其全部捕获并安全地传递给它,以便可以从容器内部进行访问。< / p>
答案 13 :(得分:0)
我遇到的问题是我将--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