无法从Golang容器连接到MySQL容器

ie3xauqp  于 2023-04-03  发布在  Go
关注(0)|答案(5)|浏览(135)

我有两个容器:一个简单的golang程序和mysql.我可以启动两者,但golang应用程序无法连接到mysql.我收到连接拒绝.
如果我将docker exec放入mysql容器,并尝试使用mysql -u root -p进行本地连接,则一切正常。
如果在主机上,我尝试连接到mysql -h 0.0.0.0 -P 10000 -u root -p的容器,一切正常。
我在docker-compose中添加了MYSQL_ROOT_HOST: '%',在mysqld.cnf中添加了bind-address = 0.0.0.0,但仍然不工作。
我做错了什么?

对接合成

version: '3'
    services:
      web:
        build:
          context: .
          dockerfile: docker/web/Dockerfile
        ports:
          - "8081:8081" # http
          - "443:443" # https
        links:
          - db_private
        volumes:
         - ../../../../.:/go
      db_private:
        image: mysql:5.7
        restart: always
        environment:
          MYSQL_DATABASE: ${MYSQL_DATABASE}
          MYSQL_USER: ${MYSQL_USER}
          MYSQL_PASSWORD: ${MYSQL_PASSWORD}
          MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
          MYSQL_ROOT_HOST: '%'
        ports:
          - '10000:3306'
        expose:
          - '3306'
        volumes:
          - ./mysql-entry-point.sql:/docker-entrypoint-initdb.d
          - private-db:/var/lib/mysql
          - ./mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
    # Names our volume
    volumes:
      private-db:

Web容器Dockerfile

FROM golang:alpine
    RUN mkdir /app
    ADD . /app/
    
    WORKDIR /app
    
    RUN apk update && apk upgrade && apk add --no-cache bash git openssh
    
    RUN go get github.com/jinzhu/gorm
    RUN go get github.com/jinzhu/gorm/dialects/mysql
    RUN go get github.com/gin-gonic/gin
    RUN go get github.com/gin-contrib/cors
    
    
    RUN go build -o main .
    RUN adduser -S -D -H -h /app appuser
    USER appuser
    CMD ["./main"]

Golang文件

package main
    
    import (
        "fmt"
        "github.com/gin-gonic/gin"
        "github.com/jinzhu/gorm"
        _ "github.com/jinzhu/gorm/dialects/mysql"
        "net/http"
        "time"
    )
    
    var db *gorm.DB
    
    type (
        FooModel struct {
            Id        int64 `gorm:"primary_key"`
            name      string
        }
    )
    
    func init() {
        //open a db connection
        var err error
        db, err = gorm.Open("mysql", "user:pwd@(0.0.0.0:10000)/myDB?charset=utf8&parseTime=true")
        if err != nil {
            fmt.Println(err)
            panic("failed to connect database")
        }
        //Migrate the schema
        db.AutoMigrate(&FooModel{})
    
        db.LogMode(true)
    }
    
    // main inits routes
    func main() {
    
        router := gin.Default()
    
        router.GET("/getExample", getExample)
        
        router.Run("0.0.0.0:8081")
    }
    
    
    func getExample(c *gin.Context) {
    
        c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "bye"})
    }

我用这个复制容器中的mysqld.cnf

[mysqld]
    pid-file    = /var/run/mysqld/mysqld.pid
    socket      = /var/run/mysqld/mysqld.sock
    datadir     = /var/lib/mysql
    #log-error  = /var/log/mysql/error.log
    # By default we only accept connections from localhost
    #bind-address   = 127.0.0.1
    bind-address   = 0.0.0.0
    # Disabling symbolic-links is recommended to prevent assorted security risks
    symbolic-links=0
lx0bsm1f

lx0bsm1f1#

您的Web应用正在容器中运行,这意味着地址0.0.0.0是容器本身,而不是运行它的主机。请尝试使用db_private名称而不是地址0.0.0.0连接数据库。

kmynzznz

kmynzznz2#

0.0.0.0不是容器的IP地址。它是一个特殊地址,表示“所有可用接口”。
您使用0.0.0.0从主机连接到容器,因为它们共享一个接口,因为您在docker-compose.yml文件中公开了端口。
如果你的应用程序总是在一个容器中,而你的数据库总是在一个容器中,Docker提供了一个方法来连接一个到另一个。
服务名db_private可以在web(或golang)容器中找到。
这将始终有效,因为Docker有一个内部DNS服务器,您的容器可以使用它,无论您的容器使用哪个IP地址。

host> docker-compose up -d
host> docker-compose exec web /bin/sh
 web$ ping db_private

是的,你总是想使用0.0.0.0作为容器内的绑定接口,因为你永远不知道你会得到哪个IP地址,所以这就像一个快捷方式说“全部”。

57hvy0tb

57hvy0tb3#

在我的例子中,而是使用Docker主机的db_private,我通过运行以下命令来获取本地IP:
=〉172.16.4.227
然后我在我的gorm SQL连接中使用这个IP:

db, err = gorm.Open("mysql", "user:pwd@(172.16.4.227:10000)/myDB?charset=utf8&parseTime=true")

这对我很有效

3df52oht

3df52oht4#

你可以在just 3 steps中简单地解决这个问题:
1.在docker-compose文件中将ports10000:3306更改为3306:3306
1.在Golang file中将0.0.0.0:10000更改为db_private:3306
1.不需要清理容器和镜像,运行以下命令:

docker-compose up --build
9rygscc1

9rygscc15#

这可能对某人有帮助!我有同样的问题,花了5个小时来解决这个问题。在我的情况下,我使用的是“sqlc”的golang,也想通过组合文件传递连接字符串。

但是当我试图通过 Postman 调用API时,我得到了像访问被拒绝到'root'@'x.x.x.x'这样的错误。长话短说,我从DB_SOURCE中删除了双引号,它工作了!

- DB_SOURCE=root:my-secret-pw@tcp(mysql:3306)/simple_bank?parseTime=true&autocommit=true

相关问题