90DaysOfDevOps 第 46 天:用 Docker Compose 一键编排多容器应用(WordPress + MySQL 实战)

发布时间:2026/10/4 21:57:03

90DaysOfDevOps 第 46 天:用 Docker Compose 一键编排多容器应用(WordPress + MySQL 实战) 文档/教程【免费下载链接】90DaysOfDevOpsThis repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.项目地址https://gitcode.com/gh_mirrors/90/90DaysOfDevOps点击查看免费下载本指南是 90DaysOfDevOps 学习路线中容器章节的核心一课在掌握单个 Docker 容器与 Dockerfile 之后见 第 45 天Docker 镜像解剖通过 Docker Compose 以一份 YAML 文件同时拉起 WordPress 与 MySQL 两个相互关联的容器并理解命名卷带来的数据持久化能力。读完本文你将掌握docker-compose.yml的完整结构与关键参数、up/down/ps等日常编排命令、数据清理与保留的区别并能在仓库内置的 ELKElasticsearch Logstash Kibana三容器示例上举一反三。为什么需要 Docker Compose如果一个镜像已经自包含、能满足单一用例那么运行单个容器就足够了。但当你需要在多个不同的容器镜像之间构建互相协作的应用时事情就变得复杂起来。例如一个网站前端需要一个后端数据库理论上可以把数据库也塞进同一个容器但更合理、更高效的做法是让数据库拥有自己独立的容器——各自独立演进、独立伸缩、独立备份。Docker Compose 正是为此而生它是一款允许你在多个容器上运行更复杂应用的工具核心价值在于只用一份配置文件加一条命令就能把整个多容器应用拉起来。本文的实战示例来自 Docker 官方的 Quickstart 示例Compose 与 WordPress我们的目标是使用 Docker Compose 启动 WordPress 和一个独立的 MySQL 实例使用一个名为docker-compose.yml的 YAML 文件描述整个应用构建项目并验证容器状态通过浏览器完成 WordPress 的初始化配置最后执行关闭与清理观察数据是否保留。安装与验证 Docker ComposeDocker Compose 本身是一个独立的工具。如果你使用的是macOS 或 WindowsCompose 已经随Docker Desktop一并安装无需额外操作而当你希望在Windows Server 主机或 Linux 服务器上运行容器时则需要按照 Docker 官方安装文档单独安装 Compose 插件。安装完成后打开终端输入docker-compose --version或docker compose version取决于版本即可确认工具是否就绪认识 docker-compose.yml 与 YAML 语言先花一分钟理解 YAML在深入配置文件之前有必要先聊聊 YAML 本身——你会在 DevOps 的几乎所有角落遇到它。对 YAML 最经典的定义是“YAML 是一种对人类友好的、适用于所有编程语言的数据序列化语言。”它通常用于配置文件以及某些需要存储或传输数据的应用场景。你可能已经接触过承担同样职责的 XML 文件而 YAML 提供了更精简的语法却面向同样的使用场景。YAML最初是 “Yet Another Markup Language” 的缩写维护者后来将其改名为 “YAML Aint Markup Language” 以强调其数据导向特性近年来越来越流行其对象序列化能力使它成为 JSON 的有力替代品——尤其是在人类需要直接阅读和编写配置的场合。docker-compose.yml 的完整内容与逐行解析docker-compose.yml就是描述“我们想要在多容器场景下做什么”的配置清单。下面这份文件正是仓库中 WordPress 示例 的实际内容与教程原始示例完全一致version: 3.9 services: db: image: mysql:5.7 volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: depends_on: - db image: wordpress:latest volumes: - wordpress_data:/var/www/html ports: - 8000:80 restart: always environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: db_data: {} wordpress_data: {}逐段拆解这份配置version: 3.9声明 Compose 文件格式的版本号决定哪些语法特性可用。services:文件的主体部分定义了应用包含的每个容器服务。本例有两个服务db和wordpress。db服务使用mysql:5.7镜像并通过restart: always保证容器异常退出后自动重启。四个环境变量MYSQL_ROOT_PASSWORD、MYSQL_DATABASE、MYSQL_USER、MYSQL_PASSWORD分别指定了 MySQL 的 root 密码、要创建的数据库名以及普通用户账号密码MySQL 官方镜像在首次启动时会据此完成初始化。wordpress服务使用wordpress:latest镜像depends_on: - db声明它依赖db服务先启动ports: 8000:80把宿主机 8000 端口映射到容器内 80 端口WordPress 默认监听端口。四个WORDPRESS_*环境变量告诉 WordPress 如何连接数据库——注意WORDPRESS_DB_HOST填的是服务名db在 Compose 自动创建的内部网络中服务名即主机名可被 DNS 直接解析这也是多容器协作的关键机制。volumes:顶层声明db_data和wordpress_data两个命名卷。与之前教程中“用完即弃”的无状态容器不同这里第一次把状态引入了配置MySQL 数据写入db_data卷挂载到容器内/var/lib/mysqlWordPress 站点文件主题、插件、上传内容写入wordpress_data卷挂载到容器内/var/www/html。这类文件随着业务复杂会变得非常庞大但 YAML 的缩进结构与键值语法让整体面貌保持清晰可读。构建并启动多容器应用回到终端切换到存放docker-compose.yml的目录执行docker-compose up -d该命令会拉取所需的镜像并启动整个多容器应用。其中-d表示detached 模式后台运行命令执行后终端即可继续使用。随后用docker ps查看运行状态可以看到两个容器同时在运行一个是wordpress另一个是mysql见文首截图两容器均基于wordpress:latest与mysql:5.7镜像且 WordPress 容器的端口映射为0.0.0.0:8000-80/tcp。在浏览器中完成 WordPress 初始化打开浏览器访问http://localhost:8000即可看到 WordPress 的安装页面按照页面提示完成 WordPress 的初始化安装选择语言、填写站点信息、创建管理员账号随后就能进入后台开始搭建网站。再次访问http://localhost:8000可以看到使用默认主题渲染的站点首页——教程中站点标题为 “90DaysOfDevOps”并包含一篇示例文章。通过 Docker Desktop 观察卷与更改主题在对站点做任何修改之前打开Docker Desktop 的 Volumes 标签页可以看到与容器关联的两个命名卷一个属于 WordPresswordpress_data一个属于数据库db_data。这就是数据持久化的直接证据。接下来做两处典型的站点修改更换主题教程当前使用的是 “Twenty Twenty-Two” 主题在后台将其切换为 “Twenty Twenty”新增文章在后台发布一篇新文章。完成后站点即呈现新的主题与最新文章列表。清理保留数据还是彻底删除多容器应用的清理与数据生命周期管理是本节的重点几种命令的行为差异必须分清docker-compose down # 停止并移除容器但保留命名卷数据仍在 docker-compose up -d # 重新启动应用数据完整保留 docker-compose down --volumes # 停止容器并同时删除命名卷数据彻底清除执行docker-compose down后容器被移除但在 Docker Desktop 的 Volumes 标签页仍能看到两个命名卷——数据安然无恙在相同目录再次执行docker-compose up -d应用重新上线回到http://localhost:8000会发现之前更换的主题和新增的文章全部还在这正是命名卷持久化的价值若想连数据一起清除使用docker-compose down --volumes卷会被一并销毁之后再次docker-compose up -d会得到一个全新的应用——不过镜像仍然缓存在本地系统中无需重新从 DockerHub 拉取。Docker Compose 与 Kubernetes各自的定位初学 Docker Compose 时常会困惑它与 Kubernetes 这类容器编排工具的关系。本演示的所有操作都聚焦在一台主机上WordPress 和数据库运行在本地桌面机器的 Docker 环境中没有多台虚拟机或物理机也无法轻松地按需对应用进行水平伸缩scale up/down。而 Kubernetes 解决的是跨多节点的编排、调度、伸缩、自愈等问题——这是 90DaysOfDevOps 后续章节的内容在进入 Kubernetes 之前容器基础还有几天要夯实。进阶示例ELK 单节点三容器编排仓库的 Containers 目录 下内置了一个来自官方示例库、更具代表性的多容器应用Elasticsearch Logstash KibanaELK单节点部署位于 elasticsearch-logstash-kibana 目录。其 docker-compose.yml 展示了比 WordPress 示例更丰富的 Compose 特性services: elasticsearch: image: elasticsearch:7.16.1 container_name: es environment: discovery.type: single-node ES_JAVA_OPTS: -Xms512m -Xmx512m ports: - 9200:9200 - 9300:9300 healthcheck: test: [CMD-SHELL, curl --silent --fail localhost:9200/_cluster/health || exit 1] interval: 10s timeout: 10s retries: 3 networks: - elastic logstash: image: logstash:7.16.1 container_name: log environment: discovery.seed_hosts: logstash LS_JAVA_OPTS: -Xms512m -Xmx512m volumes: - ./logstash/pipeline/logstash-nginx.config:/usr/share/logstash/pipeline/logstash-nginx.config - ./logstash/nginx.log:/home/nginx.log ports: - 5000:5000/tcp - 5000:5000/udp - 5044:5044 - 9600:9600 depends_on: - elasticsearch networks: - elastic command: logstash -f /usr/share/logstash/pipeline/logstash-nginx.config kibana: image: kibana:7.16.1 container_name: kib ports: - 5601:5601 depends_on: - elasticsearch networks: - elastic networks: elastic: driver: bridge这份配置新增了几个值得学习的要点自定义网络顶层networks.elastic使用driver: bridge创建专用网络三个服务通过networks: - elastic加入同一网络服务间以容器名es、log、kib互相访问——例如 Logstash 管道配置中就用http://es:9200作为 Elasticsearch 地址健康检查Elasticsearch 通过healthcheck定期探测localhost:9200/_cluster/healthdocker ps中会显示(healthy)状态这是编排中保证依赖就绪的常用手段JVM 内存约束ES_JAVA_OPTS与LS_JAVA_OPTS分别把 Elasticsearch 和 Logstash 的堆内存限制在 512MB避免本地开发时资源耗尽端口矩阵Elasticsearch 暴露9200/9300Logstash 暴露5000TCP/UDP、5044Beats 输入、9600HTTP APIKibana 暴露5601配置挂载与启动命令Logstash 的管道配置通过 bind mount 挂载进容器并用command显式指定logstash -f启动参数。Logstash 的管道定义见 logstash-nginx.config其处理链为input从/home/nginx.log读取 Nginx 访问日志JSON 格式start_position beginning从文件头开始读取filter依次对消息做json解析、geoip地理信息增强和useragent浏览器解析最后output写入 Elasticsearch 的nginx索引并同时在stdout以rubydebug格式输出。该目录下的 README.md 还给出了完整的部署预期docker-compose up -d会创建elasticsearch-logstash-kibana_elastic网络并依次启动es、log、kib三个容器。进入该目录执行同样的docker-compose up -d随后用docker ps确认三个容器都在运行然后即可在浏览器中分别访问Elasticsearchhttp://localhost:9200Logstashhttp://localhost:9600Kibanahttp://localhost:5601/api/status结束实验后同样用docker-compose down一键移除全部容器。小结Docker Compose 把“多容器应用的描述、启动、停止、清理”压缩为一份docker-compose.yml加几条命令是本地开发、CI 验证和单机部署的利器。本文从 WordPress MySQL 的官方示例出发覆盖了 Compose 安装验证、YAML 配置结构、命名卷持久化、数据保留/删除差异再到 ELK 三容器示例中的网络、健康检查与管道配置为你后续学习 Kubernetes 集群编排打下了扎实的容器基础。下一讲将进入 第 47 天继续容器章节的深入内容。赞分享文档/教程【免费下载链接】90DaysOfDevOpsThis repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.项目地址https://gitcode.com/gh_mirrors/90/90DaysOfDevOps点击查看免费下载相关推荐90DaysOfDevOps 第 46 天用 Docker Compose 一键编排 WordPress MySQL 多容器应用90DaysOfDevOps 第 46 天用 Docker Compose 一键编排 WordPress MySQL 多容器应用 在 90 天 DevOp文档/教程90DaysOfDevOps 第 46 天用 Docker Compose 编排多容器应用WordPress MySQL 实战90DaysOfDevOps 第 46 天用 Docker Compose 编排多容器应用WordPress MySQL 实战 本文是 90DaysO文档/教程SiamMask性能优化秘籍如何实现77FPS的实时目标跟踪SiamMask性能优化秘籍如何实现77FPS的实时目标跟踪 SiamMask作为CVPR2019的明星项目以其Fast Online Object Tr创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/4 21:52:03

Qwen2-VL图像识别微调实战:Python实现LoRA训练与部署指南

简介:面向图像识别与多模态大模型应用开发者,这份Python工程源码完整演示了基于千问Qwen2-VL从COCO 2014 Caption图片数据准备、模型训练到checkpoint加载推理的落地路径,适合已有Python基础、希望掌握视觉语言模型微调及图像识别工程化流程的…

2026/10/4 23:07:06

AI编程工具插件系统全解析:plugin.json、SDK与CLI实战指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 Cursor、Codex CLI、Claude Code 这类 AI 编程工具,大概率会在某个时刻撞上plugins这个词。它可能出现在报错里,比如failed to load plugins web boot: 2 entries did not …

2026/10/4 23:07:06

Cursor插件本质是AI Agent可执行契约

1. “plugins”不是功能菜单,而是AI原生开发的底层契约接口你点开Cursor编辑器右下角那个写着“Plugins”的小图标,以为只是装个代码补全或翻译插件?错了。这个看似轻量的入口,其实是整个AI原生开发范式中最硬核的基础设施层——它…

2026/10/4 23:07:06

从零手搓AI工程:不调包如何掌控数据到服务全链路

1. 从零手搓AI工程:为什么我不建议你直接调包很多人一上来就想搞个大模型应用,第一反应是找API、装框架、跑通一个Demo,然后觉得自己“入门AI工程”了。我刚开始也这么干过,结果踩了一堆坑:接口一改就崩、成本失控、延…

2026/10/4 23:07:06

C#调用USB摄像头实战:DirectShow/AForge/OpenCvSharp选型与避坑指南

简介:面向在.NET平台使用C#操作USB摄像头的开发者,这份资源提供一套可直接运行的完整示例,覆盖摄像头枚举、连接、视频流启停、拍照抓帧与图片保存等关键环节。压缩包内共38个文件,包括6个C#源文件、10个动态库、3个可执行程序以及…

2026/10/4 23:07:06

中控Java二次开发demo实战:跑通、避坑与封装指南

简介:面向企业级考勤系统的开发者,中控Java二次开发demo.zip提供了一套直接可用的对接方案,适用于需要读取考勤记录、维护人员信息或集成考勤数据到业务系统的场景。资源以Java源码与配套文档为核心,压缩包整体约37.77MB&#xff…

2026/10/4 23:02:06

计算机专业论文被AIGC检测标红?2026年先搞懂原理再谈应对

计算机科学与技术专业的同学最近多了个新烦恼:明明论文是自己熬夜写的,AIGC 检测却给出偏高的 AI 率,答辩前被要求解释说明。更委屈的是,代码注释、算法描述这种"教科书式表达"特别容易被误判。与其抱怨检测不准&#x…

2026/10/4 0:01:02

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/4 0:01:02

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/4 1:01:05

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 0:01:02

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/4 0:01:02

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/4 1:01:05

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑