Node.jsとmysqlをdocker composeした時にECONNREFUSEDする

エラー文

node:events:371
       throw er; // Unhandled 'error' event
       ^
 Error: connect ECONNREFUSED 172.29.0.2:3306
     at TCPConnectWrap.afterConnect as oncomplete
 Emitted 'error' event on Connection instance at:
     at Connection._notifyError (/app/node_modules/mysql2/lib/connection.js:225:12)
     at Connection._handleFatalError (/app/node_modules/mysql2/lib/connection.js:156:10)
     at Connection._handleNetworkError (/app/node_modules/mysql2/lib/connection.js:169:10)
     at Socket.emit (node:events:394:28)
     at emitErrorNT (node:internal/streams/destroy:157:8)
     at emitErrorCloseNT (node:internal/streams/destroy:122:3)
     at processTicksAndRejections (node:internal/process/task_queues:83:21) {
   errno: -111,
   code: 'ECONNREFUSED',
   syscall: 'connect',
   address: '172.29.0.2',
   port: 3306,
   fatal: true
 }

原因1

データーベース接続先のホスト名がアドレスになっている。

修正前

const connection = mysql.createConnection({
    host: 'localhost:3306',
    user: 'root',
    password: "root",
    database: 'project',
});

修正後

const connection = mysql.createConnection({
    host: '[コンテナ名]',
    user: 'root',
    password: "root",
    database: 'project',
});

コンテナ名は、docker psとコマンドを実行した時にNAMESの行でも確認できる。

原因2

mysqlのデーターベースが起動完了する前にアクセスが発生している

docker-composeのバージョンが2.1以上の場合はhealthcheckを使うことでこの問題を解決できる。

services.db(mysqlのコンテナ)にhealthcheckを追加し、services.back(mysqlに依存している環境)にdepends_onを追加する。

–password==にはmysqlのパスワードを指定すること。.envファイルにパスワードを記載した環境変数を用意しておくのがおすすめ。

services:
  back:
    build:
      context: .
    depends_on:
      db:
        condition: service_healthy
  db:
    build:
      context: ./db
    healthcheck:
      test: "mysql --password=${MYSQL_ROOT_PASSWORD} --execute 'show databases;'"
      interval: 3s
      timeout: 30s
      retries: 10
      start_period: 0s

または、邪道ではあるがservices.back(mysqlに依存しているコンテナ)のentrypointを”/bin/sh -c ‘sleep 10 && node app'”のように設定し、10秒くらい待機することで解決もできる。

services:
  back:
    build:
      context: .
    entrypoint: "/bin/sh -c 'sleep 10 && node app'"

コメント

タイトルとURLをコピーしました