无法从Docker容器连接到MySQL?
无法从Docker容器连接到MySQL?
我创建了一个docker-compose文件,其中包含两个服务:一个是使用Go的服务,另一个是使用Mysql的服务。它会为Go和Mysql创建容器。现在我正在运行代码,尝试连接到作为docker容器运行的mysql数据库,但是我遇到了错误。
docker-compose.yml
版本: "2"
服务:
app:
容器名称:golang
重启:始终
构建:。
端口:
- "49160:8800"
链接:
- "mysql"
依赖:
- "mysql"
mysql:
镜像:mysql
容器名称:mysql
卷:
- dbdata:/var/lib/mysql
重启:始终
环境:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=testDB
- MYSQL_USER=root
- MYSQL_PASSWORD=root
端口:
- "3307:3306"
卷:
dbdata:
连接到Mysql数据库的错误
golang | 2019/02/28 11:33:05 dial tcp 127.0.0.1:3306:连接被拒绝
golang | 2019/02/28 11:33:05 http:在172.24.0.1:49066上服务发生崩溃:dial tcp 127.0.0.1:3306:连接被拒绝
golang | goroutine 19 [running]:
与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("连接已建立")
return db
}
编辑:更新的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"]
我使用了gorm包,它让我能够连接到数据库。
无法从Docker容器中连接到MySQL的原因是Docker的最新版本中不再需要使用link参数。解决方法是使用networks参数创建一个Docker网络,并将每个服务添加到其中。以下是一个示例的docker-compose.yml文件:
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
另外,如果只从app服务连接到MySQL,不需要暴露MySQL的端口。如果容器在同一个网络中运行,它们可以访问该网络中的所有端口。
如果以上示例无法解决问题,可以尝试以下步骤:
1. 运行docker-compose命令,并使用`docker container exec -it CONTAINER_NAME bash`进入app容器。
2. 在app容器中安装ping工具,然后运行`ping mysql`来测试连接。
3. 检查连接字符串是否为`root:root(mysql:3306)/testDB?charset=utf8&parseTime=True&loc=Local`。
以上是解决无法从Docker容器中连接到MySQL的方法。这个问题可能是由于Docker启动顺序引起的。
无法从Docker容器中连接到MySQL的问题出现的原因是depends_on
指令不能保证MySQL已经准备好接收连接。它只是在数据库容器运行后启动第二个容器,而不管数据库是否已准备好接收连接,这可能导致应用程序出现问题,因为它期望数据库已经准备好,但实际上可能并不是这样。
解决这个问题的方法有很多,比如使用wait-for工具/脚本,该工具与Alpine
镜像兼容(如果你的镜像基于Alpine
,你可以使用wait-for-it)。
你只需要通过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
...
修改go run myapplication
部分为你的Golang镜像的CMD
。
解决连接问题后可能会出现另一个问题:
使用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"
请告诉我确切的代码,以便解决这个问题。
你已经将脚本添加到镜像并使其可执行了吗?
我还没有将脚本添加到镜像中。请告诉我如何将脚本添加到镜像中?虽然我已经在Dockerfile中写了COPY wait-for-it.sh /wait-for-it.sh
。
请将你更新后的Dockerfile发布到问题中,这样我可以检查一下。如果你已经使用了COPY
,那就意味着脚本已经在镜像中,并且需要将其设置为可执行。
请检查我更新后的问题。我已经添加了Dockerfile。
实际上,无论日志中出现的错误的IP地址是否正确,mysql容器都不会正常工作,所以请仔细阅读我问题的第二部分,该部分与MYSQL_USER
变量的使用相关。
让我知道它是如何工作的,因为找不到wait_for_it。
你需要通过启动一个新容器进入容器内部,然后尝试手动执行脚本,以检查脚本是否在容器内部,或者你需要修复权限等问题,以便按照你的期望找到脚本。