从另一个容器访问一个容器中的 MySQL

Access MySQL in one container from another container

我正在尝试以下操作:

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

为此,我需要能够与我的 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(桥接网络 &host): 创建一座桥 nw

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"

与其创建自己的桥接网络,我也很累

--net host

我能够从主机连接到 sql 容器 - mysql workbench。 但是,golangapp 在尝试连接到容器内的 mysql 服务器时遇到连接被拒绝的错误。

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

我没有使用 docker 文件或 docker 撰写为:

使用配置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 我在配置中尝试过的组合:

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

这应该有效,请按照下列步骤操作:

  • 运行 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

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

你的主要收获应该是你的数据库连接字符串应该指向你主机的 private/public ip。如果你 运行 golang 没有容器链接。

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

试试这个然后告诉我。

多亏了以上回答,我才能够解决我的问题。

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

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

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

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

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

上图可能会帮助你更好地理解它。

Docker0: 带 IP 的 Docker0 接口。

现在,进入命令:

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

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

docker inspect -f '{{range .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 sub-netted 来自 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 桥接网络在容器之间进行通信。

供参考:

覆盖网络

用户定义的桥

默认桥接网络

希望以上内容对您有所帮助,如有不妥之处欢迎指正。

谢谢:)