You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

问题排查与修复

以下是你代码和配置中的几个错误,逐一修复即可解决问题:

  1. 连接地址错误
    你使用了Docker容器的内部IP(172.17.0.2),但macOS上Docker已将容器3306端口映射到本地,直接用localhost或host.docker.internal即可,无需使用容器内部IP。

  2. 密码不匹配
    Docker启动时设置的root密码是abcd1234,但代码里写的是Abc123$#,两者不一致会导致认证失败。

  3. 数据库名称错误
    你创建的数据库是test_db,但代码里连接的是test,数据库名称不匹配。

  4. 连接提前关闭
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 03:40:39