无法从 docker 容器连接 mysql? [英] Unable to connect mysql from docker container?

查看:91
本文介绍了无法从 docker 容器连接 mysql?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个 docker-compose 文件,它有两个服务,分别是 GoMysql.它为 go 和 mysql 创建容器.现在我正在运行尝试连接到作为 docker 容器运行的 mysql 数据库的代码.但我得到了错误.

docker-compose.yml

版本:2"服务:应用程序:容器名称:golang重启:总是建造: .端口:- 49160:8800"链接:- mysql"依赖于取决于:- mysql"mysql:图片:mysql容器名称:mysql卷:- 数据库数据:/var/lib/mysql重启:总是环境:- MYSQL_ROOT_PASSWORD=root- MYSQL_DATABASE=testDB- MYSQL_USER=root- MYSQL_PASSWORD=root端口:- 3307:3306"卷:数据库数据:

连接mysql数据库时出错

golang |2019/02/28 11:33:05 拨号 tcp 127.0.0.1:3306:连接:连接被拒绝golang |2019/02/28 11:33:05 http: panic services 172.24.0.1:49066: dial tcp 127.0.0.1:3306: connect: connection deniedgolang |goroutine 19 [正在运行]:

连接MySql数据库

func DB() *gorm.DB {db, err := gorm.Open("mysql", "root:root@tcp(mysql:3306)/testDB?charset=utf8&parseTime=True&loc=Local")如果错误!= nil {log.Panic(错误)}log.Println("连接建立")返回数据库}

更新的 docker 文件

FROM golang:latestRUN go get -u github.com/gorilla/muxRUN go get -u github.com/jinzhu/gorm运行 go get -u github.com/go-sql-driver/mysql复制 ./wait-for-it.sh .运行 chmod +x/wait-for-it.sh工作目录/go/src/app添加 .源文件曝光 8800CMD ["go", "run", "src/main.go"]

我正在使用 gorm 包,它可以让我连接到数据库

解决方案

depends_on 并不是 MySQL 实际上准备好接收连接的验证.无论数据库容器是否准备好连接,它都会在数据库容器运行后启动第二个容器,这可能会导致您的应用程序出现此类问题,因为它期望数据库准备就绪,但可能并非如此.

引自文档:

<块引用>

depends_on 不会等待 db 和 redis 在启动 web 之前准备好" - 只有在它们启动之前.

有很多工具/脚本可以用来解决这个问题,比如wait-for 例如,如果您的图像基于 Alpine,哪个 sh 兼容(您可以使用 等待它 如果您的图像中有 bash)

您所要做的就是通过Dockerfile 将脚本添加到您的图像中,然后在docker-compose.yml 中使用此命令为您要制作的服务它等待数据库.

-- 之后是您通常用来启动应用程序的命令

版本:2"服务:应用程序:容器名称:golang...命令:["./wait-for", "mysql:3306", "--", "go", "run", "myapplication"]链接:- mysql"依赖于取决于:- mysql"mysql:图片:mysql...

<块引用>

为了更易于阅读,我从 docker-compose 中删除了一些部分.

用你的golang镜像的CMD修改这部分go run myapplication.

请参阅控制启动顺序,了解有关此问题的更多信息以及解决该问题的策略.<小时>解决连接问题后会出现的另一个问题如下:

使用 root 值设置 MYSQL_USER 将导致 MySQL 失败并显示以下错误消息:

ERROR 1396 (HY000) at line 1: Operation CREATE USER failed for 'root'@'%'

这是因为这个用户已经存在于数据库中,它试图创建另一个.如果您需要使用 root 用户本身,您可以仅使用此变量 MYSQL_ROOT_PASSWORD 或更改 MYSQL_USER 的值,以便您可以在应用程序中安全地使用它而不是 root 用户.

更新:如果找不到并且路径正确,您可能需要编写如下命令:

command: sh -c "./wait-for mysql:3306 -- go run myapplication"

I have created a docker-compose file it has two services with Go and Mysql. It creates container for go and mysql. Now i am running code which try to connect to mysql database which is running as a docker container. but i get error.

docker-compose.yml

version: "2"
services:
  app:
    container_name: golang
    restart: always
    build: .
    ports:
      - "49160:8800"
    links:
      - "mysql"
    depends_on:
      - "mysql" 

  mysql:
    image: mysql
    container_name: mysql
    volumes:
      - dbdata:/var/lib/mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=testDB
      - MYSQL_USER=root
      - MYSQL_PASSWORD=root
    ports:
      - "3307:3306"
volumes:
  dbdata:

Error while connecting to mysql database

golang   | 2019/02/28 11:33:05 dial tcp 127.0.0.1:3306: connect: connection refused
golang   | 2019/02/28 11:33:05 http: panic serving 172.24.0.1:49066: dial tcp 127.0.0.1:3306: connect: connection refused
golang   | goroutine 19 [running]:

Connection with MySql Database

func DB() *gorm.DB {
    db, err := gorm.Open("mysql", "root:root@tcp(mysql:3306)/testDB?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        log.Panic(err)
    }
    log.Println("Connection Established")
    return db
}

EDIT:Updated docker file

FROM golang:latest 
RUN go get -u github.com/gorilla/mux
RUN go get -u github.com/jinzhu/gorm
RUN go get -u github.com/go-sql-driver/mysql
COPY ./wait-for-it.sh .
RUN chmod +x /wait-for-it.sh
WORKDIR /go/src/app
ADD . src
EXPOSE 8800
CMD ["go", "run", "src/main.go"]

I am using gorm package which lets me connet to the database

解决方案

depends_on is not a verification that MySQL is actually ready to receive connections. It will start the second container once the database container is running regardless it was ready for connections or not which could lead to such an issue with your application as it expects the database to be ready which might not be true.

Quoted from the documentation:

depends_on does not wait for db and redis to be "ready" before starting web - only until they have been started.

There are many tools/scripts that can be used to solve this issue like wait-for which sh compatible in case your image based on Alpine for example (You can use wait-for-it if you have bash in your image)

All you have to do is to add the script to your image through Dockerfile then use this command in docker-compose.yml for the service that you want to make it wait for the database.

What comes after -- is the command that you would normally use to start your application

version: "2"
services:
  app:
    container_name: golang
    ...
        command: ["./wait-for", "mysql:3306", "--", "go", "run", "myapplication"]
    links:
      - "mysql"
    depends_on:
      - "mysql" 

  mysql:
    image: mysql
  ...

I have removed some parts from the docker-compose for easier readability.

Modify this part go run myapplication with the CMD of your golang image.

See Controlling startup order for more on this problem and strategies for solving it.


Another issue that will rise after you solve the connection issue will be as the following:

Setting MYSQL_USER with root value will cause a failure in MySQL with this error message:

ERROR 1396 (HY000) at line 1: Operation CREATE USER failed for 'root'@'%'

This is because this user already exist in the database and it tries to create another. if you need to use the root user itself you can use only this variable MYSQL_ROOT_PASSWORD or change the value of MYSQL_USER so you can securely use it in your application instead of the root user.

Update: In case you are getting not found and the path was correct, you might need to write the command as below:

command: sh -c "./wait-for mysql:3306 -- go run myapplication"

这篇关于无法从 docker 容器连接 mysql?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆