如何从容器访问外部数据库?在连接字符串中硬编码是最好的方法吗?

# 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 [...]

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

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

——env-file标志以文件名作为参数,并期望每行都是VAR=VAL格式,模拟传递给——env的参数。注释行只需加上#前缀

其他回答

假设你有一个启动MySQL数据库容器的用例,所以你需要传递以下变量

docker run -dit --name db1 -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=mydb -e MYSQL_USER=jack -e MYSQL_PASSWORD=redhat mysql:5.7

使用docker-compose,你可以在docker-compose中继承env变量。yml和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

使用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 environment from the host as JSON)

你可以在docker run ..这里提到的和勘误表中提到的命令。

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

为了让它更安全,你可以把你的凭证写在一个配置文件中,并像这里提到的那样使用——env-file运行docker。然后,您可以控制对该配置文件的访问,以便其他有权访问该机器的人不会看到您的凭据。

对于Amazon AWS ECS/ECR,您应该通过私有S3桶管理您的环境变量(特别是秘密变量)。请参阅如何使用Amazon S3和Docker管理基于Amazon EC2容器服务的应用程序的机密。