首頁  >  問答  >  主體

Node.js 連接到 MySQL Docker 容器 ECONNREFUSED

在將此問題標記為重複之前,請注意我確實閱讀了其他答案,但它並沒有解決我的問題。

我有一個包含兩個服務的 Docker compose 檔案:

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" ]

docker-compose up --build 之後,服務啟動,但「wait-for-it.sh」腳本在等待mySQL 啟動時逾時(所以在測試DB 時暫時不使用它)連接,我只是等到控制台顯示MySQL 已準備好接受傳入連接)

當 MySQL 從主機執行時,我可以使用 Sequel Pro 登入並查詢資料庫並從 ./mysql/migrations 取得範例記錄


#

我還可以透過 SSH 進入正在運行的 MySQL 容器並執行相同的操作。

但是,我的 Node.js 應用程式在連接時產生 ECONNREFUSED 127.0.0.1:3307

MySQL 初始化:

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 查詢:

import { db } from '../db/client'

export let get = () => {

return db.query('SELECT * FROM users', [])
    .then((results) => {
        return results

    })
    .catch((e) => {
        return Promise.reject(e)
    })
}

點擊 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
    });
});

這不太可能是競爭條件,因為在 Node.js 失敗的同時,我可以使用 Sequel Pro 或 SSH 查詢正在執行的 Docker 容器並進行查詢。那麼這可能是 Node.js 無法存取 MySQL 容器的情況?

{
    error: connect ECONNREFUSED 127.0.0.1:3307
    code: 'ECONNREFUSED',
    errno: 'ECONNREFUSED',
    syscall: 'connect',
    address: '127.0.0.1',
    port: 3307,
    fatal: true
}


#
P粉296080076P粉296080076271 天前601

全部回覆(1)我來回復

  • P粉399090746

    P粉3990907462024-01-22 12:20:58

    這個:

    mysql:
        image: mysql:5.7
        environment:
        ...
        ports:
          - "3307:3306"

    表示Docker會將主機的3307連接埠對應到容器的3306連接埠。因此您可以從 Sequel 存取 localhost:3307。

    但是,這並不表示容器正在監聽3307;事實上容器仍在監聽 3306。當其他容器嘗試存取 mysql DNS 時,它會轉換為內部容器 IP,因此您必須連接到 3306

    所以你的節點配置應該如下:

    const config = {
        host: 'mysql',
        database: 'mydb',
        port: '3306',
        user: 'mysql',
        password: '1234',
        connectionLimit: 10
    }

    這在你的 docker-compose.yml 中:

    command: ["./wait-for-it.sh", "mysql:3306"]

    注意:wait-for-it.sh 腳本來自: https://github.com/vishnubob/wait-for-it

    回覆
    0
  • 取消回覆