Docker编写共享环境变量 docker-compose.yml

Docker编写共享环境变量 docker-compose.yml,docker,environment-variables,containers,docker-compose,Docker,Environment Variables,Containers,Docker Compose,但是,主服务service1失败,因为它正在从数据库中查找环境变量 ${env.DBNAME_PORT_3306_TCP_ADDR} ${env.DBNAME_PORT_3306_TCP_PORT} ${env.DBNAME_ENV_MYSQL_DATABASE} 我知道compose docs声明“环境变量不再是连接到链接服务的推荐方法。只有在使用旧版1 compose文件格式时,才会填充环境变量。”但如果没有它们,我在这里就无能为力 这里的最佳实践是什么?谢谢 我认为您在理解docker

但是,主服务
service1
失败,因为它正在从数据库中查找环境变量

${env.DBNAME_PORT_3306_TCP_ADDR}
${env.DBNAME_PORT_3306_TCP_PORT}
${env.DBNAME_ENV_MYSQL_DATABASE}
我知道compose docs声明“环境变量不再是连接到链接服务的推荐方法。只有在使用旧版1 compose文件格式时,才会填充环境变量。”但如果没有它们,我在这里就无能为力


这里的最佳实践是什么?谢谢

我认为您在理解
docker compose.yml
文件是如何工作的方面有些错误

我看到的第一个问题是,您在
service1
服务的
links
部分的两个链接
db1
db2
中添加了相同的别名
dbname
。分号后面的部分是别名。你不必使用它

此外,当您使用链接时,不需要添加
depends_on
部分,链接会隐式包含它。此外,从文件格式的版本3中删除了
条件

至于你的问题,这里是我在链接容器时通常做的事情

首先,在应用程序中,根据环境变量对连接字符串进行参数化。根据您的编程语言/工具,这可能很简单,也可能不简单。为了简单起见,假设您可以像下面这样参数化连接字符串(来自Play Framework的示例):

connectionString=jdbc:postgresql://${DB\u HOST}:${DB\u PORT}/{DB\u NAME}

在Play Framework中,这意味着应从环境变量中读取
DB_主机
DB_端口
DB_名称
。您的框架可能具有类似或替代的结构

现在,正确链接docker compose文件中的服务

version: '2.1'
services:
  db1:
    [...]
    healthcheck: ..

  service1:
    [...]
    links:
      - db1:database1
然而,这还不够。如果您编写了
database1
而不是
DB\u HOST
,并在应用程序配置中硬编码了端口和数据库名称,则会出现这种情况。这也是可以接受的,但我希望我的应用程序配置尽可能独立于平台。这就是我设置从环境变量读取部分配置的原因(更不用说,这种方法对Docker:-)很好)

一些环境变量采用链接别名或链接本身的值,如
DB\u HOST:database1
。这看起来可能是多余的,但将应用程序与部署分开,IMHO

最后,我的服务看起来是这样的:

version: '2.1'
services:
  db1:
    [...]
    healthcheck: ..

  service1:
    [...]
    links:
      - db1:database1
    environment:
      - DB_HOST: database1
      - DB_PORT: 5432
      - DB_NAME: accounting

您可以对多个数据库使用相同的方法。

关于这一点的一些想法:

  • 链接相对不推荐使用,而支持基于DNS的服务发现。您仍然需要使用
    dependens\u
    来维护启动顺序

  • 使用
    docker stack deploy
    ,环境变量只在有限的方面消失了。由于您使用的是2.1版,很明显您使用的是
    docker compose
    。即使如此,
    docker stack deploy
    的环境变量部分还是能够将环境变量从主机扩展到yml文件中,而不是从yml文件扩展到容器中。即使没有了扩展,您也可以使用
    docker compose config
    作为预处理器来生成可用于
    docker stack deploy
    的yml。这是一个很长的说法,不要因为这个限制而改变你的设计

  • 因为我建议不要链接,所以网络别名可以很好地替代网络上同名的两个数据库

  • 我假设您定义了两个这样的数据库,以映射到单独的卷/文件系统或约束到单独的主机,等等。否则,扩展实例将允许您创建单个定义

结果如下:

version: '2.1'
services:
  db1:
    [...]
    healthcheck: ..
    networks:
      default:
        aliases:
         - dbname

  db2:
    [...]
    healthcheck: .. 
    networks:
      default:
        aliases:
         - dbname

  service1:
    [...]
    environment:
     - DBNAME_PORT_3306_TCP_ADDR: dbname
     - DBNAME_PORT_3306_TCP_PORT: 3306
     - DBNAME_ENV_MYSQL_DATABASE: yourdb
    depends_on:
      db1:
        condition: service_healthy
      db2:
        condition: service_healthy

只有一点需要澄清:斯塔克斯还不是实验性的吗?@AleksandarStojadinovic斯塔克斯已经退出实验一段时间了。使用docker compose.yml定义堆栈从1月发布的1.13.0版开始就已经过了。谢谢!这正是我想要的。谢谢!有一个问题,我应该用什么来代替v3中的
条件
?我需要健康检查来维持启动顺序,这就是我坚持使用2.1的原因
version: '2.1'
services:
  db1:
    [...]
    healthcheck: ..
    networks:
      default:
        aliases:
         - dbname

  db2:
    [...]
    healthcheck: .. 
    networks:
      default:
        aliases:
         - dbname

  service1:
    [...]
    environment:
     - DBNAME_PORT_3306_TCP_ADDR: dbname
     - DBNAME_PORT_3306_TCP_PORT: 3306
     - DBNAME_ENV_MYSQL_DATABASE: yourdb
    depends_on:
      db1:
        condition: service_healthy
      db2:
        condition: service_healthy