1. 简介

在 Ansible 中使用 Docker Compose 可以简化多容器应用生命周期的自动化管理。但与直接在命令行中运行 docker-compose 相比,其语法并不那么直观。

在本教程中,我们将讨论如何在 Ansible 中使用 Docker Compose,并提供一个实际示例来演示其用法。

2. 创建 Docker Compose 配置文件

与在命令行中使用 Docker Compose 一样,我们需要一个 YAML 格式的配置文件。

下面是一个包含 PostgreSQL 数据库和 Adminer 的多容器应用配置示例:

$ cat docker-compose.yml
services:
  database:
    image: postgres
    restart: always
    environment:
      POSTGRES_PASSWORD=test
  adminer:
    image: adminer:latest
    restart: always
    ports:
      - "5000:8080"
    depends_on:
      - database

⚠️ 注意:我们省略了 version 字段,因为该字段在新版本中已不再推荐使用。

这个 docker-compose.yml 文件会创建一个名为 database 的 PostgreSQL 服务,并设置密码为 test。在真实项目中,我们通常会使用环境变量等方式来避免硬编码敏感信息。

adminer 服务依赖于 database 服务,因此它会在数据库服务启动后创建,并在数据库服务关闭前停止。同时,adminer 容器的 8080 端口会映射到主机的 5000 端口,因此我们可以通过访问主机的 5000 端口来访问 Adminer。

3. 创建 Ansible Playbook

有了 docker-compose.yml 文件后,接下来我们创建 Ansible playbook 文件 playbook.yml

$ cat playbook.yml
- name: Docker Compose in Ansible
  hosts: localhost
  tasks:
    - name: create and start docker compose services
      community.docker.docker_compose_v2:
        project_src: .

该 playbook 将使用 community.docker.docker_compose_v2 模块来创建并启动我们在 docker-compose.yml 中定义的服务。

参数 project_src 指定包含 docker-compose.yml 的目录。因为我们当前的 playbook 和 compose 文件在同一目录下,所以使用 . 表示当前目录。

如果你的 compose 文件名不是默认的 docker-compose.ymlcompose.yml,你需要使用 files 参数显式指定文件名。

例如,如果你的 compose 文件名为 d_compose.yml,并且位于子目录 sub 中,你可以这样写:

$ cat playbook.yml
...truncated...  
tasks:
    - name: create and deploy docker compose services
      community.docker.docker_compose_v2:
        project_src: ./sub
        files: d_compose.yml

4. 运行 Ansible Playbook

现在我们来运行这个 playbook:

$ ansible-playbook playbook.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match
'all'

PLAY [Docker Compose in Ansible] ***************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
ok: [localhost]

TASK [create and start docker compose services] ************************************************************************
changed: [localhost]

PLAY RECAP *************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

我们可以使用 w3m 测试访问 Adminer:

$ w3m http://localhost:5000
Login

 System  [MySQL               ]
 Server  [db                  ]
Username [                    ]
Password [                    ]
Database [                    ]

[Login] [ ]Permanent login
Language: [English           ] [Use]
Adminer 4.8.1

成功访问 Adminer 页面说明服务已正确启动。

5. 停止并删除容器

当前 playbook 只包含创建和启动容器的任务。如果我们想停止并删除容器,可以添加一个任务:

$ cat playbook.yml
- name: Docker Compose in Ansible
  hosts: localhost
  tasks:
    - name: create and start docker compose services
      community.docker.docker_compose_v2:
        project_src: .
    - name: stop and remove docker compose services
      community.docker.docker_compose_v2:
        project_src: .
        state: absent

但这样运行时会连续执行创建和删除操作。为了避免这种情况,我们可以为每个任务添加 tags,使其可以独立执行:

$ cat playbook.yml
- name: Docker Compose in Ansible
  hosts: localhost
  tasks:
    - name: create and start docker compose services
      community.docker.docker_compose_v2:
        project_src: .
      tags: create

    - name: stop and remove docker compose services
      community.docker.docker_compose_v2:
        project_src: .
        state: absent
      tags: destroy

现在我们可以通过指定 tag 来运行特定任务:

✅ 启动服务:

$ ansible-playbook playbook.yml --tags create

✅ 停止并删除服务:

$ ansible-playbook playbook.yml --tags destroy

服务被删除后,再次访问 http://localhost:5000 将失败:

$ w3m http://localhost:5000
w3m: Can't load http://localhost:5000.

但你可以随时重新启动服务。

6. 使用 command 模块

除了使用 community.docker.docker_compose_v2 模块,我们也可以使用 Ansible 的内置 command 模块来运行 Docker Compose 命令:

$ cat playbook.yml
- name: Docker Compose in Ansible
  hosts: localhost
  tasks:
    - name: create and start docker compose services
      command: docker compose up -d
      tags: create

    - name: stop and remove docker compose services
      command: docker compose down
      tags: destroy

运行测试:

✅ 启动服务:

$ ansible-playbook playbook.yml --tags create

✅ 停止服务:

$ ansible-playbook playbook.yml --tags destroy

⚠️ 但需要注意:虽然 command 模块也能实现功能,但它的幂等性不如 community.docker.docker_compose_v2 模块。随着 playbook 变得复杂,维护起来也会更困难。

7. 总结

在本文中,我们介绍了如何在 Ansible 中使用 Docker Compose:

  • 使用 community.docker.docker_compose_v2 模块可以更优雅地管理容器服务生命周期
  • 使用 command 模块也可以实现功能,但可维护性较差
  • 通过 tags 可以实现任务的按需执行,提高灵活性

✅ 推荐做法:优先使用 community.docker.docker_compose_v2 模块,因其具备更好的幂等性和可读性,适合中大型自动化部署场景。


原始标题:How to Use Docker Compose in Ansible