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

时间:2019-10-29 19:18:50

标签: mysql macos docker go

我有2个容器:1个带有简单的golang程序,1个带有mysql。 我可以启动Bothm,但是golang无法连接到mysql。我收到连接被拒绝的消息。

如果我尝试在mysql容器中执行bash并尝试与mysql -u root -p在本地连接,则一切正常。 如果在主机上,我尝试使用mysql -h 0.0.0.0 -P 10000 -u root -p连接到容器,则一切正常。

我在MYSQL_ROOT_HOST: '%'中添加了docker-compose,并在bind-address = 0.0.0.0中添加了mysqld.cnf,但仍然无法正常工作。

我做错了什么?

docker-compose

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

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

0.0.0.0不是您的容器的IP地址。这是一个特殊的地址,表示“所有可用接口”。

您正在使用0.0.0.0从主机连接到容器,因为它们确实共享了一个接口,因为您公开了docker-compose.yml文件中的端口。

如果您的应用程序总是要驻留在一个容器中,而您的数据库总是要驻留在一个容器中,那么Doc​​ker提供了一种方法,您可以将它们彼此连接。

可以从db_private(或golang)容器中找到服务名称

web

这将始终有效,因为Docker拥有一个内部DNS服务器,无论您的容器具有哪个IP地址,您的容器都可以使用它。

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

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

答案 2 :(得分:0)

在我的情况下,我改用db_private的Docker主机,通过运行获取本地IP:

ipconfig getifaddr en0 => 172.16.4.227

然后我在gorm SQL连接中使用此IP:

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

这对我有用