Docker NodeJS 容器无法连接 MySQL 容器



我在Digital Ocean中运行Docker服务器。我有两个容器Nodejs和Mysql。Mysql 容器已打开端口到 3306。

当尝试通过 Docker Server ip + port 通过 nodejs 访问 mysql 时。我收到错误:连接 ETIMEDOUT。

当我在本地计算机中运行相同的 nodejs docker 设置时,它工作正常。我错过了什么吗?

这是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"

这是 docker-composer.yml for mysql

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

随着我们的前进,我将修改答案 - 根据您的评论,虽然我无法访问您的环境,但让我们尝试逐步解决此问题:

  1. 让我们使数据库对节点.js服务器可见
  2. 看看它是如何工作的,然后可能深入研究环境网络配置。

有 2 种方法可以解决第一个问题,也可能是第二个问题,正如我所看到的,无法触摸您的环境:

第一个将确保服务器看到数据库,但是如果您无法从外部连接到数据库,则似乎存在防火墙/droplet网络配置问题,您可以尝试第二种方式(不太可能更改,但最好尝试)。这假设您使用相同的 docker 组合和相同的网桥客户网络:

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"

更精确的解决方案(找到问题的根源)将涉及深入研究您的环境网络配置、docker 网络设置等,但这些解决方案现在可能有助于解决您的问题。

尝试后请输出结果。

docker 网络不允许你从一个容器内部返回到主机 IP 以连接到另一个容器公开的端口。我还没有深入研究这一点,看看这是由于 iptables 规则还是 docker 代理内部的某些东西。无论哪种方式,都不值得研究,因为容器到容器网络是 docker 的内置功能。

要使用 docker 的网络,容器需要位于同一 docker 网络上,并且您可以通过其在 DNS 中的容器名称引用它们。使用 docker-compose,通常您可以使用服务名称代替容器名称(例如示例中的 test-web-install 和 mysql),因为 compose 会为这些名称创建别名。但是,由于您已经覆盖了 mysql 的容器名称,因此请改用您的flask_mysql容器名称。

在你的方案中,由于你已使用两个单独的 docker-compose.yml 文件拆分了启动,因此你将位于由 compose 创建的单独网络上。您有两种方法可以解决此问题:

  1. 将两者合并为一个 docker-compose.yml(BlackStork 举了一个例子)。
  2. 使用预先创建的外部定义的网络。

要执行后者,请首先创建您的网络:

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

最新更新