【问题标题】:Access MySQL in one container from another container从另一个容器访问一个容器中的 MySQL
【发布时间】:2019-11-02 04:16:59
【问题描述】:

我正在尝试以下方法:

  • 在一个带有暴露端口的容器中运行 MySQL 5.5,例如 4200。
  • 在一个带有暴露端口的容器中运行 MySQL 5.7,比如 4300。
  • 旋转一个 golang 容器来运行我的应用程序。

我的想法是我需要针对不同的数据库版本运行测试。

为此,我需要能够与我的 golang 容器中的每个 sql 容器通信。

我尝试过的:

方法 1 - 使用 --link:

MYSQL 容器:

docker run --name mysql55c -p 127.0.0.1:4200:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.5

GO LANG 应用容器

docker run -w /go/src/app -it --link mysql55c -d --name golangapp -v $(pwd):/go/src/app golang bash -c "go get github.com/go-sql-driver/mysql;go build main.go; go test -v
--config ./config.ini"

方法 2 - 使用 --net (bridge network &host): 创建一座桥梁

docker network mynw

MYSQL 容器:

docker run --name mysql55c --net mynw -p 127.0.0.1:4200:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.5

GO LANG 应用容器

docker run -w /go/src/app -it --net mynw -d --name golangapp -v $(pwd):/go/src/app golang bash -c "go get github.com/go-sql-driver/mysql;go build main.go; go test -v
--config ./config.ini"

没有自己搭建桥接网络,我也累了

--网络主机

我能够从主机连接到 sql 容器 - mysql 工作台。 但是,当尝试连接到容器内的 mysql 服务器时,golangapp 出现连接被拒绝错误。

所有容器都在同一个主机上。

我没有使用 dockerfile 或 docker compose as:

  • 尝试使用 docker cli 命令完成上述操作,以便使用官方 docker 映像轻松集成 jenkins。

Go 代码使用配置 url 连接到数据库

func dbconn() (*sql.DB, error) {
    opendb, err := sql.Open("mysql", *dsn + *dbname) //coming from flag
    if err != nil {
        return nil, err
    }
    return opendb, nil
}

我在配置中尝试过的dsn url组合:

  • dsn = "root:root@tcp(localhost:4200)/"
  • dsn = "root:root@tcp(172.17.0.0.x:4200)/" (docker0 ip)

  • dbname="somename"

我们如何看待上面的内容? 欢迎提出关于实现我的目标的最佳实践或新方法的建议:) 需要帮忙!! 谢谢你:)

【问题讨论】:

  • 您的 Go 代码使用的数据库连接 URL 是否正确? (只是为了确保)
  • @andreybleme 是的,我用来连接的 url 就像我在上面的配置中提到的那样。我正在使用 mysql 驱动程序连接到它。也会更新 go 代码:)
  • mysqld --verbose --help | grep bind-address => 检查绑定地址
  • @Ntwobike 我使用上述命令检查了 mysql55c 容器内的绑定地址,没有设置默认绑定地址。这是问题吗?如果是,我是否需要编写一个 docker 文件将绑定地址设置为 0.0.0.0 或者我可以使用 docker run 吗?
  • 如果它的 0.0.0.0 或根本不存在,那么您可以从任何 ip 连接。然后检查您的用户是否可以从 docker network SELECT user,host FROM mysql.user 连接; => user | %user | 172.* 我也希望你在你的 Go 应用程序中通过容器名称来引用 mysql?

标签: docker jenkins containers devops dockerhub


【解决方案1】:

感谢以上答案,我能够解决我的问题。

任何了解 docker 网络基础知识并且只想要解决方案的人都可以完全忽略这个答案。

我正在为可能刚刚开始使用 docker 并且对 docker 网络没有清晰了解的任何人写这个答案。

问题:不同 docker 容器之间的通信。

要在 docker 中的 n 个不同容器之间进行通信,我们首先需要了解 docker 网络是如何工作的:

  • 每当我们在主机中安装 docker 时,都会创建一个 docker0 虚拟接口/网桥。 这基本上是一个虚拟以太网桥,可以自动与连接到它的任何其他网络接口通信。
  • docker 0 接口有一个 ip 地址,比如说 172.0.0.x。
  • 此 IP 的后续容器子网。
  • 因此,容器之间的任何通信都可以通过 docker 网桥或使用主机私有 IP 进行。

上图可以帮助你更好的理解。

Docker0: Docker0 与 IP 的接口。

现在,进入命令:

使用此命令获取容器的 IP:

How to get a Docker container's IP address from the host?

docker 检查 -f '{{范围 .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id

SQL 容器:

docker run --name mysql55c -p 4500:3306 -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=db_ngen -d mysql:5.5

上述命令创建了一个名为 mysql55c 的容器,其 ip 从 docker0 子网。

Golang 容器

docker run -w /go/src/app -it -d --name golangapp --link mysql55c:db -v $(pwd):/go/src/app golang bash

上面的容器创建了一个名为golangapp的容器。

需要注意的重要一点是--link 命令。
此命令允许两个容器相互发现。
但是在引入 docker 网络功能之后,这可以使用 docker 默认桥接网络或用户定义的网络来完成。

容器 Ip 的:

现在,我们可以看到我们可以使用默认的 docker bridge 网络在容器之间进行通信。

供参考:

覆盖网络

用户定义的网桥

默认桥接网络

希望以上内容对你有所帮助,如有错误,请随时纠正我。

谢谢你:)

【讨论】:

    【解决方案2】:

    这应该可行,请按照下列步骤操作:

    • 运行mysql容器docker run --name mysql55c -p 4200:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.5
    • 为golang创建Dockerfile,内容如下:
    FROM golang:latest
    
    COPY . /
    RUN go get "github.com/go-sql-driver/mysql"
    CMD go run /main.go
    
    • 使用以下内容创建main.go
    package main
    
    import(
            _ "github.com/go-sql-driver/mysql"
            "database/sql"
            "log"
    )
    
    func main() {
        // Open up our database connection.
        db, err := sql.Open("mysql", "root:root@tcp(192.168.0.33:4200)/mysql")
    
        // if there is an error opening the connection, handle it
        if err != nil {
            log.Print(err.Error())
        } else {
            log.Print("DB connected successfully")
        }
    
        defer db.Close()
    
    }
    
    • 使用docker build -t goapp .构建golang容器镜像
    • 运行golang容器docker run -itd goapp
    • 查看 golang 容器的日志:
    $ docker logs dbd5294abd61
    2019/06/19 13:24:17 DB connected successfully
    

    注意: 我运行了暴露在主机 4200 端口上的 mysql 容器。在 golang 代码中,我的连接字符串是 root:root@tcp(192.168.0.33:4200)/mysql,其中 192.168.0.33 是我机器的私有 IP。

    您的主要收获应该是您的数据库连接字符串应该指向您主机的私有/公共 IP。如果你在没有容器链接的情况下运行 golang。

    如果在运行 golang 时使用容器链接,假设 docker run -itd --link mysql55c:mydb goapp 那么你的golang代码中的mysql连接字符串应该是root:root@tcp(mydb:4200)/mysql

    试试这个并告诉我。

    【讨论】:

      猜你喜欢
      • 2021-03-04
      • 1970-01-01
      • 2017-07-12
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 2019-06-13
      • 2020-07-26
      • 2021-12-08
      相关资源
      最近更新 更多