mysql - 尝试通过 docker-compose 将 NodeJS 应用程序连接到 MySQL 图像时 ECONNREFUSED

标签 mysql node.js docker express docker-compose

我有一个项目使用 NodeJS 作为服务器(使用 ExpressJS)和 MySQL 来处理数据库。为了将它们一起加载,我使用的是 Docker。虽然这个项目包括一个 ReactJS 客户端(我有一个用于 react 的客户端文件夹和一个用于 nodejs 的服务器文件夹),但我已经测试了服务器和客户端之间的通信并且它有效。以下是与 servermysql 服务相关的代码:

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/

相关文章:

mysql - SQL 和 2 复杂连接

mysql - 未找到列 : 1054 Unknown column 'managers.id' in 'on clause' in Laravel 5 Many-to-Many relationship query

SQL 整个表更新,根据第一个表字段从另一个表中进行选择

javascript - 在 Node.js 流中全程实现背压

javascript - 如何将 LiveReload 与 AngularJS 模板 URL 一起使用

docker - 如何获取schedule:run以在docker容器中与systemd一起使用?

ruby-on-rails - Sidekiq 为 redis 使用不正确的 url

sql - mysql查询,两个select

docker - 这个 Dockerfile 是如何在没有入口点或 cmd 的情况下实际运行 logstash 的?

node.js - 当所需文件不导出任何内容时,require() 会做什么?设置 Mongoose + express 的正确方法是什么?