エラー文
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'"