ポートマッピング後に Docker コンテナが突然接続に失敗する問題のトラブルシューティング プロセス

ポートマッピング後に Docker コンテナが突然接続に失敗する問題のトラブルシューティング プロセス

1. 背景

通常、外部サービスを提供する必要がある Docker コンテナの場合、起動時に -p コマンドを使用して外部アクセス ポートを外部に公開します。たとえば、Docker Registry を起動するときに、外部アクセス用にポート 5000 をマップします。

docker run -d -p 5000:5000 レジストリ

しかし最近、非常に奇妙な状況に遭遇しました。R&D チームの CentOS 7 テスト環境に Docker レジストリがデプロイされ、ポートが外部に公開されていたのです。コンテナを起動すると、一定期間は正常に動作しますが、無期限の時間が経過すると、外部ホストはウェアハウスからイメージをプルできなくなり、タイムアウトが表示されます。

ただし、Docker ホスト上のリポジトリへのアクセスは通常どおりに実行できます。

この問題に関しては、問題のある Docker デーモン サービスを手動で再起動した後にのみ外部アクセスを復元できますが、しばらくすると問題が再発します。

2. トラブルシューティング

この問題に遭遇したとき、私の最初の反応は、グループのメンバーに CentOS 7 独自のファイアウォールを再起動した人がいるかどうかを尋ねることでした。

このサーバーは私が設定したもので、ファイアウォールはオンになっていますが、すでにポートアクセスは開いているので、ファイアウォールが接続をブロックしているからというわけではありません。しかし、この記事は落とし穴の調査文書なので、やはりこの状況を書き出しました。

ケース1: ファイアウォールはオンになっているがポートが開いていない

CentOS 7 にはファイアウォール FirewallD が付属しており、有効になっています。次のコマンドで FirewallD のステータスを確認できます。

ファイアウォール-cmd --state 

出力が「not running」の場合、FirewallD は実行されておらず、すべての保護ポリシーが開始されていません。この場合、ファイアウォールが接続をブロックしている可能性は排除できます。

出力が「running」の場合、FirewallD が現在実行中であることを意味します。現在開いているポートとサービスを表示するには、次のコマンドを入力する必要があります。

ファイアウォールコマンド --list-ports
ファイアウォールコマンド --list-services 

現在のファイアウォールはポート 80/tcp、ssh サービス (22/tcp)、dhcpv6-client サービスのみを開いており、Docker コンテナによってマップされたポート 5000/tcp は開いていないことがわかります。

解決策は2つあります。

1. FirewallD サービスをオフにします。

ファイアウォールが不要な場合は、FirewallD サービスをオフにしてください。

systemctl 停止 ファイアウォールd.service

2. 指定したポートを外部に開くポリシーを追加します。

たとえば、外部の 5000/tcp ポートを開きたい場合は、次のコマンドを使用できます。

ファイアウォールコマンド --add-port=5000/tcp --permanent
ファイアウォール-cmd --reload

ポートを一時的にのみ開きたい場合は、コマンドの最初の行にある「--permanent」パラメータを削除します。その後、FirewallD サービスを再起動すると、このポリシーは無効になります。

ケース2: CentOS 7のFirewallDサービスを手動で再起動する

FirewallD は CentOS システムのバージョン 7 で導入された新しいコンポーネントです。簡単に言えば、ファイアウォール関連の設定を簡素化するために使用される iptables のラッパーです。

しかし、FirewallD と Docker は相性がよくありません。FirewallD が起動 (または再起動) すると、iptables から DOCKER チェーンが削除され、Docker が正しく動作しなくなります。

ファイアウォールD

CentOS-7 では、iptables のラッパーである firewalld が導入されましたが、これは Docker と競合する可能性があります。

firewalld を起動または再起動すると、iptables から DOCKER チェーンが削除され、Docker が正常に動作しなくなります。

Systemd を使用する場合、firewalld は Docker の前に起動されますが、Docker の後に firewalld を起動または再起動する場合は、Docker デーモンを再起動する必要があります。

Dockerの公式ドキュメント「CentOS - Docker Documentation」より抜粋

CentOS 7 では、Docker は systemd 構成ファイルに「After=firewalld.service」と明記し、FirewallD の起動後に Docker デーモンが起動するようにしているため、起動時に Docker サービスを自動的に起動するように systemd を設定しても問題はありません。

(ドッカー:私を怒らせる余裕がないなら、私から隠れる余裕はありますか?)

ただし、ユーザーが手動で FirewallD サービスを再起動するたびに、FirewallD サービスは Docker デーモンによって iptables に書き込まれた DOCKER チェーンを削除するため、Docker デーモン サービスが DOCKER チェーンを再構築できるように、Docker デーモン サービスを手動で 1 回再起動する必要があります。

しかし、グループ内の他の2人の研究開発担当者に尋ねたところ、2人とも触っていないとのことでした。シェルの履歴を確認しましたが、対応するレコードは見つかりませんでした。

それは奇妙ですね。しかし、しばらく調査した後、ついに新たな理由が見つかりました。

ケース3: IP_FORWARDが有効になっていない

問題を特定できなかったため、倉庫に正常にアクセスできないことが判明すると、R&D チームが手動でホスト マシンにログインし、Docker デーモン サービスを再起動します。

ホスト サーバーにログインして Docker デーモン サービスを再起動する前に、以前 Docker を使用したときに遭遇した別の問題を突然思い出しました。ホスト マシンで IP_FORWARD 機能が有効になっていないと、Docker コンテナーは起動時に警告メッセージを出力します。

警告: IPv4 転送が無効になっています。ネットワークは機能しません。

また、起動したコンテナでは外部ネットワークにアクセスできなくなり、コンテナによって公開されるポートには外部から正常にアクセスできなくなります。

この障害は、ホスト マシンの IP_FORWARD 機能が有効になっていないことが原因でしょうか?

sysctl net.ipv4.ip_forward 

確かに、出力には、現在のシステムの IP_FORWARD 機能が無効になっていることが示されています。

しかし問題は、コンテナを起動したときにはすべて正常で、出力がなかったことです。使用中に IP_FORWARD 関数が無効になったのはなぜでしょうか?

待ってください。Docker デーモン サービスは起動時に iptables 設定を自動的に設定します。IP_FORWARD 設定もチェックして、一時的に有効にしてくれるのでしょうか?

この仮定に基づいて、Docker デーモン サービスを手動で再起動しました。

案の定、Docker デーモン サービスは起動時にシステムの IP_FORWARD 設定項目をチェックします。現在のシステムの IP_FORWARD 機能が無効になっている場合は、IP_FORWARD 機能を一時的に有効にするのに役立ちます。ただし、一時的に有効になった IP_FORWARD 機能は、他のさまざまな理由で失敗します...

この障害の具体的な原因を突き止める決定的な証拠はまだありませんが、ネットワーク サービスの再起動が原因であると真剣に疑っています。問題のあるサーバー ホストは、当社の R&D チームが開発している Web プロジェクトを実行しているため、機能の 1 つはネットワーク カードの IP アドレスを変更することです。ネットワーク カードの IP を変更した後、この機能は自動的に次のコマンドを呼び出してネットワーク サービスを再起動します。

systemctl でネットワークサービスを再起動します。

ネットワーク サービスを再起動すると、Docker デーモン サービスによって自動的に設定された一時的な IP_FORWARD 構成が無効になります。

また、プログラムはコマンドを直接呼び出すため、履歴コマンドに痕跡は残りません。

修復ソリューションは非常に簡単で、コマンド 1 行だけです。

エコー 'net.ipv4.ip_forward = 1' >> /usr/lib/sysctl.d/50-default.conf

実行が完了したら、サーバーを再起動するか、次のコマンドを使用してファイルから構成を読み込みます。

sysctl -p /usr/lib/sysctl.d/50-default.conf 

それでおしまい。

3. まとめ

Docker デーモン サービスは、起動時に、今回問題を引き起こした IP_FORWARD 構成など、多くの構成項目を調整するのに役立ちます。

Docker デーモンは、Docker コンテナのデフォルトのネットワーク モード (ブリッジ モード) が各コンテナにプライベート IP を割り当てるため、 IP_FORWARD 機能を有効にします。コンテナが外部と通信する必要がある場合は、NAT が必要です。 NAT では IP_FORWARD 機能がサポートされている必要があります。そうでない場合、NAT は使用できません。これは、IP_FORWARD 機能が無効になっている場合、ブリッジ モードを使用するコンテナーに内部からも外部からもアクセスできない理由も説明しています。

ただし、Linux ではセキュリティ上の理由から、IP_FORWARD 機能はデフォルトで無効になっています。Docker デーモン サービスは起動時に IP_FORWARD 機能が有効になっているかどうかを確認します。有効になっていない場合、Docker デーモンはこの機能を一時的にサイレントに有効にします。ただし、一時的に有効になった IP_FORWARD 機能は永続化できず、他のコマンドの干渉により無効になります。

しかし、この出来事から私はちょっとした真実を学びました。問題が発生したときは、慌てず、経験に基づいて大胆な仮定を立て、それを検証して症状と根本原因の両方に対処することです。

要約する

上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に一定の参考学習価値を持つことを願っています。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM を応援していただきありがとうございます。

以下もご興味があるかもしれません:
  • 実行中のDockerコンテナのポートマッピングを変更する方法
  • Docker ポート マッピングと外部アクセス不可の問題
  • Dockerコンテナの起動後にポートマッピングを追加する
  • Docker で実行中のコンテナのポート マッピングを設定する方法
  • Dockerコンテナの4つのポートマッピングのデモンストレーションと分析

<<:  Vue3サンドボックスの仕組みの詳しい説明

>>:  MySQLデータベースの増分バックアップのアイデアと方法

推薦する

WMLとは何ですか?

WML (ワイヤレス マークアップ言語)。これは HTML から派生したマークアップ言語ですが、W...

Linux ipcsコマンドの使用

1. コマンドの紹介ipcs コマンドは、Linux のプロセス間通信機能の状態を報告するために使用...

Zabbix の psk 暗号化と zabbix_get 値の組み合わせ

Zabbix バージョン 3.0 以降、Zabbix サーバー、Zabbix プロキシ、Zabbix...

MySQLにおける(JOIN/ORDER BY)文のクエリ処理と最適化方法

EXPLAIN ステートメントは、MySQL クエリ ステートメント プロセスと EXPLAIN ス...

SQL文のANDとORの実行順序で発生する問題

質問昨日、データベースSQLを書いているときに問題が発生しました。問題の根本は、SQL ステートメン...

VMware14 に CentOS 7 をインストールするグラフィック チュートリアル

CentOS の紹介CentOS は、Red Hat Linux が提供する無料で利用できるソースコ...

Vue双方向バインディングの詳細な説明

目次1. 双方向バインディング2. 他のタグを選択した場合にも同じ結果になりますか? 答えはもちろん...

HTML テーブル境界制御実装コード

一般的に、テーブルを使用する場合は、常に <table border="1"...

Linux で at および cron スケジュールタスクをカスタマイズする方法

Linux システムには 2 種類のスケジュールされたタスクがあります。1 つは 1 回だけ実行され...

SQL GROUP BYの詳細な説明と簡単な例

GROUP BY ステートメントは、Aggregate 関数と組み合わせて使用​​され、1 つ以上の...

MySQL が大規模トランザクションを避けるべき理由とその解決方法

何が大問題ですか?長時間実行され、長時間コミットされないトランザクションは、大規模トランザクションと...

MySQLでの少し複雑な使用例コード

序文MySQL の構文は誰にとっても難しいものではないと思いますが、この記事では主に MySQL の...

MySQLの重複排除操作を極限まで最適化する方法

目次1. インデックスと変数の賢い使用1. インデックスなしの比較テスト2. created_tim...

Docker+DockerCompose を使用して Web アプリケーションをカプセル化する方法

目次テクノロジースタックバックエンドビルドAPIフロントエンドウェブ構築ゲートウェイ建設ゲートウェイ...

Mac に mysql5.7 をインストールするための完全な手順 (画像とテキスト付き)

最近、Mac システムを使用して、ローカル Web サーバー環境を構築する準備をしていました。 Ma...