无法从 docker 容器连接 mysql? [英] Unable to connect mysql from docker container?
问题描述
我创建了一个 docker-compose 文件,它有两个服务,分别是 Go
和 Mysql
.它为 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 theCMD
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屋!