本文记录我在 Linux 服务器上使用 Docker Compose 部署一个 Go 聊天系统时遇到的各种坑,以及完整的排障思路。文章不走概念教学路线,而是基于真实错误日志 + 实战修复过程展开。希望能给后来者提供可复用的经验。
1. 背景
项目结构在本地 Windows 环境下开发良好。目标是在 Linux(CentOS)服务器上通过 Docker Compose 启动三大服务:
-
MySQL 8.0
-
Redis 7
-
Go Chat Server(自构建镜像)
本以为是三分钟小事,结果一路从 YAML 语法错、容器冲突、MySQL 初始化失败、Redis 域名解析失败,一直踩到跨系统 MySQL 连接问题。
下面按时间线回放整个排障过程。
2. Docker Compose 报错:服务名冲突
第一次 docker compose up -d 就报:
Error response from daemon: Conflict. The container name "/mysql" is already in use
问题不复杂:服务器上早就有个叫 mysql 的残留容器,Compose 创建新容器冲突。
解决方案:
docker rm -f mysql
docker compose up -d
经验总结:
docker ps 只会显示活着的容器,很多死掉的容器会被 -a 才能看到,而正是它们在占用着名字。
3. YAML 语法错误:行尾符号、缩进、引号
遇到过几次:
yaml: line 26: mapping values are not allowed in this context
这种报错 90% 是:
-
多了冒号
-
引号不成对
-
-v换行后缩进不一致 -
Windows 文件换行符 CRLF
最终是某一行多了一个意外字符,通过重新复制 YAML 格式解决。
经验总结:
YAML 的错误提示永远不可信。找到报错行没意义,直接从最近修改的几行开始查。
4. 服务启动顺序问题:MySQL 启动慢导致 Chat Server 失败
Chat Server 在启动时不断输出:
初始化数据库失败:连接数据库失败:dial tcp 172.x.x.x:3306: connect: connection refused
原因非常明确:
MySQL 容器启动还没完成,Go 程序就来连,连不上自然报错。
一般要么用 depends_on 配合健康检查,要么让应用层自动重试。
本项目服务端已有重试机制,因此数次“失败 → 成功”是正常现象。
最终日志出现:
MySQL 数据库连接成功!
说明数据库稳定运行。
5. Redis 域名解析失败:服务名不存在
Chat Server 报错:
初始化redis失败:redis ping failed dial tcp: lookup chat-redis on 127.0.0.11:53: no such host
分析:
-
compose 中 redis 的服务名是 redis
-
chat-server 配置用的是 chat-redis
-
网络别名需要在 compose 中声明
最终通过在 redis 服务中加入:
networks:
chat-net:
aliases:
- chat-redis
成功解决。
经验总结:
Docker Compose 网络下的域名解析走内部 DNS,所有容器以服务名作为 hostname。要用别名,记得添加 alias。
6. MySQL 表不存在:初始化 SQL 未创建表
客户端提示:
Error 1146 (42S02): Table 'net_chat.users' doesn't exist
MySQL 明确没有初始化表结构,原因如下:
-
我以为 Docker 会自动执行 init SQL
-
实际上只有在容器第一次创建数据目录时才执行
docker-entrypoint-initdb.d下文件 -
我重新部署用了同一个数据卷 → 不会再运行 SQL
最终登录容器内手动建表即可:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
create_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
经验总结:
使用 docker-entrypoint-initdb.d 时一定要记住:
初始化脚本只在首次为空数据卷时运行一次。
7. 运行客户端:Linux 环境无 go 命令
在服务器执行客户端时报:
bash: go: 未找到命令...
这是因为生产服务器没有安装 Go,解决方法:
wget https://go.dev/dl/go1.24.4.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.24.4.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
经验总结:
开发环境和部署环境不等价,尤其生产机器通常不会预装编译工具链。
8. Windows 客户端无法连接 Linux Docker MySQL
Linux 上运行正常,但 Windows 客户端死活连不上 MySQL。
常见原因:
-
Docker 没映射 3306
-
防火墙阻挡 3306
-
MySQL 用户没有远程权限
-
bind-address 锁定 127.0.0.1
最终检查发现 Docker Compose 内确实没映射端口。
修复:
mysql:
ports:
- "3306:3306"
加上远程用户授权:
CREATE USER 'appuser'@'%' IDENTIFIED BY 'apppass123';
GRANT ALL PRIVILEGES ON net_chat.* TO 'appuser'@'%';
FLUSH PRIVILEGES;
Windows 成功通过:
mysql -h <Linux_IP> -u appuser -papppass123
经验总结:
不开放端口,跨主机永远连不上。
别过度怀疑 MySQL,80% 问题都是端口没映射。
9. 整体架构最终稳定运行
最终 docker compose config 显示:
-
chat-server → 使用
redis:6379成功连接 redis -
redis → alias 为
chat-redis -
mysql → 映射 3306,客户端可访问
-
三服务共用 chat-net 网络
访问日志确认:
MySQL 数据库连接成功!
初始化redis成功
服务端正在监听端口 :8080
系统在 Linux 上顺利跑通。
10. 全程经验总结
这次部署踩坑总结:
1)容器网络
服务之间通信必须走 服务名 而不是 IP。
2)Compose 的端口
所有跨主机访问必须在 ports: 中映射出来。
3)日志是唯一真相
每个坑都是日志给出线索:
-
DNS 失败
-
连接拒绝
-
表不存在
-
找不到命令
4)顺序问题大于配置问题
数据库启动慢引发的依赖服务报错经常被误判为配置错误。
5)跨平台开发注意连接方式
Windows 客户端要连接容器 MySQL,必须确认:
-
外部可达
-
用户已授权
-
防火墙放行



346

被折叠的 条评论
为什么被折叠?



