【问题标题】:Connect a containerized Node.js application to a MySQL server将容器化的 Node.js 应用程序连接到 MySQL 服务器
【发布时间】:2021-05-13 08:59:09
【问题描述】:

我目前在 Raspberry Pi 3 上运行 Ubuntu 20.10。我已经安装了 Docker 和 MySQL 服务器,它在 Ubuntu 上作为服务运行。两种安装都正常工作。现在我正在尝试运行这个 Node.js API:

'use strict';

const express = require('express');
const mysql = require('mysql');

const PORT = 8080;
const HOST = '0.0.0.0';

const app = express();
app.get('/', (req, res) => {
  res.send('Hello World');
});

app.get('/persons', (req, res) => {
  connection.query('SELECT * FROM persons', (err, result) => {
    if (err) res.send(`Some error occured: ${err}`);
    res.send(result);
  });
});

app.listen(PORT, HOST);
console.log(`Runnning API on http://${HOST}:${PORT}`);

const connection = mysql.createConnection({
  host: 'localhost',
  user: myuser,
  password: 'mypwd,
  database: mydb
});

connection.connect(err => {
  if (err) throw err;
  console.log('Successfully connected to MySQL');
});

在我将此应用程序包装到 Docker 容器中之前,这非常有效。 Dockerfile 如下所示:

FROM node:14

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 8080
CMD [ "node", "server.js"]

然后我得到这个错误:

if (err) throw err;
           ^

Error: connect ECONNREFUSED 127.0.0.1:3306
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1135:16)
    --------------------
    at Protocol._enqueue (/home/felix/workspaces/node-api/node_modules/mysql/lib/protocol/Protocol.js:144:48)
    at Protocol.handshake (/home/felix/workspaces/node-api/node_modules/mysql/lib/protocol/Protocol.js:51:23)
    at Connection.connect (/home/felix/workspaces/node-api/node_modules/mysql/lib/Connection.js:116:18)
    at Object.<anonymous> (/home/felix/workspaces/node-api/server.js:31:12)
    at Module._compile (internal/modules/cjs/loader.js:1138:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
    at Module.load (internal/modules/cjs/loader.js:986:32)
    at Function.Module._load (internal/modules/cjs/loader.js:879:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47 {
  errno: 'ECONNREFUSED',
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 3306,
  fatal: true
}

有谁知道如何解决这个问题? 此外,我想知道在 Linux 上将 MySQL 作为服务运行或在容器中运行它有什么区别……优点/缺点是什么?或者有人可以解释在两个不同的容器中运行应用程序和数据库并使用 Docker compose 连接它们是否有意义?

【问题讨论】:

  • 错误消息有一个不同的端口3306 而不是8080 为什么会这样?你可以通过运行sudo ss -tnlp | grep 8080来检查docker容器是否使用端口8080

标签: mysql node.js docker


【解决方案1】:
<...>
const connection = mysql.createConnection({
      host: 'localhost',
<...>

localhost 部分不正确。在容器中,localhost 指的是在该容器中运行的服务,而 MySQL 不存在。它在您的 Ubuntu 主机中,这就是主机应该指的内容。如果你想走这条路:


以上并不是使用 docker 做事的标准方式。除非您有充分的理由在主机上运行 MySQL,否则只需将其放在容器中并使用 docker-compose 运行容器对(或更多,如果需要)。要回答有关此设置的问题:

谁能解释在两个不同的容器中运行应用程序和数据库并使用 Docker compose 连接它们是否有意义?

是的,这是标准的做法。您可以通过各种方式(链接、depends_on)链接 docker-compose 中的容器,但也会有一个default/implicitly created network for services in docker-compose。然后,您可以仅通过服务名称来引用数据库容器,例如可能是db,或者你怎么称呼它。您通常将该名称作为环境变量或 .env 的一部分传递给 Node 应用程序。

我想知道在 Linux 上将 MySQL 作为服务运行或在容器中运行它有什么区别……优点/缺点是什么?

这取决于你追求什么。两种情况都有。但是对于一个基本情况,只需为一个节点应用程序提供一个数据库,docker-compose 路由和容器中的数据库是可行的,因为:

  • 通过 docker-compose 可以轻松管理(启动/停止/更新/配置)容器
  • 容器中的东西更便于携带
  • 服务是独立的。没有一个影响另一个的风险,依此类推
  • 它们(可以说)更安全,因为它们只在一个容器中拥有一个东西和一个东西,而不是一堆东西在你的数据库旁边运行。还可以将数据库放在 NAT 后面,以及容器的其他细节

容器的好处清单还在继续。大多数好处都有另一面,但对于小型应用程序,容器中的 MySQL 可能恰到好处且简单。确保您manage persistence(MySQL 存储数据的位置)。这通常通过volumes 完成。

【讨论】:

    【解决方案2】:

    如果我理解正确,您要做的是将容器中的应用程序与您安装在主机中的 mysqld 连接起来?

    Firstable:为什么不把一个 mysql 实例放到另一个容器中呢? 第二:127.0.0.1是容器本身的环回地址,与你安装mysql服务器的主机无关...

    我认为你应该尝试使用 mysql 容器,但如果你出于某种原因需要它,你可以看看这篇文章:https://medium.com/@sirajul.anik/docker-for-linux-localhost-docker-connect-to-host-machine-from-a-docker-container-in-linux-fa42b00f161e

    【讨论】:

      猜你喜欢
      • 2020-06-08
      • 2017-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多