正确写法是:services中mysql服务名须与gin配置的数据库host一致(如mysql),gin服务通过depends_on声明依赖但需自行重试连接,禁用localhost/127.0.0.1,确保共用默认网络且不使用host网络模式。

docker-compose.yml 里 services 怎么写才不连不上数据库
Gin 后端启动就 panic 报 connection refused 或 unknown host 'mysql',八成是 services 定义没对齐网络或依赖逻辑。Docker Compose 默认为整个 docker-compose.yml 创建一个默认桥接网络,所有 service 都在这个网络里,但名字解析只认 service 名(不是容器名),且 depends_on 只控制启动顺序,不等服务“就绪”。
正确写法要点:
-
mysql服务必须显式声明container_name或直接用 service 名(如mysql)作为 Gin 应用里的数据库地址,例如mysql://root:password@mysql:3306/goadmin -
server(Gin 服务)的depends_on要写全,比如:depends_on: [mysql, redis],但别指望它自动等 MySQL 初始化完 - 避免在
server的environment里硬编码127.0.0.1或localhost—— 这在容器里指向自己,不是宿主机也不是其他服务 - 如果 Gin 项目读取配置文件(如
config.yaml),确保该文件中数据库 host 字段填的是mysql,而不是127.0.0.1
Gin 服务的 Dockerfile 为什么不能直接用 go run
本地开发用 go run main.go 没问题,但放进容器里会出问题:编译依赖、调试符号、CGO、运行时环境全都不干净,镜像体积大,还容易因 Alpine 基础镜像缺 libc 而 panic。生产环境必须用静态编译二进制。
推荐多阶段构建写法:
FROM golang:1.22-alpine AS builder WORKDIR /app COPY go.mod ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -a -o server . FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /app/server . CMD ["./server"]
关键点:
-
CGO_ENABLED=0禁用 CGO,避免 Alpine 上缺失libc导致运行失败 -
GOOS=linux明确目标系统,防止跨平台编译错误 - 最终镜像不带 Go 编译器和源码,体积通常压到 15MB 以内
- 别在 final 阶段用
alpine:edge或随意升级基础镜像,某些版本会删掉ca-certificates,导致 Gin 访问 HTTPS 外部接口失败
前端 Vue 和后端 Gin 怎么配通请求路径
Vue 项目打包后是纯静态文件,由 Nginx 托管;Gin 是 API 服务。两者部署在同一 Compose 文件里时,常见问题是前端发请求 404 或 CORS,根源不在代码而在反向代理配置和网络拓扑。
典型解法是让 Nginx 把 /api/ 开头的请求代理到 Gin 服务:
location /api/ {
proxy_pass http://server:8000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
对应 Compose 中需确保:
-
server服务暴露的端口(如8000)**不映射到宿主机**(即不要写ports: ["8000:8000"]),只用于内部通信 -
web(Nginx)服务通过depends_on: [server]启动,并在networks下共享同一自定义网络(如gva-net) - Vue 项目里 Axios 的 base URL 设为
/api,而非http://localhost:8000/api—— 后者在浏览器里会跨域,且宿主机端口在容器内根本不可达 - 如果用
network_mode: "host",所有服务都退化到宿主机网络,service 名解析失效,mysql就变127.0.0.1,极易踩坑
docker compose up -d 后 Gin 日志不输出或卡住不动
执行 docker compose up -d 后 docker compose logs server 看不到日志,或者日志停在 “listening on :8000” 就不动,大概率是 Gin 没开启标准输出或 stdout 被重定向了。
检查项:
- Gin 默认使用
log.Println写到 stdout,没问题;但如果项目用了第三方日志库(如zap),要确认是否调用了zap.NewStdLogAt或设置了Output: os.Stdout - Dockerfile 的
CMD必须是前台进程,不能加&或nohup,否则容器启动即退出 - 检查 Gin 是否启用了
gin.SetMode(gin.ReleaseMode)—— 这个模式下部分 debug 日志会被屏蔽,但不影响功能,只是看着“没日志” - 若 Gin 使用了
http.Server自定义配置,确保srv.ListenAndServe()没被包裹在 goroutine 里却没做错误处理,否则 panic 会静默吞掉 - 最简单验证方式:进容器
docker exec -it <server-container-id> sh</server-container-id>,手动跑./server,看是否真能启动并响应 curl localhost:8000/ping
depends_on 不等于“数据库已 ready”,得靠应用层重试或加 wait-for-it.sh 脚本兜底。











