使用Go和Docker无法连接到MySQL服务器 - dial tcp 127.0.0.1:3306:connect:连接被拒绝。

9

我在我的Mac上安装了Mysql Community Server,已经设置好并且可以正常工作,我可以使用Navicat for MySQL在localhost:3306上连接它。然而,每当我尝试从使用docker-compose运行的Go应用程序连接到数据库时,我都会收到以下错误:

dial tcp 127.0.0.1:3306: connect: connection refused

这是我的Go代码:

// dbUser, dbPassword, & dbName are all variables that definitely contain the correct values
db, err = sql.Open("mysql", dbUser+":"+dbPassword+"@tcp(localhost:3306)/"+dbName)

if err != nil {
    panic(err.Error())
}

defer db.Close()

query, err := db.Query("INSERT INTO test_table(test_field) VALUES(This is a test)")

if err != nil {
    panic(err.Error())
}

defer query.Close()

我正在导入:

"database/sql"
_ "github.com/go-sql-driver/mysql"

非常感谢您提供的帮助,请您知悉。


https://dev59.com/SGIj5IYBdhLWcg3w95nA - kosa
这个问题之前已经有人问过并得到了答案。请查看从Docker VM连接到主机 - Jacob
5个回答

14

在 Docker 中(特别是在 Mac 上,因为 Docker 在表面下运行在 Linux VM 中),你无法从 localhost 连接到主机并访问其提供的服务。

然而,通过使用特殊的主机名 docker.for.mac.localhost 的 IP 地址,可以访问主机。如果没有其他 Docker 网络问题,将连接字符串修改为 docker.for.mac.localhost:3306 应该解决此问题,并允许访问主机上的服务。

(有关此解决方法的更多详细信息,请参见 Docker 文档。)


这个方法可行,谢谢 :) 谢谢你的解释。我猜因为这是一个变通方法,所以我不应该这样做,使用docker-compose开发MySQL的正确方式是什么?(我对docker非常陌生) - william205
2
这种方法本质上没有什么问题。它的好处是您的数据库数据会持久存在 - 即使您意外销毁了MySQL容器,数据也不会消失,您也不必担心将主机卷映射到此类容器中,这更加复杂。另一种选择是在Docker中托管MySQL实例,并以相同方式使用Docker Compose进行设置。此时,您将获得Docker的内部容器对容器网络功能。 docker.for.mac.localhost的主要优点是Docker守护程序将自动将该名称映射到主机IP。 - Cosmic Ossifrage
谢谢你,我非常感激 :) - william205

9

你应该像这样打开:

db, err := sql.Open("mysql", "root:root@tcp(mysql:3306)/GoLife")

mysql 是 Docker Compose 的服务名称。


1

我的解决方案最终是结合了这个页面上的答案。我一直收到这个错误:

dial tcp 127.0.0.1:3306: connect: connection refused

我的连接构建如下:

db, err := sql.Open("mysql",  "root:password@/mydbname?parseTime=true")

我读了@Cosmic Ossifrage的内容,但不确定如何实现,所以我采用了Vitah给出的答案。但这并没有起作用,因为mysql:3306不是docker能理解的位置,所以连接失败。然后我将@Cosmic Ossifrage和Vitah的解决方案结合起来,得到了一个可行的设置。
db, err:= sql.Open("mysql", "root:password@tcp(docker.for.mac.localhost:3306)/mydbname?parseTime=true")

希望这能帮助任何寻找答案的人!感谢其他贡献者帮助我拼凑出来。

0

我认为处理这个问题的最佳方式是使用docker iptables

如果你的docker-composer.yml

version: '3.9'
services:
    api:
        container_name: webapi
        restart: on-failure
        depends_on:
            - mariadb
        ...
   db:
        image: mariadb
        container_name: mariadb
        volumes:
            - database:/var/lib/mysql
        ports:
            - 3306:3306
        ...

您可以像这样使用db服务的container_name
func main() {
  dsn := "user:pass@tcp(mariadb)/dbname?charset=utf8"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

  if err != nil {
    panic(err.Error())
  }
}

非常简单,如果您的db服务具有动态IP,则建议使用此方法。


0

我使用了本地机器的IP地址来解决这个问题,这是为了从docker-compose连接到运行在本地的MySQL服务器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接