「connect ECONNREFUSED 127.0.0.1:5432」エラーの修正 — サーバーまたはデータベース接続拒否

intermediate🌐 Networking2026-04-28| Node.js / Python / PostgreSQL、MySQL、Redis、またはLinux、macOS、Windows上の任意のTCPサービスに接続するバックエンドアプリ

Error Message

Error: connect ECONNREFUSED 127.0.0.1:5432
#ネットワーキング#econnrefused#バックエンド#データベース#postgresql#nodejs#docker

何が起きたのか

アプリが突然こんなエラーで落ちた:

Error: connect ECONNREFUSED 127.0.0.1:5432

ECONNREFUSED は、OSがそのポートをノックしたら扉を思いっきり閉められた状態だ。タイムアウトでもない。ファイアウォールによるドロップでもない。積極的な拒否——そのポートで何も待ち受けていない。

ポート番号を見れば、どのサービスが音信不通になったかがわかる:5432 = PostgreSQL、3306 = MySQL、6379 = Redis、27017 = MongoDB。どれも根本原因は同じ——サービスが起動していないか、アプリが間違ったアドレスを指しているかだ。

デバッグの手順

ステップ 1 — サービスは本当に起動しているか?

十中八九これが原因だ。他に何もする前にここから始めよう。

# Linux / macOS
sudo systemctl status postgresql
sudo systemctl status mysql
sudo systemctl status redis

# または実際にそのポートで待ち受けているものを確認する
sudo ss -tlnp | grep 5432
sudo lsof -i :5432

そのポートの出力がない?サービスが落ちている。後述の修正1に飛ぼう。

ステップ 2 — 正しいインターフェースで待ち受けているか?

見た目より厄介な問題だ。PostgreSQLは正常に起動していても、127.0.0.1 にしかバインドされていない場合がある——つまりローカルホストからの接続しか受け付けない。

sudo ss -tlnp | grep 5432
# 期待される出力:
# LISTEN 0 128 127.0.0.1:5432 0.0.0.0:*

0.0.0.0:5432 または :::5432 なら全インターフェースで接続を受け付けている。127.0.0.1:5432 だけ?リモート接続は最初から死んでいる——ローカルのみだ。

ステップ 3 — アプリの接続文字列を確認する

タイポは起きる。DB_HOSTDB_PORT の一文字の間違いで、すべての接続試行がブラックホールに吸い込まれる。

# Node.js — .env または設定ファイルを確認する
DB_HOST=localhost
DB_PORT=5432

# Python SQLAlchemy
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb

見落としがちな点:このマシンで localhost は本当に 127.0.0.1 に解決されるか?

ping localhost
# 127.0.0.1 または ::1 に解決されるはず

WSL2やDockerでは、localhost が期待と異なる解決をすることがよくある——多くの開発者がこれに引っかかっている。

ステップ 4 — Docker?おそらくネットワークの問題だ

Dockerコンテナの内部では、localhost はコンテナ自身を指す——ラップトップでもVMでもない。ホストマシン上のデータベースはそのアドレスでは到達できない。

# Linux — DockerブリッジゲートウェイのIPを使う
DB_HOST=172.17.0.1

# MacまたはWindows上のDocker Desktop — これで動く
DB_HOST=host.docker.internal

2つのコンテナが通信する必要がある?同じ名前付きDockerネットワークに置いて、コンテナ名をホスト名として使おう。IPアドレスに頼ってはいけない——再起動のたびに変わる。

修正方法

修正 1 — サービスを起動する

# PostgreSQL
sudo systemctl start postgresql
sudo systemctl enable postgresql   # 起動時に自動スタート

# MySQL / MariaDB
sudo systemctl start mysql

# Redis
sudo systemctl start redis

起動後、実際に立ち上がったか確認する:

sudo ss -tlnp | grep 5432

修正 2 — 起動時にクラッシュしている場合はログを確認する

systemctl start はサイレントに失敗することがある——コマンドはエラーなしで返るが、サービスは数秒以内に死ぬ。ログが理由を教えてくれる。

journalctl -u postgresql -n 50 --no-pager
# 探すもの: パーミッションエラー、ポートの競合、設定ファイルの構文エラー

よくある3つの原因:ディスクがフル(df -h で確認)、データディレクトリ(/var/lib/postgresql/)の所有権が間違っている、または別のプロセスがすでにポート5432を掴んでいる。

# ポートを占有しているものを見つける
sudo lsof -i :5432

修正 3 — リモート接続のためにバインドアドレスを変更する

PostgreSQLの場合、postgresql.conf を見つけて編集する:

# 設定ファイルの場所を確認する
psql -U postgres -c 'SHOW config_file;'

# この行を変更する:
listen_addresses = '*'    # 元: 'localhost'

pg_hba.conf も更新してリモートホストをホワイトリストに追加することを忘れずに。その後再起動する:

sudo systemctl restart postgresql

MySQLの場合、設定は /etc/mysql/mysql.conf.d/mysqld.cnf にある:

bind-address = 0.0.0.0    # 元: 127.0.0.1

修正 4 — 環境変数が読み込まれていない

よくあるタイミングの問題:アプリが .env が読み込まれる前に起動し、localhost:5432 のようなデフォルト値にフォールバックして何にも繋がらない。実行時にアプリが実際に何を見ているか出力してみよう:

# Node.js
console.log('DB:', process.env.DB_HOST, process.env.DB_PORT);

# Python
import os
print(os.getenv('DB_HOST'), os.getenv('DB_PORT'))

undefinedNone が表示される?envファイルが読み込まれていない——dotenvの設定やプロセスの起動方法を確認しよう。

確認方法

アプリを再起動する前に、生のTCPテストでポートが実際に到達可能か確認しよう:

# TCP接続を直接テストする
nc -zv 127.0.0.1 5432
# 成功: Connection to 127.0.0.1 5432 port [tcp/postgresql] succeeded!

# curlを使った代替方法
curl -v telnet://127.0.0.1:5432

これが成功してもアプリがまだ失敗する?問題はサービスではなくアプリの設定にある。ステップ3に戻ろう。

Tips

DockerブリッジネットワークやVPNルーティングをデバッグしていて、見覚えのないIPを眺めている?ToolCraftのサブネット計算機を使えば、あるIPがどのネットワーク範囲に属するかをすばやく確認できる——アドレスがローカルなのか予期しない場所にルーティングされているのかを確かめるのに便利だ。

得られた教訓

  • **ECONNREFUSED = 何も待ち受けていない。**アプリのコードではなく、まずサービスをデバッグしよう。
  • 何かに触れる前に ss -tlnp または lsof -i :PORT を実行しよう。2秒で20分を節約できる。
  • Dockerの localhost トラップは誰もが一度は引っかかる——MacとWindowsでの修正は host.docker.internal だ。
  • 起動時のヘルスチェックを追加して、アプリがクラッシュする代わりにデータベースを待つようにしよう。wait-for-it のようなツールが一行でこれを解決してくれる。
  • すべてのデータベースサービスで systemctl enable を実行しよう。サーバーの再起動のたびにこのエラーを追いかけ回すことになってはいけない。

Related Error Notes