Node.js 连接到 MySQL Docker 容器 ECONNREFUSED
在您将此问题标记为重复之前,请注意我确实阅读了其他答案,但并没有解决我的问题.
我有一个包含两个服务的 Docker 组合文件:
版本:3"服务:mysql:图像:mysql:5.7环境:MYSQL_HOST:本地主机MYSQL_DATABASE:mydbMYSQL_USER: mysqlMYSQL_PASSWORD:1234MYSQL_ROOT_PASSWORD:root端口:- 3307:3306"暴露:- 3307卷:-/var/lib/mysql- ./mysql/migrations:/docker-entrypoint-initdb.d重新启动:除非停止网络:建造:语境: .dockerfile: 网络/Dockerfile卷:- ./:/web端口:- 3000:3000"环境:NODE_ENV:开发端口:3000链接:- mysql:mysql依赖于取决于:- mysql暴露:- 3000命令:["./wait-for-it.sh", "mysql:3307"]
/web/Dockerfile:
来自节点:6.11.1运行 mkdir -p/usr/src/app工作目录/usr/src/app复制 package.json/usr/src/app/运行 npm 安装复制 ./usr/src/应用程序CMD [ "npm", "start" ]
在 docker-compose up --build
服务启动后,但是
我也可以通过 SSH 连接到正在运行的 MySQL 容器并执行相同的操作.
但是,我的 Node.js 应用程序在连接时产生 ECONNREFUSED 127.0.0.1:3307
MySQL 初始化:
import * as mysql from 'promise-mysql'常量配置 = {主机:'本地主机',数据库:'mydb',端口:'3307',用户:'mysql',密码:'1234',连接限制:10}导出让 db = mysql.createPool(config);
MySQL 查询:
import { db } from '../db/client'export let get = () =>{return db.query('SELECT * FROM users', []).then((结果) => {返回结果}).catch((e) => {返回 Promise.reject(e)})}
点击 url 时调用的路由/
import { Router } from 'express';从../repository"导入 * 作为存储库export let router = Router();router.get('/', async (req, res) => {让用户;尝试{users = await repository.users.get();}赶上(e){//ECONNREFUSED 127.0.0.1:3307}res.render('索引', {用户:用户});});
这不太可能是竞争条件,因为在 Node.js 失败的同时,我可以使用 Sequel Pro 或 SSH 查询正在运行的 Docker 容器并进行查询.所以可能是Node.js无法访问MySQL容器的情况?
<代码>{错误:连接 ECONNREFUSED 127.0.0.1:3307代码:'ECONNREFUSED',errno: 'ECONNREFUSED',系统调用:'连接',地址:'127.0.0.1',端口:3307,致命的:真的}解决方案
这个:
mysql:图像:mysql:5.7环境:...端口:- 3307:3306"
表示Docker会将宿主机的3307
端口映射到容器的3306
端口.所以你可以从 Sequel 访问 localhost:3307
.
然而,这并不意味着容器正在监听3307
;容器实际上仍在监听 3306
.当其他容器尝试访问 mysql
DNS 时,它会被转换为内部容器 IP,因此您必须连接到 3306
.
所以你的节点配置应该是这样的:
const 配置 = {主机:'mysql',数据库:'mydb',端口:'3306',用户:'mysql',密码:'1234',连接限制:10}
这在你的 docker-compose.yml 中:
command: ["./wait-for-it.sh", "mysql:3306"]
Before you flag this question as a duplicate, please note that I did read other answers, but it didn't solve my problem.
I have a Docker compose file consisting of two services:
version: "3"
services:
mysql:
image: mysql:5.7
environment:
MYSQL_HOST: localhost
MYSQL_DATABASE: mydb
MYSQL_USER: mysql
MYSQL_PASSWORD: 1234
MYSQL_ROOT_PASSWORD: root
ports:
- "3307:3306"
expose:
- 3307
volumes:
- /var/lib/mysql
- ./mysql/migrations:/docker-entrypoint-initdb.d
restart: unless-stopped
web:
build:
context: .
dockerfile: web/Dockerfile
volumes:
- ./:/web
ports:
- "3000:3000"
environment:
NODE_ENV: development
PORT: 3000
links:
- mysql:mysql
depends_on:
- mysql
expose:
- 3000
command: ["./wait-for-it.sh", "mysql:3307"]
/web/Dockerfile:
FROM node:6.11.1
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install
COPY . /usr/src/app
CMD [ "npm", "start" ]
After docker-compose up --build
the services start up, however the "wait-for-it.sh" script times out when waiting for mySQL to start (so temporarily I am not using it when testing for DB connectivity, I just wait until the console shows that MySQL is ready for accepting incoming connections)
When MySQL is running from the host machine I can login using Sequel Pro and query the DB and get the sample records from ./mysql/migrations
I can also SSH into the running MySQL container and do the same.
However, my Node.js app yields ECONNREFUSED 127.0.0.1:3307
when connecting
MySQL init:
import * as mysql from 'promise-mysql'
const config = {
host: 'localhost',
database: 'mydb',
port: '3307',
user: 'mysql',
password: '1234',
connectionLimit: 10
}
export let db = mysql.createPool(config);
MySQL query:
import { db } from '../db/client'
export let get = () => {
return db.query('SELECT * FROM users', [])
.then((results) => {
return results
})
.catch((e) => {
return Promise.reject(e)
})
}
Route invoked when hitting url /
import { Router } from 'express';
import * as repository from '../repository'
export let router = Router();
router.get('/', async (req, res) => {
let users;
try{
users = await repository.users.get();
} catch(e){
// ECONNREFUSED 127.0.0.1:3307
}
res.render('index', {
users: users
});
});
It's unlikely to be a race condition because at the same time when Node.js fails I can query using Sequel Pro or SSH into the running Docker container and query. So it's probably a case of Node.js not being able to access to MySQL container?
{
error: connect ECONNREFUSED 127.0.0.1:3307
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 3307,
fatal: true
}
解决方案
This:
mysql:
image: mysql:5.7
environment:
...
ports:
- "3307:3306"
Means that Docker will map the 3307
port of the host to the 3306
port of the container. So you can access from Sequel to localhost:3307
.
However, it does not mean that the container is listenting to 3307
; the container is in fact still listening to 3306
. When others containers tries to access the mysql
DNS, it gets translated to the internal container IP, therefore you must connect to 3306
.
So your node config should look like:
const config = {
host: 'mysql',
database: 'mydb',
port: '3306',
user: 'mysql',
password: '1234',
connectionLimit: 10
}
And this in your docker-compose.yml:
command: ["./wait-for-it.sh", "mysql:3306"]
相关文章