Docker Compose综合实战
2026/9/15 10:53:31 网站建设 项目流程

📑 目录

  • 一、实战一:MySQL 主从复制集群
    • 1. 主从同步原理
    • 2. 主库与从库 Dockerfile
    • 3. docker-compose.yml
    • 4. 构建与验证
  • 二、实战二:Redis Cluster 集群
    • 1. Redis Cluster 基础
    • 2. Redis Dockerfile(多阶段构建)
    • 3. docker-compose.yml
    • 4. 构建与验证
  • 三、实战三:C++ 微服务编排与负载均衡
    • 1. 微服务与容器编排
    • 2. C++ 服务与 Dockerfile
    • 3. Nginx 加权负载均衡配置
    • 4. docker-compose.yml
    • 5. 构建与验证
  • 四、三个实战的 Docker 技巧对比

一、实战一:MySQL 主从复制集群

1. 主从同步原理

MySQL 主从复制是指数据可以从一个 MySQL 主节点复制到一个或多个从节点。主要目的是读写分离提升性能数据实时备份高可用 HA

在主从复制的过程中,基于三个线程来操作:

线程位置作用
binlog dumpmaster读取 binlog 日志,发送给 slave
I/Oslave接收 binlog,写入本地 relaylog
SQLslave读取 relaylog,解析并重做操作

复制流程:master 将写操作记录到binlog→ binlog dump 线程发送给 slave → slave 的 I/O 线程写入relaylog→ slave 的 SQL 线程重做操作,达到数据一致性。

📌 主从同步的数据内容是二进制日志(Binlog),详见 MySQL 复制官方文档。

2. 主库与从库 Dockerfile

docker-compose.yml中使用build选项编译镜像,有两种格式:

services:# 格式一:简单路径,在该路径下找默认文件名Dockerfilefrontend:image:awesome/webappbuild:./webapp# 格式二:指定 context 和 dockerfile,在context路径下找自定义文件名backend.Dockerfilebackend:image:awesome/databasebuild:context:./backenddockerfile:./backend.Dockerfile

📌 Composebuild选项的完整说明见 Compose 文件规范。

创建目录结构:

mkdir-p/data/mysqlcluster/{master,slave}cd/data/mysqlcluster

主库master/Dockerfile-master

FROM mysql:5.7.36 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime COPY ./master/master.sql /docker-entrypoint-initdb.d

📌 MySQL 官方镜像在启动时会自动执行/docker-entrypoint-initdb.d目录下的.sql文件进行数据库初始化。镜像说明见 MySQL 官方镜像。

主库配置脚本master/master.sql

-- 因 Mysql 默认创建了 root 用户不需要手动创建配置CREATEUSER'root'@'%'IDENTIFIEDBY'root';grantreplicationslave,replicationclienton*.*to'root'@'%';flushprivileges;

从库slave/Dockerfile-slave

FROM mysql:5.7.36 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime COPY ./slave/slave.sql /docker-entrypoint-initdb.d

从库配置脚本slave/slave.sql

change mastertomaster_host='mysql-master',master_user='root',master_password='root',master_port=3306;startslave;

3. docker-compose.yml

version:"3"services:mysql-master:build:context:./dockerfile:./master/Dockerfile-masterimage:mysqlmaster:v1.0restart:alwayscontainer_name:mysql-mastervolumes:-./mastervarlib:/var/lib/mysqlports:-9306:3306environment:MYSQL_ROOT_PASSWORD:rootprivileged:true#给容器开启**特权模式**,容器内拥有接近宿主机 root 权限。command:['--server-id=1','--log-bin=master-bin','--binlog-ignore-db=mysql','--binlog_cache_size=256M','--binlog_format=mixed','--lower_case_table_names=1','--character-set-server=utf8','--collation-server=utf8_general_ci']mysql-slave:build:context:./dockerfile:./slave/Dockerfile-slaveimage:mysqlslave:v1.0restart:alwayscontainer_name:mysql-slavevolumes:-./slavevarlib:/var/lib/mysqlports:-9307:3306environment:MYSQL_ROOT_PASSWORD:rootprivileged:truecommand:['--server-id=2','--relay_log=slave-relay','--lower_case_table_names=1','--character-set-server=utf8','--collation-server=utf8_general_ci']depends_on:-mysql-mastermysql-slave2:build:context:./dockerfile:./slave/Dockerfile-slaveimage:mysqlslave:v1.0restart:alwayscontainer_name:mysql-slave2volumes:-./slavevarlib2:/var/lib/mysqlports:-9308:3306environment:MYSQL_ROOT_PASSWORD:rootprivileged:truecommand:['--server-id=3','--relay_log=slave-relay','--lower_case_table_names=1','--character-set-server=utf8','--collation-server=utf8_general_ci']depends_on:-mysql-master

4. 构建与验证

# 构建镜像dockercompose build# 启动服务dockercompose up-d# 查看状态dockercomposeps# NAME IMAGE SERVICE STATUS PORTS# mysql-master mysqlmaster:v1.0 mysql-master Up 0.0.0.0:9306->3306/tcp# mysql-slave mysqlslave:v1.0 mysql-slave Up 0.0.0.0:9307->3306/tcp# mysql-slave2 mysqlslave:v1.0 mysql-slave2 Up 0.0.0.0:9308->3306/tcp

验证主从同步

# 查看从库同步状态dockerexec-itmysql-slavebashmysql-pmysql>SHOW SLAVE STATUS\G

关键检查项:

Slave_IO_Running: Yes ← I/O 线程正常运行 Slave_SQL_Running: Yes ← SQL 线程正常运行 Seconds_Behind_Master: 0 ← 与主库延迟为 0
-- 在主库创建数据库和表mysql>createdatabasetest;mysql>usetest;mysql>createtableusers(snoint,snamevarchar(20));mysql>insertintousersvalues(1,'pony');mysql>insertintousersvalues(2,'maxhou');-- 连接从库查看数据自动同步mysql>select*fromusers;-- +------+--------+-- | sno | sname |-- +------+--------+-- | 1 | pony |-- | 2 | maxhou |-- +------+--------+

二、实战二:Redis Cluster 集群

1. Redis Cluster 基础

Redis Cluster 是 Redis 官方提供的分布式方案,通过分片将数据分布在多个节点上,每个节点负责一部分哈希槽(slot)。Redis Cluster 共有16384 个槽位,集群中的主节点各负责一部分槽位。本实战搭建一个3 主 3 从的 Redis Cluster,3 个从节点分别复制对应的主节点,实现高可用。Redis 源码可从 Redis 官网 下载。

2. Redis Dockerfile(多阶段构建)

准备 Redis 配置文件:

mkdir-p/data/rediscluster/rediscd/data/rediscluster/rediswgethttp://download.redis.io/releases/redis-7.0.11.tar.gz

找到里面的配置文件模板redis.conf,修改以下内容,完成配置文件创建,创建好的文件放到目录/data/rediscluster/redis :

daemonize no port 6379 dir /data/redis cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 requirepass 123456 masterauth 123456 bind * -::*

📌 Redis Cluster 配置参数详见 Redis Cluster 文档。

Dockerfile(多阶段构建,从源码编译 Redis):

# ---- 第一阶段:构建阶段 ---- FROM ubuntu:22.04 as buildstage RUN sed -i 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.list && apt update RUN apt install -y build-essential # ADD 会自动解压 tar 包 ADD redis-7.0.11.tar.gz / ADD redis.conf /redis/ WORKDIR /redis-7.0.11 # 编译 Redis RUN make # 将编译产物移动到 /redis 目录 RUN mv /redis-7.0.11/src/redis-server /redis/ && mv /redis-7.0.11/src/redis-cli /redis/ ENTRYPOINT ["/redis/redis-server", "/redis/redis.conf"] # ---- 第二阶段:运行阶段 ---- FROM ubuntu:22.04 RUN mkdir -p /data/redis && mkdir -p /redis # 只拷贝编译好的二进制文件和配置文件 COPY --from=buildstage /redis /redis EXPOSE 6379 ENTRYPOINT ["/redis/redis-server", "/redis/redis.conf"]
# 构建并测试镜像dockerbuild-tmyredis:v1.0.dockerrun-d--nametestmyredis myredis:v1.0dockerps# CONTAINER ID IMAGE COMMAND STATUS PORTS# fd9495f93cec myredis:v1.0 "/redis/redis-server…" Up 1 second 6379/tcp testmyredisdockerrm-ftestmyredis

3. docker-compose.yml

/data/rediscluster目录下创建docker-compose.yml,定义 6 个 Redis 节点(redis01-06)和 1 个集群创建容器(redis07)。

version:"3"services:redis01:image:myredis:v1.0build:./redisports:-6379:6379container_name:redis01healthcheck:test:/redis/redis-cli pinginterval:10stimeout:5sretries:10redis02:image:myredis:v1.0container_name:redis02healthcheck:test:/redis/redis-cli pinginterval:10stimeout:5sretries:10# redis03-06 配置类似,省略...redis06:image:myredis:v1.0container_name:redis06healthcheck:test:/redis/redis-cli pinginterval:10stimeout:5sretries:10redis07:image:myredis:v1.0container_name:redis07# 覆盖 entrypoint,执行集群创建命令entrypoint:["/redis/redis-cli","--cluster","create","redis01:6379","redis02:6379","redis03:6379","redis04:6379","redis05:6379","redis06:6379","--cluster-replicas","1","-a","123456","--cluster-yes"]depends_on:redis01:condition:service_healthyredis02:condition:service_healthy# ... redis03-06 类似redis06:condition:service_healthy

📌关键设计

  • healthcheck确保每个 Redis 节点启动并就绪后才标记为 healthy;
  • redis07depends_on使用condition: service_healthy,确保 6 个节点全部健康后才执行集群创建命令;
  • --cluster-replicas 1表示每个主节点配 1 个从节点(3 主 3 从);
  • --cluster-yes自动确认集群创建提示,无需手动输入。

4. 构建与验证

# 构建镜像dockercompose build# 启动服务dockercompose up-d# ✔ Container redis06 Healthy 15.7s# ✔ Container redis01 Healthy 15.7s# ...# ✔ Container redis07 Started 16.0s# 查看容器状态dockercomposeps-a# redis01-06 状态为 Up (healthy)# redis07 状态为 Exited (0) ← 集群创建完成后自动退出# 查看 redis07 的日志,确认集群创建成功dockerlogs-fredis07

日志输出关键信息:

>>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica redis05:6379 to redis01:6379 Adding replica redis06:6379 to redis02:6379 Adding replica redis04:6379 to redis03:6379 ... [OK] All 16384 slots covered.
# 进入任意节点容器dockerexec-itredis01bash/redis/redis-cli-c-a123456# 查看集群信息127.0.0.1:6379>cluster info# cluster_state:ok# cluster_slots_assigned:16384# cluster_known_nodes:6# cluster_size:3# 测试数据写入(会自动重定向到对应槽位的节点)127.0.0.1:6379>seta123# -> Redirected to slot [15495] located at 192.168.192.6:6379# OK192.168.192.6:6379>get a# "123"

三、实战三:C++ 微服务编排与负载均衡

1. 微服务与容器编排

微服务架构是将大型应用分解成多个独立组件,每个组件有各自的责任领域。容器是微服务的最佳载体——环境一致、秒级启停、资源隔离、版本管理。Docker Compose 通过一个docker-compose.yml文件定义和运行多个容器,是微服务编排的核心工具。

在微服务架构中,同一服务通常部署多个实例以提高可用性。Nginx 作为反向代理,将请求分发到后端多个实例,实现负载均衡。Nginx 通过upstream模块定义后端服务器池,支持多种调度策略:

策略配置方式说明
轮询(默认)server host:port;按顺序逐一分配
加权轮询server host:port weight=N;按权重比例分配
ip_haship_hash;按客户端 IP 哈希分配,保证会话粘性
最少连接least_conn;分配给连接数最少的实例

📌 Nginx 负载均衡详见 Nginx upstream 文档。

本实战使用加权轮询策略,部署两个 C++ HTTP 服务实例,权重分别为 1 和 2。

2. C++ 服务与 Dockerfile

构建一个 C++ HTTP Web 服务器,使用 socket + pthread 实现多线程并发:

#include<iostream>#include<netinet/in.h>#include<string.h>#include<assert.h>#include<unistd.h>#include<pthread.h>usingnamespacestd;void*serverForClient(void*arg);intmain(){structsockaddr_insever_add;memset(&sever_add,0,sizeof(sever_add));sever_add.sin_family=PF_INET;sever_add.sin_addr.s_addr=htons(INADDR_ANY);sever_add.sin_port=htons(8081);intoption=1;intsocket_fd=socket(AF_INET,SOCK_STREAM,0);assert(socket_fd>=0);setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));intres=bind(socket_fd,(structsockaddr*)&sever_add,sizeof(sever_add));assert(res!=-1);res=listen(socket_fd,1);assert(res!=-1);cout<<"server init"<<endl;while(1){structsockaddr_inclient;intclient_len=sizeof(client);intconn_fd=accept(socket_fd,(structsockaddr*)&client,(socklen_t*)&client_len);pthread_data pdata;pdata.client_addr=client;pdata.sock_fd=conn_fd;pthread_t pt;pthread_create(&pt,NULL,serverForClient,(void*)&pdata);}return0;}void*serverForClient(void*arg){structpthread_data*pdata=(structpthread_data*)arg;intconn_fd=pdata->sock_fd;charrequest[1024];recv(conn_fd,request,1024,0);charbuf[520]="HTTP/1.1 200 ok\r\nconnection: close\r\n\r\n";send(conn_fd,buf,strlen(buf),0);charbuf2[1024]="<!DOCTYPE html><html><head>""<title>Welcome to C++ web server!</title>""</head><body>""<h1>Welcome to C++ webserver!</h1>""</body></html>";send(conn_fd,buf2,strlen(buf2),0);close(conn_fd);returnnullptr;}

Dockerfile(多阶段构建,编译后只保留二进制文件):

# ---- 第一阶段:构建 ---- FROM ubuntu:22.04 as buildstage RUN sed -i 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.list && apt update RUN apt install -y build-essential WORKDIR /src COPY ./main.cpp . RUN g++ main.cpp -o mycppweb -lpthread CMD ["/src/mycppweb"] # ---- 第二阶段:运行 ---- FROM ubuntu:22.04 COPY --from=buildstage /src/mycppweb / CMD ["/mycppweb"]

💡 多阶段构建使最终镜像只包含编译好的二进制文件,不包含 gcc 等编译工具。

3. Nginx 加权负载均衡配置

upstream backend { server mycppweb:8081 weight=1; server mycppweb2:8081 weight=2; } server { listen 80; access_log off; location / { proxy_pass http://backend; } }

📌weight=1weight=2表示mycppweb2获得的请求量是mycppweb的 2 倍。

Nginx Dockerfile:

FROM nginx:1.24.0 COPY ./bit.conf /etc/nginx/conf.d/ CMD ["nginx", "-g", "daemon off;"] ENTRYPOINT ["/docker-entrypoint.sh"]

4. docker-compose.yml

services:web:image:mynginx:v3.0build:context:./nginxports:-8112:80depends_on:mycppweb:condition:service_startedmycppweb:build:context:./cppwebimage:mycppweb:v2.0mycppweb2:image:mycppweb:v2.0

📌mycppweb2直接复用mycppweb构建的镜像mycppweb:v2.0,无需重复构建。

5. 构建与验证

# 构建镜像dockercompose build# 启动服务dockercompose up-d# 访问服务 6 次foriin$(seq16);docurlhttp://localhost:8112;done# 查看日志,可以看到加权负载均衡效果dockerlogs-fmycppms-mycppweb-1# mycppweb 收到约 2 次请求(weight=1)dockerlogs-fmycppms-mycppweb2-1# mycppweb2 收到约 4 次请求(weight=2)# 清理资源dockercompose down

访问 6 次后,mycppweb收到约 2 次请求,mycppweb2收到约 4 次请求,符合 1:2 的权重比例。


四、三个实战的 Docker 技巧对比

Docker 技巧MySQL 集群Redis 集群C++ 微服务
多阶段构建❌ 用官方镜像✅ 源码编译✅ 源码编译
/docker-entrypoint-initdb.d✅ 自动初始化
healthcheck✅ 节点就绪检测
depends_on形式列表形式(简单依赖)condition: service_healthycondition: service_started
entrypoint覆盖✅ 集群创建命令
command覆盖✅ MySQL 启动参数
镜像复用✅ 从库复用镜像✅ redis02-06 复用 redis01✅ mycppweb2 复用 mycppweb
反向代理✅ Nginx 负载均衡
docker compose down✅ 资源清理

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询