用 Docker Compose 一键部署高可用集群(MySQL + Tomcat + Nginx)

发布时间:2026/7/7 17:58:20

用 Docker Compose 一键部署高可用集群(MySQL + Tomcat + Nginx) 在五台虚拟机中将手工搭建的 KeepalivedNginxTomcatMySQL 高可用架构用 Docker Compose 实现标准化部署。前言之前我花了近一个月的时间手工搭建了一套基于 Keepalived、Nginx、Tomcat、MySQL 的高可用集群并成功将各组件容器化。但每次启动仍需要手动执行 docker run 命令环境迁移时也容易遗漏参数。最近我将这套架构统一用 Docker Compose 管理实现了“一键启动”这里记录下配置过程希望对你有帮助。一、项目架构回顾整套集群运行在五台 Redhat 虚拟机上各主机角色及 IP 如下主机 IP 地址 服务组件 MySQL 192.168.211.136 MySQL 5.7 Tomcat1 192.168.211.128 Tomcat 11 JSP 应用 Tomcat2 192.168.211.133 Tomcat 11 JSP 应用 Master Nginx 192.168.211.134 Nginx Keepalived (主) Backup Nginx 192.168.211.135 Nginx Keepalived (备)· VIP192.168.211.100由 Keepalived 管理用于对外统一入口。 · Nginx作为反向代理将请求轮询转发给两台 Tomcat。 · Tomcat提供 JSP 页面通过 JDBC 连接 MySQL 展示数据。 · MySQL存储服务器状态数据。容器化后Keepalived 继续运行在宿主机其他所有服务都跑在 Docker 容器中且用 Docker Compose 统一管理。二、Docker Compose 文件编写1、MySQL 主机192.168.211.136创建目录 /opt/mysql放入 docker-compose.ymlservices: mysql: image: mysql:5.7 container_name: mysql restart: always network_mode: host environment: MYSQL_ROOT_PASSWORD: AppPass123! volumes: - /var/lib/mysql:/var/lib/mysql - /etc/localtime:/etc/localtime:ro说明· network_mode: host让容器直接使用宿主机网络这样其他主机可以通过 192.168.211.136:3306 访问 MySQL。 · 数据卷挂载将宿主机原有的数据库目录/var/lib/mysql挂载进去保证数据持久化。 · 时区挂载确保容器时间与宿主机一致。启动命令cd /opt/mysql docker-compose up -d2、Tomcat 主机分别在 Tomcat1 和 Tomcat2 上创建 /opt/tomcat1 和 /opt/tomcat2 目录各放一个 docker-compose.yml。Tomcat1 的 docker-compose.ymlservices: tomcat1: image: my-tomcat:1.7 # 你的 Tomcat 镜像 container_name: tomcat1 restart: always ports: - 8081:8080 volumes: - /etc/localtime:/etc/localtime:roTomcat2 的 docker-compose.yml 只需将容器名改为 tomcat2其他相同services: tomcat2: image: my-tomcat:1.7 container_name: tomcat2 restart: always ports: - 8081:8080 volumes: - /etc/localtime:/etc/localtime:ro说明· 映射 8081:8080避免与宿主机其他服务冲突同时方便 Nginx 配置。 · 镜像 my-tomcat:1.7 是我提前构建好的包含 JSP 应用和 JDBC 驱动。启动cd /opt/tomcat1 docker-compose up -d # 在 Tomcat2 上同样操作3、Nginx 主机Master 和 BackupNginx 需要反向代理到两台 Tomcat因此我们构建了专用镜像 my-nginx:1.1其中已包含自定义配置文件 tomcat.conf内容如下upstream web { server 192.168.211.128:8081; server 192.168.211.133:8081; } server { listen 80; server_name 192.168.211.100; location / { proxy_pass http://web; proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } }在 Master 和 Backup 主机上分别创建 /opt/nginx-master 和 /opt/nginx-backup 目录放入相同的 docker-compose.ymlservices: nginx: image: my-nginx:1.1 container_name: nginx restart: always network_mode: host volumes: - /etc/localtime:/etc/localtime:ro说明· network_mode: host让 Nginx 容器直接监听宿主机的 80 端口便于与 Keepalived 配合。 · 启动前务必停止宿主机上的 nginx 服务避免端口冲突systemctl stop nginx systemctl disable nginx systemctl mask nginx pkill -9 nginx启动cd /opt/nginx-master docker-compose up -d # Backup 主机同样操作三、验证与测试1、检查容器状态在各主机上执行 docker-compose ps所有容器应显示 Up 状态。2、测试 MySQL 连接在任意 Tomcat 主机上curl http://192.168.211.128:8081/testdb.jsp应显示数据库中的表格数据。3、测试反向代理直接访问 Master IPcurl http://192.168.211.134应返回 Tomcat 页面。多次刷新观察轮询到两台 Tomcat。4、测试 VIP 高可用访问 VIPcurl http://192.168.211.100同样能正常返回。停止 Master 上的 Nginx 容器docker stop nginx等待几秒VIP 应漂移到 Backup再次访问 VIP 依然正常。四、踩坑记录· MySQL 数据目录权限容器内 MySQL 用户 UID999宿主机数据目录需 chown 999:999 /var/lib/mysql否则容器无法写入。 · Tomcat 驱动缺失记得在 Dockerfile 中添加 MySQL 驱动 JAR否则 testdb.jsp 会报 ClassNotFoundException。 · Nginx 配置不生效检查容器内 /etc/nginx/conf.d/ 是否存在 tomcat.conf若没有则重新构建镜像或挂载配置文件。 · 端口冲突启动 Nginx 容器前务必彻底停止宿主机 nginx 服务并用 ss -tlnp 确认 80 端口未被占用。 · YAML 缩进Docker Compose 对缩进敏感务必使用空格不要用 Tab。五、总结通过 Docker Compose我们将原本分散在五台虚拟机上的手工部署变成了每个主机上一个简单明了的 YAML 文件。现在无论是重启服务器还是在新环境中重建只需执行 docker-compose up -d 即可一键启动所有容器Keepalived 仍需手动启动但可用 systemd 管理。这种标准化方式不仅减少了人为失误还让整个架构变得可移植、可复现。接下来我会继续引入 Prometheus 监控和 Grafana 可视化并尝试用 Kubernetes 进行更高级的编排。

相关新闻