无法从docker容器连接mysql?

Tec*_*ain 7 database-connection docker docker-compose

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

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:
Run Code Online (Sandbox Code Playgroud)

连接到mysql数据库时出错

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]:
Run Code Online (Sandbox Code Playgroud)

与MySql数据库的连接

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
}
Run Code Online (Sandbox Code Playgroud)

编辑:更新的docker文件

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"]
Run Code Online (Sandbox Code Playgroud)

我正在使用gorm程序包,该程序包使我可以连接到数据库

Mos*_*ein 7

depends_on不能证明MySQL实际上已经准备好接收连接。无论数据库容器是否准备好进行连接,无论数据库容器是否正在运行,它都会启动第二个容器,这可能会导致应用程序出现此问题,因为它期望数据库已准备就绪,但可能不正确。

文档中引用:

Depends_on在启动Web之前不会等待db和Redis处于“就绪”状态-仅在它们启动之前。

有迹象表明,可以用来解决这个问题,就像很多工具/脚本等待了sh在兼容的情况下,根据你的形象Alpine,例如(您可以使用等待换它,如果你在你的图像具有的bash)

您所要做的就是将脚本添加到映像中,Dockerfile然后对该命令使用此命令docker-compose.yml来使您的服务等待数据库。

接下来是--通常用于启动应用程序的命令

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

  mysql:
    image: mysql
  ...
Run Code Online (Sandbox Code Playgroud)

为了方便阅读,我从docker-compose中删除了一些部分。

go run myapplication使用CMDgolang图片的修改此部分。

有关此问题的更多信息和解决方法,请参阅控制启动顺序


解决连接问题后将出现的另一个问题如下:

MYSQL_USER使用rootvalue 设置将导致MySQL错误,并显示以下错误消息:

ERROR 1396 (HY000) at line 1: Operation CREATE USER failed for 'root'@'%'
Run Code Online (Sandbox Code Playgroud)

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

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

command: sh -c "./wait-for mysql:3306 -- go run myapplication"
Run Code Online (Sandbox Code Playgroud)


小智 0

首先,如果您使用的是最新版本的 docker compose,则应用程序服务中不需要链接参数。我引用了 docker compose 文档Warning: The --link flag is a legacy feature of Docker. It may eventually be removed. Unless you absolutely need to continue using it, https://docs.docker.com/compose/compose-file/#links

我认为解决方案是使用networks。这将创建一个 docker 网络并向其中添加每个服务。

尝试这个

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

  mysql:
    image: mysql
    container_name: mysql
    volumes:
      - dbdata:/var/lib/mysql
    restart: always
    networks:
     - my_network
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=testDB
      - MYSQL_USER=root
      - MYSQL_PASSWORD=root
    ports:
      - "3307:3306"
volumes:
  dbdata:
networks:
  my_network:
    driver: bridge
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果您只从应用程序服务连接到 Mysql,则不需要公开 mysql 端口。如果容器在同一网络中运行,它们可以到达该网络内的所有端口。

如果我的示例不起作用,请尝试运行 docker compose,然后使用 docker container exec -it CONTAINER_NAME bash Install进入应用程序容器ping以测试连接,然后运行 ​​ping mysql。