複数の Docker コンテナが同じポート番号を持たない場合の解決策

複数の Docker コンテナが同じポート番号を持たない場合の解決策

背景

Dockerでは、同じイメージを使用して4つのコンテナを作成します。ネットワークはブリッジモードです。サービスAは、4つのコンテナすべてで同じポート番号(6000)を使用します。外部に公開されるポートの数を減らすために、4つのサービスインスタンスのプロキシとしてnginxを使用します。4つのサービスインスタンスは4つのアップストリームに属しており、4つのインスタンスへのアクセスには/service1や/service2などのパスが使用されます。

現時点では、ローカルで何らかのサービスにアクセスすると 502 エラーが報告され、困惑します。

アップストリームへの接続中に connect() が失敗しました (111: 接続が拒否されました)

ファイルを作成

バージョン: '2'
ネットワーク:
 んん:
  ドライバー: ブリッジ
サービス:
 サービス1:
  コンテナ名: サービス1
  画像: foo
  ネットワーク:
   -んんん
  ボリューム:
   - ./logs/1:/apps/aaa/bbb-logs
   - ./common:/apps/aaa/bbb
   - ./xxx/1.xml:/ccc/targets.xml
  エントリポイント: foo.sh
  コマンド: start app=foo port=6000
  
 サービス2:
  コンテナ名: サービス2
  画像: foo
  ネットワーク:
   -んんん
  ボリューム:
   - ./logs/2:/apps/aaa/bbb-logs
   - ./common:/apps/aaa/bbb
   - ./xxx/2.xml:/ccc/targets.xml
  エントリポイント: foo.sh
  コマンド: start app=foo port=6000
 
 サービス3:
  コンテナ名: サービス3
  画像: foo
  ネットワーク:
   -んんん
  ボリューム:
   - ./logs/3:/apps/aaa/bbb-logs
   - ./common:/apps/aaa/bbb
   - ./xxx/3.xml:/ccc/targets.xml
  エントリポイント: foo.sh
  コマンド: start app=foo port=6000
 
 サービス4:
  コンテナ名: サービス4
  画像: foo
  ネットワーク:
   -んんん
  ボリューム:
   - ./logs/4:/apps/aaa/bbb-logs
   - ./common:/apps/aaa/bbb
   - ./xxx/4.xml:/ccc/targets.xml
  エントリポイント: foo.sh
  コマンド: start app=foo port=6000  
 
 nginx:
  コンテナ名: nginx
  イメージ: nginx:1.15-alpine
  ポート:
   - 6001:6001
  ネットワーク:
   -んんん
  ボリューム:
   ./nginx/nginx.conf:/etc/nginx/nginx.conf
   nginx のログファイル

nginx.conf

ワーカープロセス数 8;
ワーカー_rlimit_nofile 65535; 
イベント {
    epoll を使用します。
    ワーカー接続 65535;
 }
 
http {
    mime.types を含めます。
    default_type アプリケーション/オクテットストリーム;
    ファイル送信オン;
    log_format main '[$time_local]$remote_addr-$upstream_addr "$request" $status $body_bytes_sent';
 
    アップストリームサービス1.local {
      サーバーサービス-1:6000;
    }
    アップストリームサービス2.local {
     サーバーサービス2:6000;
    }
    アップストリームサービス3.local {
      サーバーサービス3:6000;
    }
    アップストリームサービス4.local {
      サーバーサービス-4:6000;
    }
 
    サーバー{
      6001を聴く;
      クライアントの最大ボディサイズは100Mです。
      proxy_set_header ホスト $host:$server_port;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 
      場所 /service1/ {
        proxy_pass http://service1.local/;
      }
      場所 /service2/ {
        proxy_pass http://service2.local/;
      }
      場所 /service3/ {
        proxy_pass http://service3.local/;
      }
      場所 /service4/ {
        proxy_pass http://service4.local/;
      }
      場所 /nginx_status {
        stub_status オン;
        access_log オフ;
      }
    }
}
 

このとき、 curl localhost:6001/service1/api/v1/.... は上記の 502 エラーを報告します。各コンテナには独自のネットワーク カードがあり、異なるコンテナのポート番号が競合しないのは当然です。

解決

現時点ではこれより良い解決策はないので、4 つのサービスに異なるポート番号を使用し、それに応じて nginx を変更するしかありません。

補足: 同じサーバーに複数の Docker コンテナをデプロイするとポートリダイレクトの問題が発生する

実稼働環境では、複数のコンテナをデプロイし、複数のポートにアクセスします。

例: -p 80:80 -p 81:81

アドレス81が存在する場合は、ポート80のアドレスに直接アクセスします。

誤解: 最初はクッキーを更新したのでクッキーの問題だと思った (クッキーはポート番号を区別しない)

ついに理由が分かりました: リダイレクトの問題。ログアウトするとログインページにリダイレクトされるからです。

解決策: nginxパラメータを設定する

proxy_set_header HOST $host; は proxy_set_header HOST $host:81; になります。

なぜなら、リクエストパラメータには必ずポート番号が含まれるからです。

インターネット上には別の方法があります: proxy_redirect パラメータを変更する (ただし、試しても機能しませんでした)

上記は私の個人的な経験です。参考になれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。間違いや不備な点がありましたら、遠慮なくご指摘ください。

以下もご興味があるかもしれません:
  • Dockerでudpポート番号を指定する問題を解決する
  • Raspberry Pi シリーズ: Docker を使用して Qinglong Panel をインストールし、ポート番号の設定の問題を変更する

<<:  MySQL 8.0 redo ログの詳細な分析

>>:  Vue のライフサイクルとフック関数の詳細な説明と典型的な面接の質問

推薦する

Vue3 (パート 2) Ant Design Vue の統合

目次1. Ant Design Vueを統合する2. コンポーネントの使用1. 完全な引用2. コン...

Win10 の Linux サブシステムを有効にする方法を説明します (詳細な画像とテキスト付き)

今日は、Windows 10 で Linux サブシステムを有効にする方法を紹介します。早速、手順を...

ズームインとズームアウトの閉じるボタンを実現する CSS (サンプル コード)

この効果はブラウザ ページで最もよく見られます。まずは効果の画像をご覧ください。 上の図に示すように...

Element-uiはテーブル内のセルを直接クリックして編集します

目次成果を達成する実装コード最近、会社でelementUIを使い始めたため、開発の過程でテーブルのセ...

Javascriptはセキュリティ検証に整合性属性を使用します

目次1. スクリプトタグを使用してファイルをインポートする1. ローカルファイルをインポートする2....

Vueはプルダウンを実装してさらに読み込む

Element-UI に慣れた開発者なら、無限スクロールの InfiniteScroll が使いにく...

MySQL ルートパスワードをリセットする方法

目次1. ルートパスワードを忘れてしまい、データベースにアクセスできない: DBA にとって、スーパ...

jsは配列の平坦化を実装します

目次配列をフラット化する方法1.flat() の使用2. 正規表現を使用する3.reduce()+c...

Ubuntu 20.04 中国語入力方法のインストール手順

この記事では、Google 入力方法をインストールします。実は以前はSogou入力方式を使っていたの...

CSS3 を使用して円形スクロール プログレス バー アニメーションを作成する例

テーマ今日は、CSS3 を使用して円形スクロール プログレス バー アニメーションを作成する方法を説...

MySQL インデックスの左端原則のサンプルコード

序文最近、MySQL のインデックスについて読んでいました。結合されたインデックスを見ると、左端の原...

JavaScript でネットワーク速度をテストする方法

目次序文ネットワーク速度のフロントエンド判定原理のまとめ1. img を読み込むか Ajax リクエ...

MySQLバックアップとリカバリの実践に関する詳細な説明

1. mysqlbackup の紹介mysqlbackup は、MySQL Enterprise B...

時間範囲効果を実現するためのJavaScript

この記事では、時間範囲効果を実現するためのJavaScriptの具体的なコードを参考までに紹介します...

Vue ユニットテストに関する予備調査

目次序文なぜユニットテストを導入するのですか?ユニットテストの概要テスト開発パターン1. テスト駆動...