1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Dockerのネットワークエイリアスの競合

Last updated at Posted at 2025-12-02

はじめに

本記事ではDocker composeを基準に進めますが、CLIでも同様です。

コンテナ間通信

Dockerのコンテナ名とネットワーク

Dockerのコンテナ間通信について基本知識を知っておきましょう。

DockerコンテナはDocker networkを介してコンテナ間通信を行うことができます。

同じネットワークに接続されているコンテナ同士は、

http://[コンテナ名]:[ポート(オプション)]

というURIでアクセス可能です。

コンテナ名はコンテナに与えられる一意の名前で、デフォルトでは

[プロジェクト名]_[サービス名]_[連番]

の形で自動生成されます。
container_nameキーを使って明示的にコンテナ名を指定することも可能です。

いずれの場合でも、コンテナ名はDocker全体で一意でなければなりません。

例えば以下のcomposeは起動失敗します。

許されないコンテナ名の重複
services:
  container1:
    container_name: app
    ...
  container2:
    container_name: app # appの重複
    ...
実行結果
$ docker compose up -d
> services.container2: container name "app" is already in use by service {}"

ネットワークエイリアス

引き続きネットワークエイリアスについても知っておきましょう。

コンテナは、ネットワーク範囲のエイリアス(別名)を持つことが可能です。

例えば、下のcomposeを見てください。

services:
  mysql:
    container_name: mysql
    networks:
      db_network: # db_networkに参加し、dbというエイリアスを持つ
        aliases:
          - db
  app:
    container_name: app
    networks:
      - db_network: # db_networkに参加

networks:
  db_network: # appとmysqlが共に参加するネットワーク

このとき、appコンテナはmysqlに2通りの名前でアクセスが可能です。
すなわち

コンテナ名を用いたアクセス
http://mysql
エイリアスを用いたアクセス
http://db

エイリアスは複数指定することが可能です。

重要な点として、エイリアスはコンテナ間通信においてのみコンテナ名の代わりとして使用できます。
そのため、以下のように使うことはできません。

エイリアスをつけたコンテナを起動したかった
$ docker compose up db -d
実行結果
> Error response from daemon: No such container: db

エイリアスの競合

エイリアスについて理解したところで、本題です。
このエイリアス、一意であることを強制されません

複数のコンテナに同じエイリアスを割り当てることができます。
実行してもエラーになりません。

実験をしてみましょう。

エイリアス競合実験

概要

自分に割り当てられた名前を返すシンプルなコンテナを複数用意し、同じエイリアスを指定して様子を見てみましょう。

今回はapp_aapp_bapp_cの3つのコンテナを仮定します。
まとめて「応答コンテナ」と呼びましょう。

応答コンテナは実験のために単純化します。
curlでアクセスされたとき、自分に割り当てられた名前を返すだけのものです。

3つの応答コンテナには、全て同じエイリアスappを割り当てます。

curlを送出するのは観測用のメインコンテナmainです。

応答コンテナとメインコンテナは共通のネットワークtest_netに接続します。

各応答コンテナに、メインコンテナからアクセスする、というシナリオです。

実験準備

ディレクトリ構造
./ #
├── Dockerfile # 応答コンテナ用
├── compose.yml
├── entrypoint.sh # 応答コンテナビルド用
└── main.Dockerfile # 応答コンテナに接続するメインコンテナ
Dockerfile
FROM nginx:alpine
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 80
CMD ["/entrypoint.sh"]
compose.yml
services:
  app_a: # 応答コンテナ1つ目
    build: .
    container_name: app_a
    environment:
      NAME: app A
    networks:
      test_net:
        aliases:
          - app
  app_b: # 応答コンテナ2つ目
    build: .
    container_name: app_b
    environment:
      NAME: app B
    networks:
      test_net:
        aliases:
          - app
  app_c: # 応答コンテナ3つ目
    build: .
    container_name: app_c
    environment:
      NAME: app C
    networks:
      test_net:
        aliases:
          - app
 
  app_main: # メインコンテナ
    container_name: main
    build:
      context: .
      dockerfile: main.Dockerfile
    tty: true
    networks:
      - test_net
networks:
  test_net:
entrypoint.sh
echo "Hi I'm ${NAME} container!" > /usr/share/nginx/html/index.html
nginx -g "daemon off;"
main.Dockerfile

FROM alpine
RUN apk update && apk add curl

ファイルが揃ったディレクトリで以下のコマンドを実行して、実験を始めましょう。

実験開始
docker compose up -d
docker exec -it main sh # 観測のためにメインコンテナに入る

実験① コンテナ名でアクセスしてみる

各応答コンテナにコンテナ名でアクセス
curl http://app_a
curl http://app_b
curl http://app_c
結果
Hi I'm app A container!
Hi I'm app B container!
Hi I'm app C container!

ちゃんと対応するコンテナが応答していますね。

では、エイリアスでやってみましょう。

実験② エイリアスでアクセスしてみる

エイリアスでアクセスしてみる
curl http://app

何回かこのコマンドを叩いてみてください。

結果
Hi I'm app B container!
Hi I'm app A container!
Hi I'm app B container!
Hi I'm app C container!
Hi I'm app A container!
...

無作為に応答コンテナへ繋いでいます。

解説

DNSラウンドロビン

ここまででピンときた方もいらっしゃるかもしれません。

エイリアスを指定した際の無作為な応答は、DNSラウンドロビンの挙動そのものです。

DNSラウンドロビンの概要

DNSラウンドロビンのWikipediaには

一つのドメイン名に複数のIPアドレスを割り当てる負荷分散技術

とあります。

通常DNSのAレコードは、1エントリにつきドメインとアドレスが一対一で対応します。

DNSレコード
hoge       IN  A  127.0.1.1

hogeへのリクエストは、127.0.1.1が応答します。

では以下のレコードはどうでしょう。

DNSラウンドロビン
hoge       IN  A  127.0.1.1
hoge       IN  A  127.0.1.2
hoge       IN  A  127.0.1.3

このレコードは、hogeへのリクエストに対し、127.0.0.1127.0.0.2127.0.0.3の3つが応答可能です。

同じドメインで異なるアドレスのAレコードを複数登録すると、そのドメインに紐づけられたアドレスを順繰りで返すことになっています

この挙動は、1つのドメインに来るアクセスを複数のアドレス先に分散させてサーバーあたりの負荷を軽減するという、原始的なロードバランサとして機能することになっています

これがDNSラウンドロビンです。

ラウンドロビンの偏り

前項で、”なっている”と強調したのは、実際に登録された中から返されるアドレスはきれいな順繰り(ローテーション)でも、均等なランダムでもないからです。

詳しい説明は省きますが、ラウンドロビンで返されるアドレスは様々な要因によって大きく偏りが生じます。

実験②のコマンドを叩き続けると、実際にある程度の偏りを観察できるでしょう。

この偏り以外にも、ロードバランサーとしてのDNSラウンドロビンは、使い勝手が悪い問題点を数多く抱えており、現在では積極的に採用されることは少なくなっています。

DockerのDNS

Dockerはデーモンの中にDNSサーバーを内蔵しており、コンテナの名前解決を実現しています。

ネットワークエイリアスは、コンテナと紐づけられたレコードとして内蔵DNSに正常に登録されます。

重複したエイリアスは同じドメインに対する異なるアドレスとして登録され、結果DNSラウンドロビン状態になるというわけです。

結論と感想

意図してDocker内ラウンドロビンを作る必要性はほぼない気がします。

余程尖った需要がない限り、コンテナ名を使うほうが確実で安心ですね。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?