docker nodejs容器无法连接mysql容器
Posted
技术标签:
【中文标题】docker nodejs容器无法连接mysql容器【英文标题】:docker nodejs container cant connect mysql container 【发布时间】:2017-08-10 06:43:40 【问题描述】:我在 Digital Ocean 中运行 Docker 服务器。我有两个容器 Nodejs 和 mysql。 Mysql 容器开放了 3306 端口。
当尝试通过 Docker 服务器 ip + 端口通过 nodejs 访问 mysql 时。我收到错误:连接 ETIMEDOUT。
当我在本地计算机上运行相同的 nodejs docker setup 时,它工作正常。有什么我想念的吗?
这里是 nodejs docker-composer.yml:
version: '2'
services:
test-web-install:
image: example-nodejs:latest
working_dir: /home/app
volumes:
- ./:/home/app
command: sh -c 'nodemon'
environment:
- NODE_ENV=development
- DB_HOST=192.168.11.207 #or public ip in internet
- DB_PORT=3036
- DB_PASSWORD=root
- DB_USER=root
- DB_DATABASE=root
ports:
- "3000:3000"
这里是 mysql 的 docker-composer.yml
mysql:
container_name: flask_mysql
restart: always
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: 'root' # TODO: Change this
MYSQL_USER: 'root'
MYSQL_PASS: 'root'
MYSQL_DATABASE: 'root'
volumes:
- ./data:/var/lib/mysql
ports:
- "3036:3306"
restart: always
【问题讨论】:
您是否尝试在本地计算机上通过localhost:3306
访问mysql 容器?请提供更多信息 - docker files/docker-compose/outputs。到目前为止,我的建议是使用 docker-compose 并使用 docker-compose dns(即mysql:3306
)从桥接网络中连接到 mysql 容器,前提是您的设置可以允许 db 仅对您的 node.js 服务器可用。
我也想通过 Sequal Pro 等 Mac 客户端访问数据库。我添加了那些设置文件。感谢您的帮助。
你试过通过域名连接吗?首先需要检查是否有任何监听以及是否有防火墙:sudo netstat -tulpen
、sudo ufw status verbose
。如果不是这篇文章可能会有所帮助:digitalocean.com/community/tutorials/…
看起来和docker网络设置有关。一些容器 ip 是 128.0.0.1 而不是主机 ip。是否可以使用主机ip?
我还在 docker 中将它们添加到同一个网络中。即使是 Curl 操作也不起作用。
【参考方案1】:
docker 网络不允许您从容器内部返回到主机 IP 以连接到另一个容器公开的端口。我还没有深入研究这是否是由于 iptables 规则或者可能是 docker-proxy 内部的某些东西。无论哪种方式,它都不值得研究,因为容器到容器网络是 docker 的内置功能。
要使用 docker 的网络,容器需要位于同一个 docker 网络上,并且您可以通过它们在 DNS 中的容器名称来引用它们。使用 docker-compose,通常您可以使用服务名称代替容器名称(例如示例中的 test-web-install 和 mysql),因为 compose 会为这些创建别名。但是,由于您已经覆盖了 mysql 的容器名称,因此请改用您的 flask_mysql 容器名称。
在您的场景中,由于您已将启动与两个单独的 docker-compose.yml 文件分开,因此您将位于由 compose 创建的单独网络上。您有两种选择来解决此问题:
-
将两者合并成一个 docker-compose.yml (BlackStork gave an example of this)。
使用您预先创建的外部定义网络。
要执行后者,首先创建您的网络:
docker network create dbnet
然后更新您的 docker-compose.yml 以使应用看起来像:
version: '2'
networks:
dbnet:
external: true
services:
test-web-install:
image: example-nodejs:latest
working_dir: /home/app
volumes:
- ./:/home/app
command: sh -c 'nodemon'
environment:
- NODE_ENV=development
- DB_HOST=flask_mysql
- DB_PORT=3036
- DB_PASSWORD=root
- DB_USER=root
- DB_DATABASE=root
ports:
- "3000:3000"
networks:
- dbnet
还有用于 mysql 的 docker-compose.yml:
version: '2'
networks:
dbnet:
external: true
services:
mysql:
container_name: flask_mysql
restart: always
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: 'root' # TODO: Change this
MYSQL_USER: 'root'
MYSQL_PASS: 'root'
MYSQL_DATABASE: 'root'
volumes:
- ./data:/var/lib/mysql
ports:
- "3036:3306"
restart: always
networks:
- dbnet
【讨论】:
【参考方案2】:随着我们的进展,我会修改答案 - 跟随你的 cmets,虽然我无法访问你的环境,但让我们尝试逐步解决这个问题:
-
让我们让 db 对 node.js 服务器可见
看看它是如何工作的,然后可能会深入了解 env 网络配置。
正如我所见,有两种方法可以解决第一个问题,也可能是第二个问题,但无法触及您的环境:
第一种方法将确保服务器可以看到数据库,但是如果您无法从外部连接到数据库,似乎存在防火墙/droplet 网络配置问题,您可以尝试第二种方法(不太可能改变,但最好尝试)。这假设您使用相同的 docker compose 和相同的桥接客户网络:
version: '2'
services:
test-web-install:
image: example-nodejs:latest
working_dir: /home/app
volumes:
- ./:/home/app
command: sh -c 'nodemon'
environment:
- NODE_ENV=development
- DB_HOST= mysql
- DB_PORT=3036
- DB_PASSWORD=root
- DB_USER=root
- DB_DATABASE=root
ports:
- "3000:3000"
networks:
inner:
alias: server
mysql:
container_name: flask_mysql
restart: always
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: 'root' # TODO: Change this
MYSQL_USER: 'root'
MYSQL_PASS: 'root'
MYSQL_DATABASE: 'root'
volumes:
- ./data:/var/lib/mysql
ports:
- "<externalEnvIp>:3036:3306"
restart: always
networks:
inner:
alias: mysql
networks:
inner:
driver: bridge
driver_opts:
com.docker.network.enable_ipv6: "true"
com.docker.network.bridge.enable_ip_masquerade: "true"
ipam:
driver: default
config:
- subnet: 172.16.100.0/24
gateway: 172.16.100.1
选项 2:
version: '2'
services:
test-web-install:
image: example-nodejs:latest
working_dir: /home/app
volumes:
- ./:/home/app
command: sh -c 'nodemon'
environment:
- NODE_ENV=development
- DB_HOST= mysql
- DB_PORT=3036
- DB_PASSWORD=root
- DB_USER=root
- DB_DATABASE=root
ports:
- "3000:3000"
network_mode: "host"
mysql:
container_name: flask_mysql
restart: always
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: 'root' # TODO: Change this
MYSQL_USER: 'root'
MYSQL_PASS: 'root'
MYSQL_DATABASE: 'root'
volumes:
- ./data:/var/lib/mysql
ports:
- "3036:3306"
restart: always
network_mode: "host"
更精确的解决方案(找出问题的根源)将涉及深入挖掘您的 env 网络配置、docker 网络设置等,但这些解决方案可能会帮助并暂时解决您的问题。
请尝试后请输出结果。
【讨论】:
解决方案 1 是我们案例的最佳解决方案!谢谢。以上是关于docker nodejs容器无法连接mysql容器的主要内容,如果未能解决你的问题,请参考以下文章
将 NodeJS Docker 容器连接到 MySQL Docker 容器 - docker-compose 3