go容器连不上mysql主因是网络隔离与地址错误:需共用自定义网络并以容器名作host;mysql启动慢需重试或健康检查;大镜像应多阶段构建;挂载目录须匹配uid 999。

docker run 启动 MySQL 容器时,Go 连不上:检查网络和地址
Go 应用在容器里连不上 MySQL,八成是地址写错了。宿主机上用 localhost 能连,放进容器后必须换地址——Docker 默认不共享宿主机网络命名空间。
常见错误现象:connect: connection refused 或 dial tcp 127.0.0.1:3306: connect: connection refused。
- MySQL 容器启动时加
--network mynet,Go 容器也用同一个自定义网络(别用bridge默认网桥) - Go 代码里数据库 DSN 中的 host 改成 MySQL 容器名,比如
mysql://root:pass@mysql:3306/mydb,其中mysql是docker run --name mysql ...指定的名字 - 别暴露 3306 到宿主机再连
host.docker.internal——这在 Linux 上默认不可用,且增加跳转延迟
docker-compose.yml 里 MySQL 启动慢,Go 服务报错 timeout
Go 程序启动快,MySQL 初始化要十几秒(尤其首次启动、有初始化 SQL 时),直接硬连必然失败。这不是 Go 写得有问题,是依赖没等齐。
使用场景:本地开发或 CI 环境中,go run main.go 在容器内执行,但 MySQL 还没 ready。
- 在 Go 代码里加简单重试逻辑,例如用
sql.Open+db.PingContext循环,超时 30 秒,间隔 2 秒重试 - 或者用 Compose 的
depends_on配合健康检查(healthcheck),但注意:depends_on只等容器启动,不等 MySQL 就绪;必须配condition: service_healthy - MySQL 健康检查建议写成:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"](密码用双$防止 shell 展开)
Go 编译的二进制体积大、启动慢:用多阶段构建压缩镜像
直接 FROM golang 构建再运行,镜像动辄 900MB+,里面全是编译工具链,线上完全不需要。
性能影响:镜像拉取慢、容器启动略拖沓、CI 缓存效率低。
- 第一阶段用
golang:1.22-alpine编译,CGO_ENABLED=0 go build -a -ldflags '-s -w' -o /app/main . - 第二阶段用
alpine:latest或scratch,只 COPY 二进制文件,体积可压到 15MB 以内 - 别在 alpine 上跑 CGO 开启的程序(比如用
mysql驱动而非mysql-driver/mysql),会缺libc报no such file or directory
MySQL 数据目录挂载后权限报错:alpine 容器里 user 不存在
用 volume 挂载宿主机目录给 MySQL 存数据,结果容器起不来,日志刷屏 mysqld: Can't create/write to file 或 chown: unknown user mysql。
根本原因:Alpine 镜像没有 mysql 用户,而官方 mysql:8.0 镜像默认以该用户运行。
- 方案一:挂载时显式指定 UID/GID,
chown -R 999:999 ./mysql-data(999 是官方 MySQL 镜像中 mysql 用户的 UID) - 方案二:改用非 Alpine 的 MySQL 镜像,比如
mysql:8.0(Debian base),自带 mysql 用户 - 方案三:在 docker-compose.yml 里加
user: "999:999",绕过用户名查找
docker-compose.yml 顶部注释里,省得翻历史记录。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











