我有一个项目,该项目使用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
)。如果我使用正确的凭据,为什么会发生这种情况?如果您发现了我可能错过的东西,请告诉我
答案 0 :(得分:1)
在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