如何根据已调用的角色自动生成docker-compose文件

123次阅读
没有评论

问题描述

正在编写一个Ansible playbook,用于在集群环境中部署服务。有3种类型的主机(应用程序、负载均衡器、数据库)。服务是通过docker-compose在每个主机上分别部署的。
以下是部署到数据库主机的playbook示例:

- name:           Deploy database node.
  hosts:          databases
  become:         yes
  become_method:  sudo
  roles:
  - common
  - zabbix-agent
  - database
  - backup

Ansible play需要根据在主机上调用的角色动态生成一个docker-compose文件。因此,这个示例需要生成一个列出这些角色的docker-compose文件。
如何根据已调用的角色自动生成一个docker-compose.yml文件?
我已经考虑过:
– Ansible facts
– Tags
– 全局布尔变量 [yuck],但是我觉得这些都不是正确的方法。
如果有更好的方法来实现我的目标,我也愿意听取任何其他建议。
编辑:

你能解释一下容器里面有什么吗?
‘common’角色当前在目标主机上安装Docker和docker-compose。
‘database’启动一个mariadb容器。
‘zabbix-agent’在主机上安装zabbix agent。
‘backup’复制一些shell脚本。
数据库是在容器中还是与数据库并行运行的容器?
数据库是一个mariadb Docker容器。因此,我的compose文件将需要包含一个’mariadb’部分。
对于你来说,一个好的docker-compose.yml文件应该是什么样子的?
好问题。像这样:

version:                            '2.2'
services:
  terracotta:
    image:                          terracotta/terracotta-server-oss:5.5.1
    container_name:                 terracotta
    restart:                        always
    networks:
      - skyNet
    logging:
      driver:                       "json-file"
      options:
        max-size:                   "10m"
        max-file:                   "5"
  mariadb:
    image:                          mariadb/server:{{docker_mariadb_version}}
    container_name:                 mariadb
    restart:                        always
    logging:
      driver:                       "json-file"
      options:
        max-size:                   "10m"
        max-file:                   "5"
    networks:
      - skyNet
    ports:
    - 127.0.0.1:3306:3306/tcp
    volumes:
      - /opt/mariadb/data:/var/lib/mysql
    environment:
      MARIADB_ROOT_PASSWORD:        "{{database_root_password}}"
# Network
networks:
  skyNet:
    driver:                         bridge

我需要能够通过标签或其他方式切换将哪些服务添加到compose文件中。也许我应该改变我的问题的措辞?

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

根据你的问题描述,你不需要动态生成docker-compose.yml文件。你已经在一个明确的网络上部署了东西;只需将其作为单独的compose文件外部化即可。也就是说,执行以下等效操作:

docker network create skyNet

然后修改你的compose配置文件,将其作为外部网络引用:

services:
  mariadb:
    image:                          mariadb/server:{{docker_mariadb_version}}
    container_name:                 mariadb
    restart:                        always
    logging:
      driver:                       "json-file"
      options:
        max-size:                   "10m"
        max-file:                   "5"
    networks:
      - skyNet
    ports:
    - 127.0.0.1:3306:3306/tcp
    volumes:
      - /opt/mariadb/data:/var/lib/mysql
    environment:
      MARIADB_ROOT_PASSWORD:        "{{database_root_password}}"
networks:
  skyNet:
    external: true

你可以让每个角色管理自己的docker-compose.yaml文件(并负责启动堆栈)。因为它们共享一个网络,即使它们在不同的文件中定义,名称查找也会按预期工作。

方案2

使用脚本或工具来管理容器的启动顺序可能会增加复杂性,并且需要确保容器A和容器B之间的依赖关系正确设置。
另一种方法是编写脚本或使用工具来控制容器的运行顺序。你可以使用docker run命令来手动控制容器的启动顺序,或者使用一些第三方工具来管理容器的依赖关系。

示例:

以下是一个简单的bash脚本示例,可以在容器A启动后启动容器B:

#!/bin/bash
# 启动容器A
docker run -d --name container_a your_image_a
# 等待容器A完全启动
while ! docker exec container_a echo "Container A is ready"; do
  sleep 1
done
# 启动容器B
docker run -d --name container_b your_image_b

在这个示例中,我们首先使用docker run命令启动容器A,并将其命名为container_a。然后,使用一个循环来等待容器A完全启动(这里是通过在容器内运行echo命令来测试)。一旦容器A就绪,我们再使用docker run命令启动容器B,并将其命名为container_b

正文完