Ansible与Docker自动化运维实战:从环境搭建到应用部署

发布时间:2026/7/10 6:17:42

Ansible与Docker自动化运维实战:从环境搭建到应用部署 30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度在运维领域手工重复操作、环境不一致、部署效率低下是每个团队都会遇到的痛点。随着业务规模扩大服务器数量从几台增长到上百台传统“人肉运维”模式不仅效率低还极易出错。本文将围绕 Ansible 和 Docker 这两大自动化利器为你提供一套从零开始的实战教程。无论你是刚接触运维的开发者还是希望提升团队效率的运维工程师都能通过本文掌握自动化运维的核心技能实现从单机脚本到规模化、可复现的自动化流程的跨越。1. 自动化运维核心概念与工具选型在深入实战之前我们有必要厘清自动化运维的核心思想以及为什么选择 Ansible 和 Docker 作为我们的技术栈。1.1 什么是自动化运维自动化运维DevOps Automation并非一个具体的工具而是一种通过技术手段将运维工作中的重复性、标准化任务交由系统自动执行的理念与实践。其目标在于提升效率、减少人为错误、保证环境一致性并最终实现运维工作的可追溯和可重复。典型的自动化运维场景包括服务器的批量初始化配置、应用程序的自动化部署与更新、监控告警的自动处理以及合规性检查等。1.2 为什么是 Ansible Docker这是一个经典的“编排”与“封装”的组合。Ansible是一个基于 Python 开发的自动化运维工具它通过 SSH 协议无需在目标主机安装客户端执行任务使用 YAML 语言编写易于阅读的“剧本”Playbook。它的核心优势在于“无代理”Agentless、简单易学、模块丰富非常适合进行配置管理、应用部署和任务编排。你可以把它想象成一位远程指挥官能够同时向成百上千台服务器下达清晰的指令。Docker是一个应用容器引擎它可以将应用及其所有依赖库、环境变量、配置文件打包成一个标准化的镜像。这个镜像可以在任何安装了 Docker 的宿主机上以容器的方式运行彻底解决了“在我机器上能跑”的环境一致性问题。Docker 实现了应用层面的封装和隔离。组合价值Ansible 负责宏观的、跨主机的编排和配置例如在哪些服务器上安装 Docker、拉取哪个镜像、如何配置网络而 Docker 负责微观的、应用本身的标准化交付和运行。使用 Ansible 来管理 Docker 的生命周期可以实现从基础设施准备到应用上线的全流程自动化。1.3 与其他工具的简单对比在自动化运维领域还有像 Puppet、Chef、SaltStack 等工具。Ansible 以其无代理和极低的学习门槛脱颖而出特别适合从零开始的团队。而在容器领域虽然 Kubernetes 是编排的事实标准但对于中小规模场景或初学者直接使用 Docker 或 Docker Compose 更能快速上手并理解容器化带来的好处。本教程的路径是先掌握 Ansible 和 Docker 这两个基石再向更复杂的编排工具进阶。2. 环境准备与安装指南我们将在一个典型的 Linux 环境下进行实战。本文以CentOS 7.x作为控制节点运行 Ansible和被管理节点的操作系统示例。其他如 Ubuntu、RHEL 等发行版命令仅有细微差别。2.1 基础环境要求控制节点至少一台 Linux 服务器用于安装 Ansible。需要 Python 3.6 或更高版本。被管理节点一台或多台 Linux 服务器。本文为了演示可以使用一台服务器同时作为控制节点和被管理节点。网络互通控制节点需要能通过 SSH 连接到所有被管理节点。权限建议使用具有 sudo 权限的普通用户进行操作避免直接使用 root。2.2 安装 Ansible在控制节点上执行以下步骤。步骤一更新系统并安装 EPEL 仓库CentOS 默认仓库可能不包含最新版 AnsibleEPEL 仓库提供了稳定版本。sudo yum update -y sudo yum install epel-release -y步骤二安装 Ansible通过 yum 直接安装。sudo yum install ansible -y步骤三验证安装安装完成后检查 Ansible 版本确认安装成功。ansible --version你应该能看到类似ansible 2.9.x的输出信息。步骤四配置主机清单InventoryAnsible 通过“主机清单”文件来管理它要操作的目标机器。默认文件是/etc/ansible/hosts。我们来编辑它sudo vim /etc/ansible/hosts在文件末尾添加以下内容将192.168.1.100替换为你实际被管理节点的 IP 地址。这里我们创建一个名为webservers的组。[webservers] 192.168.1.100 ansible_ssh_useryour_username ansible_ssh_passyour_password注意在生产环境中强烈建议使用 SSH 密钥认证而不是明文密码。使用密钥的配置方式是ansible_ssh_useryour_username ansible_ssh_private_key_file/path/to/private_key。步骤五测试连接使用ping模块测试 Ansible 是否能连接到被管理节点。ansible webservers -m ping如果看到192.168.1.100 | SUCCESS {...}这样的输出表示连接成功。2.3 安装 Docker我们将使用 Ansible 来在被管理节点上安装 Docker这本身就是一次自动化实践。首先我们需要在控制节点上创建一个 Ansible Playbook。步骤一创建 Playbook 文件在控制节点上创建一个目录用于存放我们的 Playbook。mkdir -p ~/ansible-docker-demo cd ~/ansible-docker-demo vim docker-install.yml步骤二编写 Docker 安装 Playbook将以下内容写入docker-install.yml。这个 Playbook 完成了添加 Docker 官方仓库、安装 Docker 引擎、启动服务并设置开机自启等一系列操作。--- - name: Install and start Docker on CentOS hosts: webservers # 指定在主机清单中的 webservers 组上执行 become: yes # 使用 sudo 权限执行任务 tasks: - name: Install required packages (yum-utils) yum: name: yum-utils state: present - name: Add Docker repository get_url: url: https://download.docker.com/linux/centos/docker-ce.repo dest: /etc/yum.repos.d/docker-ce.repo - name: Install Docker CE (Community Edition) yum: name: - docker-ce - docker-ce-cli - containerd.io state: latest - name: Start and enable Docker service systemd: name: docker state: started enabled: yes - name: Add current user to docker group (to run docker without sudo) user: name: {{ ansible_user }} groups: docker append: yes代码解释hosts: webservers指定任务执行的目标主机组。become: yes意味着所有任务都将以 root 权限运行。每个- name:下面是一个具体的任务Task使用 Ansible 模块如yum,get_url,systemd,user来执行操作。{{ ansible_user }}是一个 Ansible 变量代表当前连接使用的用户名。步骤三执行 Playbook运行这个 Playbook让 Ansible 自动完成 Docker 的安装。ansible-playbook docker-install.yml执行过程中你会看到 Ansible 输出每个任务的执行状态ok,changed,failed。如果全部成功最后会有一个PLAY RECAP总结。步骤四验证 Docker 安装在控制节点上使用 Ansible 的shell模块远程执行命令验证 Docker。ansible webservers -m shell -a docker --version如果安装成功你会看到类似Docker version 24.0.x, build xxxxx的输出。3. Ansible 核心语法与模块精讲仅仅会运行 Playbook 还不够理解其核心语法和常用模块是编写高效自动化脚本的关键。3.1 Playbook 结构解析一个标准的 Playbook 是 YAML 格式文件通常包含以下部分--- - name: 这是一个Playbook的描述 hosts: target_servers # 目标主机 become: yes # 是否提权 vars: # 定义变量 http_port: 80 tasks: # 任务列表核心部分 - name: 确保nginx已安装 yum: name: nginx state: present - name: 启动nginx服务 systemd: name: nginx state: started enabled: yes handlers: # 处理器由任务通知触发 - name: restart nginx systemd: name: nginx state: restartedPlay一个 Playbook 可以包含多个 Play以-开头。每个 Play 针对一组主机执行一系列任务。Task每个任务调用一个 Ansible模块。模块是 Ansible 执行实际工作的单元如yum,copy,template。Handler一种特殊的任务只在被其他任务notify时执行一次常用于服务重启。3.2 常用核心模块实战copy模块复制文件- name: Copy local config file to remote server copy: src: ./myapp.conf # 控制节点上的源文件路径 dest: /etc/myapp/myapp.conf # 被管理节点上的目标路径 owner: root group: root mode: 0644template模块动态生成配置文件template模块类似copy但源文件是一个 Jinja2 模板可以在传输前渲染变量。创建模板文件nginx.conf.j2server { listen {{ http_port }}; # 使用变量 server_name {{ server_name }}; root /var/www/{{ app_name }}; }在 Playbook 中定义变量并使用templatevars: http_port: 8080 server_name: demo.example.com app_name: myapp tasks: - name: Configure Nginx with template template: src: nginx.conf.j2 dest: /etc/nginx/conf.d/default.confshell和command模块执行命令command执行简单命令不通过 shell 解析因此不支持变量和管道|。- name: Run a simple command command: ls -la /tmpshell通过/bin/sh执行命令支持管道、重定向等所有 shell 特性。- name: Check process and grep shell: ps aux | grep nginx register: ps_result # 将命令输出注册到变量docker_container模块管理 Docker 容器这是 Ansible 社区提供的用于管理 Docker 容器的核心模块需要安装dockerPython 包。- name: Run a Nginx container docker_container: name: my-nginx image: nginx:latest state: started # started, stopped, absent ports: - 8080:80 volumes: - /host/path:/container/path restart_policy: always3.3 变量与循环变量让 Playbook 更灵活。变量可以定义在 Playbook 顶部、外部文件、或通过-e参数传递。vars: package_list: - nginx - git - curl tasks: - name: Install multiple packages yum: name: {{ item }} state: present loop: {{ package_list }} # 循环遍历列表使用loop可以避免为每个包写一个独立任务。4. 完整实战使用 Ansible 部署 Docker 化应用现在我们将综合运用所学完成一个经典场景使用 Ansible 在远程服务器上部署一个由 Docker 容器运行的 Web 应用以 Nginx 为例。4.1 项目结构与设计在控制节点的~/ansible-docker-demo目录下创建如下结构~/ansible-docker-demo/ ├── docker-install.yml # 之前创建的安装Docker的Playbook ├── deploy-nginx-app.yml # 主部署Playbook ├── templates/ │ └── index.html.j2 # 网站首页模板 └── files/ └── nginx-custom.conf # 自定义Nginx配置文件4.2 准备应用文件创建自定义首页模板(templates/index.html.j2)!DOCTYPE html html head titleAnsible Docker Demo/title /head body h1Hello from {{ ansible_hostname }}!/h1 pThis Nginx container was deployed automatically by Ansible./p pServer Time: {{ ansible_date_time.iso8601 }}/p /body /html这个模板使用了 Ansible 内置事实变量ansible_hostname和ansible_date_time使页面内容动态化。创建自定义 Nginx 配置(files/nginx-custom.conf)server { listen 80; server_name _; location / { root /usr/share/nginx/html; index index.html index.htm; } # 禁用版本号显示增强安全性 server_tokens off; }4.3 编写主部署 Playbook创建主 Playbook 文件deploy-nginx-app.yml--- - name: Deploy Nginx Application using Docker hosts: webservers become: yes vars: container_name: my_nginx_app host_port: 8080 container_port: 80 tasks: # 任务1: 创建应用目录 - name: Create application directory on host file: path: /opt/{{ container_name }} state: directory mode: 0755 # 任务2: 生成动态首页文件 - name: Generate index.html from template template: src: templates/index.html.j2 dest: /opt/{{ container_name }}/index.html mode: 0644 # 任务3: 复制自定义Nginx配置 - name: Copy custom Nginx configuration copy: src: files/nginx-custom.conf dest: /opt/{{ container_name }}/default.conf mode: 0644 # 任务4: 运行Nginx容器 - name: Run Nginx Docker container docker_container: name: {{ container_name }} image: nginx:alpine # 使用更小的Alpine镜像 state: started restart_policy: unless-stopped ports: - {{ host_port }}:{{ container_port }} volumes: - /opt/{{ container_name }}/index.html:/usr/share/nginx/html/index.html:ro - /opt/{{ container_name }}/default.conf:/etc/nginx/conf.d/default.conf:ro # 环境变量示例 env: TZ: Asia/Shanghai notify: - wait for nginx handlers: # 处理器: 等待容器服务就绪 - name: wait for nginx wait_for: port: {{ host_port }} delay: 5 state: started4.4 执行部署与验证运行部署 Playbookansible-playbook deploy-nginx-app.yml观察输出所有任务状态应为ok或changed。验证部署结果方法一使用 Ansible 检查容器状态ansible webservers -m shell -a docker ps | grep my_nginx_app方法二直接访问应用在浏览器或使用curl访问http://被管理节点IP:8080。你应该能看到渲染后的 HTML 页面其中包含服务器的主机名和当前时间。4.5 扩展使用 Docker Compose 进行编排对于更复杂的多容器应用例如 Web Database使用 Docker Compose 定义服务再用 Ansible 来部署是更佳实践。在被管理节点安装 Docker Compose可通过 Ansible 完成- name: Install Docker Compose get_url: url: https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-linux-x86_64 dest: /usr/local/bin/docker-compose mode: 0755创建docker-compose.yml文件并复制到远程# docker-compose.yml 示例 version: 3.8 services: web: image: nginx:alpine ports: - 8080:80 volumes: - ./web/html:/usr/share/nginx/html db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: myapp编写 Ansible Playbook 来启动 Compose 项目- name: Deploy with Docker Compose hosts: webservers become: yes tasks: - name: Copy docker-compose.yml copy: src: ./docker-compose.yml dest: /opt/myapp/docker-compose.yml - name: Start services with Docker Compose community.docker.docker_compose: project_src: /opt/myapp state: present这里使用了community.docker.docker_compose模块它是docker_container模块的补充专门用于 Compose。5. 常见问题与排查思路在自动化实践中遇到问题是常态。下面是一些典型问题的排查指南。问题现象可能原因排查思路与解决方案AnsibleUNREACHABLE错误1. 网络不通。2. SSH 服务未运行或端口不对。3. SSH 认证失败密码错误/密钥不对。4. 主机清单配置错误。1.ping 目标IP测试网络。2.ssh your_user目标IP手动连接测试。3. 检查清单文件中的用户名、密码/密钥路径。4. 使用-i参数指定清单文件ansible all -i hosts -m ping。AnsibleFAILED错误提示权限不足任务需要sudo权限但未提供或用户不在 sudoers 列表中。1. 在 Playbook 或任务中设置become: yes。2. 确保 Ansible 连接用户有 sudo 权限且无需密码或在清单中配置ansible_become_pass。3. 使用-K参数运行 Playbook 来交互输入 sudo 密码。Docker 命令执行失败提示Cannot connect to the Docker daemon当前用户不在docker组或 Docker 服务未运行。1. 运行sudo systemctl status docker检查服务状态。2. 将用户加入 docker 组sudo usermod -aG docker $USER需要退出重新登录生效。3. 在 Ansible 任务中使用become: yes来运行 Docker 命令。Playbook 执行成功但应用无法访问1. 容器端口映射错误。2. 宿主机防火墙未放行端口。3. 容器内应用未监听正确端口。1.docker ps检查端口映射列0.0.0.0:8080-80/tcp。2. 检查防火墙sudo firewall-cmd --list-ports(CentOS)。3. 进入容器检查docker exec -it 容器名 sh然后netstat -tlnp。template模块报错提示变量未定义模板中引用的变量在 Playbook 作用域内未定义。1. 检查变量名拼写。2. 确保变量在vars中定义或通过-e传入或是有效的事实变量。3. 使用debug模块打印变量值- debug: varmy_variable。使用docker_container模块报错缺少 Python Docker SDK目标主机上未安装dockerPython 包。在被管理节点上安装sudo pip3 install docker。可以通过一个前置的 Ansible 任务来完成- pip: namedocker6. 最佳实践与工程建议将自动化脚本用于生产环境需要遵循一定的规范以确保其可靠性、安全性和可维护性。6.1 代码与项目管理使用版本控制将所有的 Playbook、模板、变量文件纳入 Git 仓库管理。这是协作和回滚的基础。目录结构标准化采用 Ansible 官方推荐的角色Role目录结构即使项目初期很小。这有助于模块化。production.yml site.yml roles/ common/ tasks/ handlers/ templates/ files/ vars/ webserver/ database/ group_vars/ all/ webservers/ host_vars/ server01/利用 Roles 实现复用将相关的任务、变量、文件等组织成 Role如docker-install,nginx-deploy然后在主 Playbook 中调用它们避免代码重复。6.2 安全与权限禁用 SSH 密码认证在生产环境中强制使用 SSH 密钥对进行认证并在清单文件中配置密钥路径。使用 Ansible Vault 加密敏感数据对于密码、API密钥等敏感信息不要明文写在 Playbook 或变量文件中。使用ansible-vault命令进行加密。# 加密一个变量文件 ansible-vault encrypt group_vars/all/secrets.yml # 运行Playbook时提供密码 ansible-playbook site.yml --ask-vault-pass遵循最小权限原则在 Playbook 中精确控制become的使用范围。不要整个 Playbook 都用 root只为需要特权的任务启用。谨慎处理shell和command模块避免直接执行未经验证的用户输入防止命令注入。优先使用专用的 Ansible 模块。6.3 执行与维护使用--check和--diff进行试运行在真正执行改变系统的操作前使用--check干跑模式和--diff显示差异来预览 Ansible 将要做什么。ansible-playbook deploy.yml --check --diff为 Playbook 添加标签Tags给任务打上标签可以只运行特定部分方便调试和快速执行。tasks: - name: Install packages yum: ... tags: install - name: Copy config copy: ... tags: config运行ansible-playbook deploy.yml --tags install收集事实Facts并合理使用Ansible 默认会收集目标主机信息IP、主机名、内存等。这些ansible_facts变量可以在 Playbook 中用于条件判断和模板渲染。如果不需要可以用gather_facts: no关闭以提升执行速度。做好日志与通知重要的 Playbook 执行应有日志记录并与监控告警系统如 Zabbix, Prometheus或通讯工具如 Slack, 钉钉集成通知执行结果。6.4 Docker 相关实践使用特定版本标签在 Playbook 中避免使用latest标签。应指定具体的版本号如nginx:1.25-alpine以保证部署的一致性。管理数据持久化对于数据库等有状态服务务必通过volumes将数据目录挂载到宿主机或外部存储避免容器销毁后数据丢失。资源限制为容器设置 CPU 和内存限制防止单个容器耗尽主机资源。docker_container: name: myapp image: myapp:latest state: started cpu_shares: 512 memory: 512m镜像仓库安全从可信的仓库拉取镜像如有私有镜像需在 Playbook 中配置docker_login模块进行认证。掌握 Ansible 和 Docker 是构建现代自动化运维体系的坚实基础。通过本文你不仅学会了如何安装和运行它们更重要的是理解了如何将两者结合用声明式的代码Playbook来管理弹性的、隔离的应用环境容器。从单次的手动执行到可重复的自动化脚本再到版本化、模块化的工程化部署这条路径能显著提升运维工作的质量和效率。建议你从本文的示例出发尝试将自己的日常运维任务改写成 Ansible Playbook并逐步将应用容器化。接下来可以探索 Ansible Roles 进行代码复用学习 Docker Compose 编排多容器应用甚至进一步研究 Kubernetes 与 Ansible 的集成以应对更复杂的生产场景。 30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度

相关新闻