尝试通过 docker-compose 将 NodeJS 应用程序连接到 MySQL 映像时出现 ECONNREFUSED
Posted
技术标签:
【中文标题】尝试通过 docker-compose 将 NodeJS 应用程序连接到 MySQL 映像时出现 ECONNREFUSED【英文标题】:ECONNREFUSED when trying to connect NodeJS app to MySQL image via docker-compose 【发布时间】:2019-11-06 19:12:14 【问题描述】:我有一个项目使用 NodeJS 作为服务器(使用 ExpressJS)和 mysql 来处理数据库。要将它们一起加载,我使用的是 Docker。虽然这个项目包括一个 ReactJS 客户端(我有一个用于 react 的客户端文件夹和一个用于 nodejs 的服务器文件夹),但我已经测试了服务器和客户端之间的通信并且它可以工作。以下是与server
和mysql
服务相关的代码:
docker-compose.yml
mysql:
image: mysql:5.7
environment:
MYSQL_HOST: localhost
MYSQL_DATABASE: sampledb
MYSQL_USER: gfcf14
MYSQL_PASSWORD: xxxx
MYSQL_ROOT_PASSWORD: root
ports:
- 3307:3306
restart: unless-stopped
volumes:
- /var/lib/mysql
- ./db/greendream.sql:/docker-entrypoint-initdb.d/greendream.sql
.
.
.
server:
build: ./server
depends_on:
- mysql
expose:
- 8000
environment:
API_HOST: "http://localhost:3000/"
APP_SERVER_PORT: 8000
ports:
- 8000:8000
volumes:
- ./server:/app
links:
- mysql
command: yarn start
然后是服务器的Dockerfile
:
FROM node:10-alpine
RUN mkdir -p /app
WORKDIR /app
COPY package.json /app
COPY yarn.lock /app
RUN yarn install
COPY . /app
CMD ["yarn", "start"]
在服务器的package.json
中,脚本start
就是这样的:"start": "nodemon index.js"
被执行的文件index.js
是这样的:
const express = require('express');
const cors = require('cors');
const mysql = require('mysql');
const app = express();
const con = mysql.createConnection(
host: 'localhost',
user: 'gfcf14',
password: 'xxxx',
database: 'sampledb',
);
app.use(cors());
app.listen(8000, () =>
console.log('App server now listening on port 8000');
);
app.get('/test', (req, res) =>
con.connect(err =>
if (err)
res.send(err);
else
res.send(req.query);
)
);
所以我现在要做的就是确认连接发生了。如果可行,我会发回我从前端获得的参数,如下所示:
axios.get('http://localhost:8000/test',
params:
test: 'hi',
,
).then((response) =>
console.log(response.data);
);
所以,在我实现连接之前,我会在浏览器的控制台中获得 test: 'hi'
。我希望在连接成功后立即得到它,但我得到的是:
address: "127.0.0.1"
code: "ECONNREFUSED"
errno: "ECONNREFUSED"
fatal: true
port: 3306
syscall: "connect"
__proto__: Object
我以为我可能有错误的权限,但我也尝试使用root
作为用户和密码,但我得到了相同的结果。奇怪的是,如果我刷新页面,我不会得到ECONNREFUSED
,而是PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR
(带有fatal: false
)。如果我使用正确的凭据,为什么会发生这种情况?如果你发现了我可能错过的东西,请告诉我
【问题讨论】:
您好,可能是防火墙或网络问题? @jspcal 我在家里的 linux mint 和工作的 Windows 10 上执行此操作。我如何检查是否有某种阻塞?另外,如果两个镜像都应该在 docker-compose 创建的同一个内部网络上运行,真的有可能出现防火墙问题吗? 连接时使用端口 3307 node.js mysql error: ECONNREFUSED的可能重复 【参考方案1】:在您的 mysql.createConnection 方法中,您需要提供 mysql 主机。 mysql 主机不是 localhost,因为 mysql 有自己的容器和自己的 IP。实现这一点的最佳方法是将您的 mysql 主机外部化并允许 docker-compose 将 mysql 服务名称(在您的情况下是 mysql)解析为我们需要的内部 IP。基本上,你的 nodejs 服务器会连接到 mysql 容器的内部 IP。
将nodejs服务器中的mysql主机外化:
const con = mysql.createConnection(
host: process.env.MYSQL_HOST_IP,
...
);
在 docker-compose 的服务器服务中添加这个:
environment:
MYSQL_HOST_IP: mysql // the name of mysql service in your docker-compose, which will get resolved to the internal IP of the mysql container
【讨论】:
谢谢!它似乎第一次工作,但如果我刷新我得到code: "PROTOCOL_ENQUEUE_HANDSHAKE_TWICE", fatal: false
我怀疑 HANDSHAKE_TWICE
错误是由于每次调用 get
路由时连接造成的,所以我将其从 .get
中删除并放在外面,就在 .createConnection
下方。当我运行时,我得到一个PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR
(因为我添加了一个简单的 mysql 查询)。但奇怪的是,如果我在 server/index.js
中更改某些内容并刷新浏览器,它就可以工作
我将.createConnection
更改为.createPool
,它就像一个魅力。再次,非常感谢!
谢谢,非常感谢。我不知道在哪里可以搜索,你的答案真的解决了问题。我花了很多时间寻找答案。再次感谢您以上是关于尝试通过 docker-compose 将 NodeJS 应用程序连接到 MySQL 映像时出现 ECONNREFUSED的主要内容,如果未能解决你的问题,请参考以下文章
使用`docker-compose run`时无法调试,但`docker-compose up`有效
如何在 docker-compose 中定义 build-args?
将Traefik StripPrefix中间件添加到docker-compose标签结果为504
Nginx 从 docker-compose 运行返回“在上游找不到主机”