我有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
答案 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
文件中的端口。
如果您的应用程序总是要驻留在一个容器中,而您的数据库总是要驻留在一个容器中,那么Docker提供了一种方法,您可以将它们彼此连接。
可以从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")
这对我有用