ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker Compose综合实战

Docker Compose综合实战 目录一、实战一MySQL 主从复制集群1. 主从同步原理2. 主库与从库 Dockerfile3. docker-compose.yml4. 构建与验证二、实战二Redis Cluster 集群1. Redis Cluster 基础2. Redis Dockerfile多阶段构建3. docker-compose.yml4. 构建与验证三、实战三C 微服务编排与负载均衡1. 微服务与容器编排2. C 服务与 Dockerfile3. Nginx 加权负载均衡配置4. docker-compose.yml5. 构建与验证四、三个实战的 Docker 技巧对比一、实战一MySQL 主从复制集群1. 主从同步原理MySQL 主从复制是指数据可以从一个 MySQL 主节点复制到一个或多个从节点。主要目的是读写分离提升性能、数据实时备份和高可用 HA。在主从复制的过程中基于三个线程来操作线程位置作用binlog dumpmaster读取 binlog 日志发送给 slaveI/Oslave接收 binlog写入本地 relaylogSQLslave读取 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-masterFROM 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 用户不需要手动创建配置CREATEUSERroot%IDENTIFIEDBYroot;grantreplicationslave,replicationclienton*.*toroot%;flushprivileges;从库slave/Dockerfile-slaveFROM mysql:5.7.36 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime COPY ./slave/slave.sql /docker-entrypoint-initdb.d从库配置脚本slave/slave.sqlchange mastertomaster_hostmysql-master,master_userroot,master_passwordroot,master_port3306;startslave;3. docker-compose.ymlversion:3services: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-id1,--log-binmaster-bin,--binlog-ignore-dbmysql,--binlog_cache_size256M,--binlog_formatmixed,--lower_case_table_names1,--character-set-serverutf8,--collation-serverutf8_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-id2,--relay_logslave-relay,--lower_case_table_names1,--character-set-serverutf8,--collation-serverutf8_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-id3,--relay_logslave-relay,--lower_case_table_names1,--character-set-serverutf8,--collation-serverutf8_general_ci]depends_on:-mysql-master4. 构建与验证# 构建镜像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-pmysqlSHOW SLAVE STATUS\G关键检查项Slave_IO_Running: Yes ← I/O 线程正常运行 Slave_SQL_Running: Yes ← SQL 线程正常运行 Seconds_Behind_Master: 0 ← 与主库延迟为 0-- 在主库创建数据库和表mysqlcreatedatabasetest;mysqlusetest;mysqlcreatetableusers(snoint,snamevarchar(20));mysqlinsertintousersvalues(1,pony);mysqlinsertintousersvalues(2,maxhou);-- 连接从库查看数据自动同步mysqlselect*fromusers;-- ---------------- | sno | sname |-- ---------------- | 1 | pony |-- | 2 | maxhou |-- --------------二、实战二Redis Cluster 集群1. Redis Cluster 基础Redis Cluster 是 Redis 官方提供的分布式方案通过分片将数据分布在多个节点上每个节点负责一部分哈希槽slot。Redis Cluster 共有16384 个槽位集群中的主节点各负责一部分槽位。本实战搭建一个3 主 3 从的 Redis Cluster3 个从节点分别复制对应的主节点实现高可用。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.cng /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 --frombuildstage /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-ftestmyredis3. docker-compose.yml在/data/rediscluster目录下创建docker-compose.yml定义 6 个 Redis 节点redis01-06和 1 个集群创建容器redis07。version:3services: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 节点启动并就绪后才标记为 healthyredis07的depends_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:6379cluster info# cluster_state:ok# cluster_slots_assigned:16384# cluster_known_nodes:6# cluster_size:3# 测试数据写入会自动重定向到对应槽位的节点127.0.0.1:6379seta123# - Redirected to slot [15495] located at 192.168.192.6:6379# OK192.168.192.6:6379get a# 123三、实战三C 微服务编排与负载均衡1. 微服务与容器编排微服务架构是将大型应用分解成多个独立组件每个组件有各自的责任领域。容器是微服务的最佳载体——环境一致、秒级启停、资源隔离、版本管理。Docker Compose 通过一个docker-compose.yml文件定义和运行多个容器是微服务编排的核心工具。在微服务架构中同一服务通常部署多个实例以提高可用性。Nginx 作为反向代理将请求分发到后端多个实例实现负载均衡。Nginx 通过upstream模块定义后端服务器池支持多种调度策略策略配置方式说明轮询默认server host:port;按顺序逐一分配加权轮询server host:port weightN;按权重比例分配ip_haship_hash;按客户端 IP 哈希分配保证会话粘性最少连接least_conn;分配给连接数最少的实例 Nginx 负载均衡详见 Nginx upstream 文档。本实战使用加权轮询策略部署两个 C HTTP 服务实例权重分别为 1 和 2。2. C 服务与 Dockerfile构建一个 C HTTP Web 服务器使用 socket pthread 实现多线程并发#includeiostream#includenetinet/in.h#includestring.h#includeassert.h#includeunistd.h#includepthread.husingnamespacestd;void*serverForClient(void*arg);intmain(){structsockaddr_insever_add;memset(sever_add,0,sizeof(sever_add));sever_add.sin_familyPF_INET;sever_add.sin_addr.s_addrhtons(INADDR_ANY);sever_add.sin_porthtons(8081);intoption1;intsocket_fdsocket(AF_INET,SOCK_STREAM,0);assert(socket_fd0);setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,option,sizeof(option));intresbind(socket_fd,(structsockaddr*)sever_add,sizeof(sever_add));assert(res!-1);reslisten(socket_fd,1);assert(res!-1);coutserver initendl;while(1){structsockaddr_inclient;intclient_lensizeof(client);intconn_fdaccept(socket_fd,(structsockaddr*)client,(socklen_t*)client_len);pthread_data pdata;pdata.client_addrclient;pdata.sock_fdconn_fd;pthread_t pt;pthread_create(pt,NULL,serverForClient,(void*)pdata);}return0;}void*serverForClient(void*arg){structpthread_data*pdata(structpthread_data*)arg;intconn_fdpdata-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 htmlhtmlheadtitleWelcome to C web server!/title/headbodyh1Welcome 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.cng /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 --frombuildstage /src/mycppweb / CMD [/mycppweb] 多阶段构建使最终镜像只包含编译好的二进制文件不包含 gcc 等编译工具。3. Nginx 加权负载均衡配置upstream backend { server mycppweb:8081 weight1; server mycppweb2:8081 weight2; } server { listen 80; access_log off; location / { proxy_pass http://backend; } }weight1和weight2表示mycppweb2获得的请求量是mycppweb的 2 倍。Nginx DockerfileFROM nginx:1.24.0 COPY ./bit.conf /etc/nginx/conf.d/ CMD [nginx, -g, daemon off;] ENTRYPOINT [/docker-entrypoint.sh]4. docker-compose.ymlservices:web:image:mynginx:v3.0build:context:./nginxports:-8112:80depends_on:mycppweb:condition:service_startedmycppweb:build:context:./cppwebimage:mycppweb:v2.0mycppweb2:image:mycppweb:v2.0mycppweb2直接复用mycppweb构建的镜像mycppweb:v2.0无需重复构建。5. 构建与验证# 构建镜像dockercompose build# 启动服务dockercompose up-d# 访问服务 6 次foriin$(seq16);docurlhttp://localhost:8112;done# 查看日志可以看到加权负载均衡效果dockerlogs-fmycppms-mycppweb-1# mycppweb 收到约 2 次请求weight1dockerlogs-fmycppms-mycppweb2-1# mycppweb2 收到约 4 次请求weight2# 清理资源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_startedentrypoint覆盖—✅ 集群创建命令—command覆盖✅ MySQL 启动参数——镜像复用✅ 从库复用镜像✅ redis02-06 复用 redis01✅ mycppweb2 复用 mycppweb反向代理——✅ Nginx 负载均衡docker compose down——✅ 资源清理
返回列表