Golang无法Ping通Docker中运行的MySQL数据库求助
问题描述
我是Golang、Docker和MySQL的新手,正在macOS本地尝试使用Golang连接运行在Docker中的MySQL。
我的代码
package main import ( "context" "database/sql" _ "github.com/go-sql-driver/mysql" "log" "time" ) func dbConn() *sql.DB { db, err := sql.Open("mysql", "root:Abc123$#@tcp(172.17.0.2:3306)/test") if err != nil { log.Printf("Error %s when opening DB connection\n", err) return nil } db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) db.SetConnMaxLifetime(time.Minute * 2) ctx, cancelfunc := context.WithTimeout(context.Background(), time.Second) defer cancelfunc() err = db.PingContext(ctx) if err != nil { log.Printf("Error %s pinging DB", err) return db } log.Print("Connected to the DB successfully\n") defer func() { err := db.Close() if err != nil { log.Print(err) } }() return db } func main() { db := dbConn() defer db.Close() }
Docker运行命令
docker run --name mysql -e MYSQL_ROOT_PASSWORD=abcd1234 -p 3306:3306 -d mysql:8.0.30
错误信息
Error dial tcp 172.17.0.2:3306: i/o timeout pinging DB
已完成操作
Docker本地运行正常,已通过命令行创建了test_db:
mysql> create database test_db;
执行查询后显示:
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | test_db | +--------------------+ 6 rows in set (0.00 sec)
问题排查与修复
以下是你代码和配置中的几个错误,逐一修复即可解决问题:
连接地址错误
你使用了Docker容器的内部IP(172.17.0.2),但macOS上Docker已将容器3306端口映射到本地,直接用localhost或host.docker.internal即可,无需使用容器内部IP。密码不匹配
Docker启动时设置的root密码是abcd1234,但代码里写的是Abc123$#,两者不一致会导致认证失败。数据库名称错误
你创建的数据库是test_db,但代码里连接的是test,数据库名称不匹配。连接提前关闭
dbConn函数内的defer db.Close()会导致刚建立连接就被关闭,返回的DB对象处于无效状态,main函数再调用defer db.Close()会报错。需删除该内部关闭逻辑,将连接生命周期交给main函数管理。
修复后的完整代码
package main import ( "context" "database/sql" _ "github.com/go-sql-driver/mysql" "log" "time" ) func dbConn() *sql.DB { // 修正连接字符串:地址用localhost,密码匹配Docker设置,数据库名改为test_db db, err := sql.Open("mysql", "root:abcd1234@tcp(localhost:3306)/test_db") if err != nil { log.Printf("Error %s when opening DB connection\n", err) return nil } db.SetMaxOpenConns(10) db.SetMaxIdleConns(10) db.SetConnMaxLifetime(time.Minute * 2) // 适当延长超时时间,避免连接慢导致超时 ctx, cancelfunc := context.WithTimeout(context.Background(), 5*time.Second) defer cancelfunc() err = db.PingContext(ctx) if err != nil { log.Printf("Error %s pinging DB", err) db.Close() // 连接失败时手动关闭 return nil } log.Print("Connected to the DB successfully\n") return db } func main() { db := dbConn() if db == nil { log.Fatal("Failed to get DB connection") } defer db.Close() // 此处可添加你的数据库操作逻辑 }
额外注意事项
- 确保本地3306端口未被其他服务占用,若占用可修改Docker映射端口,比如
-p 3307:3306,代码里对应改为localhost:3307。 - MySQL 8.0默认使用
caching_sha2_password认证插件,若遇到认证错误,可在Docker启动命令中添加兼容参数:docker run --name mysql -e MYSQL_ROOT_PASSWORD=abcd1234 -p 3306:3306 -d mysql:8.0.30 --default-authentication-plugin=mysql_native_password
内容的提问来源于stack exchange,提问作者HSAR
相关产品推荐
相关产品推荐

