1. 概述
在管理 Docker 容器时,我们通常会手动执行一系列 CLI 命令。当只有一两个容器时,这种方式或许可行,但当我们面对多个服务、环境或配置时,这种手动操作容易出错且效率低下。这时我们可以借助 Ansible,它是一个自动化工具,通过名为 playbook 的 YAML 文件在多台系统上执行任务。
更方便的是,Ansible 可以与 Docker 等工具集成,使我们能够轻松实现 Docker 命令的自动化执行、容器部署,甚至是编排。
在本教程中,我们将通过一个实际且易懂的示例,学习如何使用 Ansible 来运行 Docker 命令。文中将以 Ubuntu Linux 系统为例,演示如何结合 Docker Engine 和 Ansible 使用。
2. 为什么要使用 Ansible 来运行 Docker 命令?
以下是几个使用 Ansible 来运行 Docker 或 Docker Compose 命令的常见原因:
- 作为 CI/CD 流水线的一部分自动部署容器
- 避免重复执行相同的命令行操作
- 通过自动化简化开发流程
- 统一配置本地或测试环境
✅ 使用 Ansible,我们可以对 Docker 的工作流进行版本控制,并轻松复用。
3. 问题描述
我们的问题是:使用 Ansible 来运行 Docker Compose 命令。例如:
$ docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
在开始之前,需要确保 Ansible 已安装。
⚠️ 虽然 Ubuntu 的 apt 包管理器提供了 Ansible,但该版本常常存在插件依赖问题(如 Jinja2 相关警告)。为了避免这些问题并确保更好的兼容性,建议使用 pip 安装 Ansible:
$ sudo apt update && sudo apt install python3-pip -y && pip install --user ansible jinja2
上面的命令将 Ansible 安装到用户本地目录(~/.local/bin/
),避免系统级冲突和插件错误,从而确保在不同 Ubuntu 系统上的安装一致性。
安装完成后,可通过以下命令验证:
$ ansible --version
ansible [core 2.17.13]
...
输出 Ansible 版本即表示安装成功。
此外,我们选择使用 Docker Engine 而不是 Docker Desktop,因为前者更适合与 Ansible 在 Linux 上配合使用,提供更一致的部署流程。
4. 项目搭建
我们将创建一个项目,使用 Docker Compose 启动一个简单的 Nginx Web 服务器,并通过 Ansible 自动化启动服务。
首先创建工作目录并进入:
$ mkdir ansible-docker-demo && cd ansible-docker-demo
接下来完成项目的其余部分。
4.1. 创建一个简单的 Web 应用
创建一个基础的 HTML 文件:
$ mkdir app && touch app/index.html
打开 app/index.html
并写入以下内容:
<!DOCTYPE html>
<html>
<head>
<title>Hello from Ansible</title>
</head>
<body>
<h1>Hello from Docker + Ansible!</h1>
</body>
</html>
Nginx 默认会从 /usr/share/nginx/html
目录中加载网页文件。我们将在后续通过 Docker volume 将本地 app
目录挂载到容器中的这个路径。
4.2. 创建 Docker Compose 文件
创建 docker-compose.yml
文件:
version: '3'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./app:/usr/share/nginx/html:ro
该文件定义了一个基于 nginx:alpine 镜像的服务,映射 8080 端口,并挂载本地的 app
目录作为静态资源目录。
接着创建 docker-compose.prod.yml
文件:
version: '3'
services:
web:
environment:
- ENV=production
该文件为服务添加了一个环境变量,虽然示例简单,但它展示了如何通过 override 文件为不同环境(如 dev、staging、prod)定制部署配置。
4.3. 创建 Ansible Inventory 文件
Ansible 通过 inventory 文件来指定需要管理的主机。我们这里只在本地运行,因此创建 inventory.ini
文件:
[local]
localhost ansible_connection=local ansible_python_interpreter=/usr/bin/python3
说明:
ansible_connection=local
:告诉 Ansible 在本地执行命令,而不是通过 SSHansible_python_interpreter
:指定使用的 Python 解释器,避免警告
如果要在多台服务器上部署,可以扩展为:
[webservers]
192.168.10.10 ansible_user=ubuntu
192.168.10.11 ansible_user=ubuntu
这样就可以复用同一个 playbook 用于本地测试和生产部署。
4.4. 编写 Ansible Playbook
创建 playbook.yml
文件:
- name: Run Docker Compose with Ansible
hosts: local
become: yes
tasks:
- name: Ensure Docker is installed
package:
name: docker.io
state: present
- name: Ensure Docker Compose is installed
package:
name: docker-compose
state: present
- name: Ensure Docker service is running
service:
name: docker
state: started
enabled: true
- name: Pull Docker images
command: docker-compose -f docker-compose.yml -f docker-compose.prod.yml pull
args:
chdir: "{{ playbook_dir }}"
- name: Run Docker Compose
command: docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
args:
chdir: "{{ playbook_dir }}"
Playbook 说明如下:
name
:用于标识每个任务的作用hosts: local
:指定在inventory.ini
中定义的local
主机组执行become: yes
:以 sudo 权限执行任务(安装包、操作 Docker 服务)tasks
:按顺序执行的操作列表
各任务参数说明:
package
:确保安装 Docker 和 Docker Composestate: present
:表示安装状态service
:确保 Docker 服务运行并开机自启command
:执行 Docker Compose 命令chdir
:指定命令执行目录为 playbook 所在目录{{ playbook_dir }}
:Ansible 内置变量,表示 playbook 文件所在路径
该 playbook 会安装 Docker 和 Docker Compose(如未安装),然后运行 compose 命令启动服务。
4.5. 运行 Playbook
一切准备就绪后,运行 playbook:
$ ansible-playbook -i inventory.ini playbook.yml --ask-become-pass
BECOME password:
PLAY [Run Docker Compose with Ansible] *******************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************************************
ok: [localhost]
TASK [Ensure Docker is installed] ************************************************************************************************************
ok: [localhost]
TASK [Ensure Docker Compose is installed] ****************************************************************************************************
ok: [localhost]
TASK [Ensure Docker service is running] ******************************************************************************************************
ok: [localhost]
TASK [Pull Docker images] ********************************************************************************************************************
changed: [localhost]
TASK [Run Docker Compose] ********************************************************************************************************************
changed: [localhost]
PLAY RECAP ***********************************************************************************************************************************
localhost : ok=6 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
输出显示 Ansible 按顺序执行了每个任务,--ask-become-pass
会提示输入 sudo 密码。
验证服务是否运行成功:
$ curl http://localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Hello from Ansible</title>
</head>
<body>
<h1>Hello from Docker + Ansible!</h1>
</body>
</html>
可以看到我们的页面已成功运行在 Nginx 容器中,并由 Ansible 管理。
⚠️ 如果遇到权限错误(如连接 Docker daemon socket 被拒绝),请将当前用户加入 docker
组并重启系统:
$ sudo usermod -aG docker $USER
5. 总结
在本文中,我们演示了如何使用 Ansible 来运行 Docker 和 Docker Compose 命令。
我们构建了一个简单的 Nginx 应用,定义了多个 Compose 文件,并通过 Ansible 实现了一键自动化部署。借助 Ansible 与 Docker Compose 的结合,我们能够实现:
- 环境一致性(可重复性)
- 服务扩展性(轻松添加新容器或服务)
- 部署自动化(避免手动操作)
✅ 现在你可以在测试和生产环境中自动化复杂的基础设施部署,而不仅仅局限于开发环境。