Docker环境下Go Web服务连接MySQL容器报connection refused问题求助
问题修复方案
1. 核心错误1:容器内部网络端口使用错误
docker-compose中ports: "3307:3306"的规则是宿主机端口:容器内部端口,同Docker网络内的服务互相访问时,只能用容器内部监听的端口,而非宿主机映射端口。
需要修改main.go中的数据库连接地址:
// 错误写法 db, err := sql.Open("mysql", "user:password@tcp(db:3307)/example") // 正确写法,额外补充parseTime参数是mysql驱动的强制要求,避免后续时间类型操作报错 db, err := sql.Open("mysql", "user:password@tcp(db:3306)/example?parseTime=true")
2. 核心错误2:服务启动顺序无依赖+MySQL初始化慢
MySQL容器首次启动需要执行初始化脚本、配置账号权限,耗时远长于Go服务启动,即使配置了depends_on也无法保证MySQL完全就绪后再启动Go服务。
修复方案:
- 先修正
docker-compose.yml的语法错误与依赖配置:version: '3' services: db: build: context: ./database volumes: - database:/database/data environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: example MYSQL_USER: user MYSQL_PASSWORD: password container_name: container_db ports: - "3307:3306" networks: - default # 确认MySQL绑定所有地址,避免本地访问限制 command: --bind-address=0.0.0.0 api: build: context: . restart: on-failure container_name: "container_api" # 修正原配置中volumes缩进错误的问题 volumes: - api:/usr/api ports: - "8080:8080" networks: - default # 增加服务依赖,保证先启动db再启动api depends_on: - db volumes: database: api: - 可选优化:在Go代码中增加数据库连接重试逻辑,避免首次启动MySQL未就绪导致的启动失败,示例:
记得导入// 原db.Ping()部分替换为重试逻辑 var pingErr error for i := 0; i < 10; i++ { pingErr = db.Ping() if pingErr == nil { break } log.Printf("数据库连接失败,2秒后重试,剩余重试次数:%d", 10 - i) time.Sleep(2 * time.Second) } if pingErr != nil { log.Fatal(pingErr) }time包。
3. 核心错误3:MySQL初始化SQL语法错误
example.sql中建表语句缺少逗号,会导致MySQL初始化失败、服务无法正常启动:
-- 错误写法 CREATE TABLE IF NOT EXISTS exampleTable ( id INT NOT NULL, name VARCHAR(2048) NOT NULL, lastName VARCHAR(2048) PRIMARY KEY (`id`) ); -- 正确写法,lastName字段后补充逗号 CREATE TABLE IF NOT EXISTS exampleTable ( id INT NOT NULL, name VARCHAR(2048) NOT NULL, lastName VARCHAR(2048), PRIMARY KEY (`id`) );
最终验证步骤
清理之前的错误容器与缓存卷,避免旧数据影响:
docker-compose down -v
重新构建启动服务:
docker-compose up --build
内容的提问来源于stack exchange,提问作者malajedala
相关产品推荐
相关产品推荐

