Docker環境におけるWebサーバー接続拒否の診断と復旧手順

コンテナ内で動作するHTTPサービスに対し、ホストからのアクセスが「Connection refused」で遮断される事象が発生しました。ポート転送設定の検証、ネットワークフィルタの確認、内部ログの解析を経て、プロセスの信号処理異常によるサスペンド状態を特定し、サービスを復旧させた技術的フローを記述します。

ネットワークフィルタとポート転送の検証

まず、ホストレベルのパケット遮断が発生していないかを確認します。CentOS系環境におけるデフォルトファイアウォール状態を参照しました。

# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled)
   Active: inactive (dead)

サービスが非活性化されているため、外部からのパケット到達はコンテナのDockerプロキシ設定に依存します。ポートマッピング自体に異常はないため、内部プロセスの状態へ調査を移行します。

コンテナ出力ストリームとエラーログの解析

コンテナの標準出力を追跡し、プロセスの起動・終了履歴を確認します。

$ docker logs web_app_01
2025-11-11 08:20:40 WARN received SIGTERM indicating exit request
2025-11-11 08:20:43 INFO waiting for httpd, mysqld to die
2025-11-11 08:20:49 INFO supervisor: apache2 process terminated

Webサーバーが起動直後に異常終了している様子が確認できます。単純なコンテナ再起動では状態が解消しないため、対話型シェルへ進入して詳細を調査します。

$ docker exec -it web_app_01 /bin/bash
root@container_id:/#

内部のエラーログを参照すると、PIDファイルの競合と不正終了の警告が記録されていました。構成ファイルの構文チェックは正常に通過するため、設定の破損は除外できます。

# apache2ctl configtest
Syntax OK

# tail -n 15 /var/log/apache2/error.log
[Tue Nov 11 07:53:30] [core:warn] AH00098: pid file /run/apache2/apache2.pid overwritten
[Tue Nov 11 07:53:30] [mpm_prefork:notice] AH00163: Apache/2.4.41 configured -- resuming normal operations

ポートバインドとプロセス状態の特定

ローカルホストからの接続テストでは接続拒否が返ります。ネットワーク状態を可視化するため、監視ユーティリティを導入してソケット情報を取得します。

# apt-get update && apt-get install -y net-tools
# netstat -tlnp | grep -E ':(80|3306)'
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      -

データベースポートのみがリッスンしており、Webサーバーのポートバインドが消失しています。起動スクリプトを確認すると、`exec apache2 -D FOREGROUND` が定義されていましたが、実際のプロセスリストには対象のバイナリが存在しません。

# ps aux | grep -E 'apache|httpd' | grep -v grep
(出力なし)

デバッグモード起動による異常状態の再現

古いPIDファイルを削除し、デバッグフラグを使用してプロセスをフォアグラウンド起動した際、端末操作により`suspend`信号が送信されました。これにより、プロセスはポート`80`のバインドを保持したまま`T`(停止)ステータスに遷移しました。

# rm -f /var/run/apache2/apache2.pid
# apache2ctl start -X
^Z
[1]+  Stopped                 apache2ctl start -X

# ps -eo pid,state,cmd | grep apache
  884 T  /usr/sbin/apache2 -X

ポートは占有されているが、カーネル空間でリクエストキューを処理できないため、`Connection reset by peer` が発生する状態です。

プロセスの強制解放とデーモン再起動

サスペンド状態のバイナリを確実に終了させ、通常のバックグラウンドモードでサービスを復旧します。

# kill -9 $(pgrep -f apache2)
# rm -f /var/run/apache2/apache2.pid
# service apache2 start

# ss -tlnp | grep :80
LISTEN  0  128  0.0.0.0:80  0.0.0.0:*  users:(("apache2",pid=9012,fd=4))

# curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1
200

メインプロセスとワーカープロセスが`S`(スリープ)状態で常駐し、HTTPステータス`200`が正常に返却されていることを確認できました。

技術的考察

本事象の根本原因は、デバッグ実行オプション(`-X`)とシェル制御コマンドの組み合わせによるプロセス状態の不一致です。`Ctrl+Z` は`SIGTSTP`をプロセスグループに送信し、ソケットのバインド状態を維持したまま実行コンテキストを一時停止させます。Docker環境では`CMD`や`ENTRYPOINT`に定義されたプロセスマネージャー(supervisord等)が子プロセスの終了コードを監視しているため、意図しない信号処理が再起動ループやポート競合を引き起こす要因となります。運用時はフロントエンド実行オプションを避け、標準的なデーモン起動シーケンスを採用することで、リソースの解放と信号伝播の整合性を担保できます。

タグ: Docker apache-httpd linux-troubleshooting container-networking process-signal

5月17日 01:12 投稿