Go容器连不上MySQL主因是网络隔离与地址错误:需共用自定义网络并以容器名作host;MySQL启动慢需重试或健康检查;大镜像应多阶段构建;挂载目录须匹配UID 999。
docker run 启动 MySQL 容器时,Go 连不上:检查网络和地址
Go 应用在容器里连不上 MySQL,八成是地址写错了。宿主机上用
能连,放进容器后必须换地址——Docker 默认不共享宿主机网络命名空间。
常见错误现象:
或
。
MySQL 容器启动时加
,Go 容器也用同一个自定义网络(别用
默认网桥)
Go 代码里数据库 DSN 中的 host 改成 MySQL 容器名,比如
,其中
是
指定的名字
别暴露 3306 到宿主机再连
——这在 Linux 上默认不可用,且增加跳转延迟
docker-compose.yml 里 MySQL 启动慢,Go 服务报错 timeout
Go 程序启动快,MySQL 初始化要十几秒(尤其首次启动、有初始化 SQL 时),直接硬连必然失败。这不是 Go 写得有问题,是依赖没等齐。
使用场景:本地开发或 CI 环境中,
在容器内执行,但 MySQL 还没 ready。
立即学习
“
go语言免费学习笔记(深入)
”;
在 Go 代码里加简单重试逻辑,例如用
+
循环,超时 30 秒,间隔 2 秒重试
或者用 Compose 的
配合健康检查(
),但注意:
只等容器启动,不等 MySQL 就绪;必须配
MySQL 健康检查建议写成:
(密码用双
防止 shell 展开)
Go 编译的二进制体积大、启动慢:用多阶段构建压缩镜像
直接
构建再运行,镜像动辄 900MB+,里面全是编译工具链,线上完全不需要。
性能影响:镜像拉取慢、容器启动略拖沓、CI 缓存效率低。
第一阶段用
编译,
第二阶段用
或
,只 COPY 二进制文件,体积可压到 15MB 以内
别在 alpine 上跑 CGO 开启的程序(比如用
驱动而非
),会缺
报
MySQL 数据目录挂载后权限报错:alpine 容器里 user 不存在
用
挂载宿主机目录给 MySQL 存数据,结果容器起不来,日志刷屏
或
。
根本原因:Alpine 镜像没有
用户,而官方
镜像默认以该用户运行。
方案一:挂载时显式指定 UID/GID,
(999 是官方 MySQL 镜像中 mysql 用户的 UID)
方案二:改用非 Alpine 的 MySQL 镜像,比如
(Debian base),自带 mysql 用户
方案三:在 docker-compose.yml 里加
,绕过用户名查找
Go 和 MySQL 容器协同最麻烦的从来不是语法,而是两个进程生命周期不同步、文件权限跨系统、网络命名空间隔离这些“看不见的边界”。调通一次不难,难的是下次换环境又掉坑里——建议把网络名、DSN 地址、UID、健康检查这几处都写死在
顶部注释里,省得翻历史记录。
localhostconnect: connection refuseddial tcp 127.0.0.1:3306: connect: connection refused--network mynetbridgemysql://root:pass@mysql:3306/mydbmysqldocker run --name mysql ...host.docker.internalgo run main.gosql.Opendb.PingContextdepends_onhealthcheckdepends_oncondition: service_healthytest: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"]$FROM golanggolang:1.22-alpineCGO_ENABLED=0 go build -a -ldflags '-s -w' -o /app/main .alpine:latestscratchmysqlmysql-driver/mysqllibcno such file or directoryvolumemysqld: Can't create/write to filechown: unknown user mysqlmysqlmysql:8.0chown -R 999:999 ./mysql-datamysql:8.0user: "999:999"docker-compose.yml