我有一个项目使用 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
)。如果我使用正确的凭据,为什么会发生这种情况?如果您发现了我可能遗漏的内容,请告诉我
最佳答案
在您的 mysql.createConnection 方法中,您需要提供 mysql 主机。 Mysql 主机不是本地主机,因为 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
关于mysql - 尝试通过 docker-compose 将 NodeJS 应用程序连接到 MySQL 图像时 ECONNREFUSED,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56745711/