Go后端本地运行正常,Docker运行时MySQL连接被拒绝问题
问题原因
容器运行时,localhost或127.0.0.1指向容器自身的网络环境,而非宿主机的网络。本地用go run时,程序在宿主机运行,能直接访问宿主机上的MySQL;但容器里的程序访问localhost:3306,是在容器内部寻找MySQL服务,而你的MySQL大概率跑在宿主机或另一个独立容器里,因此会出现连接拒绝的错误。
解决办法
1. 用宿主机实际IP替换localhost
找到宿主机的局域网IP(比如192.168.x.x或10.x.x.x),修改代码中的DSN地址:
dsn := "joelwasike:joelwasike@tcp(192.168.1.100:3306)/talk?charset=utf8mb4&parseTime=True&loc=Local"
注意:需确保宿主机的MySQL允许外部IP访问——修改my.cnf里的bind-address为0.0.0.0,并给joelwasike用户授权远程访问权限。
2. 使用Docker宿主网络模式(不推荐生产环境)
启动容器时添加--net=host参数,让容器共享宿主机的网络栈,此时容器内的localhost会指向宿主机:
docker run --net=host mybackend:multistage
缺点:容器失去网络隔离性,生产环境不建议使用。
3. 用Docker Compose管理MySQL和后端容器的网络
如果MySQL也用Docker运行,通过Docker Compose创建自定义网络,让两个容器处于同一网络下,直接通过容器名访问MySQL:
- 编写
docker-compose.yml:
version: '3' services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: your_root_password MYSQL_DATABASE: talk MYSQL_USER: joelwasike MYSQL_PASSWORD: joelwasike ports: - "3306:3306" networks: - app-network backend: build: . image: mybackend:multistage depends_on: - mysql networks: - app-network networks: app-network: driver: bridge
- 修改代码中的DSN,用MySQL容器名
mysql作为地址:
dsn := "joelwasike:joelwasike@tcp(mysql:3306)/talk?charset=utf8mb4&parseTime=True&loc=Local"
- 启动服务:
docker-compose up -d
4. 用环境变量动态配置数据库地址(推荐)
不要硬编码数据库地址,通过环境变量注入配置,适配本地和容器环境:
- 修改代码:
import ( "fmt" "os" "gorm.io/driver/mysql" "gorm.io/gorm" ) func NewDB() (*DB, error) { dbHost := os.Getenv("DB_HOST") if dbHost == "" { dbHost = "localhost" // 本地环境默认值 } dsn := fmt.Sprintf("joelwasike:joelwasike@tcp(%s:3306)/talk?charset=utf8mb4&parseTime=True&loc=Local", dbHost) db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("数据库初始化失败") } return &DB{db}, nil }
- 启动容器时传入环境变量:
docker run -e DB_HOST=192.168.1.100 mybackend:multistage
如果用Docker Compose,在backend服务中添加:
environment: - DB_HOST=mysql
内容的提问来源于stack exchange,提问作者Joel Swakise TheDancer
相关产品推荐
相关产品推荐

