できない.dev

docker compose のサービス名で DNS 解決できない

compose ではサービス名がそのまま DNS 名として解決されるが、別 compose ファイルや depends_on の起動タイミング、network 設定のミスで名前解決が失敗する。
同一ネットワーク所属と起動完了待ちを揃える。

公開: 更新:

実行例あり(2026-09-23 に実環境で検証)

要約

docker compose 内のサービスは 同じ bridge ネットワークに参加していれば、サービス名がそのまま DNS 名 として解決される。db などに繋がらない場合は、まず 同じ network にいるか と 依存先がもう起動済みか を確認する。
host ネットワーク利用時はそもそも compose の DNS が効かない点にも注意。

実行例

Windows 11 上の Docker 29.1.3 で試すと、別の compose ファイルから起動した worker では user-db が引けず getent は何も返さずに終了コード 2 で終わるが、external ネットワーク shared-demo に両方を参加させると解決できるようになる。
アンダースコア入りの my_db も compose の DNS ではそのまま解決し、aliases で付けた mydb も同じアドレスを返す。

$ docker compose ps --format "table {{.Service}}\t{{.State}}"
SERVICE   STATE
api       running
user-db   running
$ docker compose exec api getent hosts user-db
172.21.0.3        user-db  user-db
終了コード: 0
$ docker network inspect <project>_default --format "{{range .Containers}}{{.Name}} {{end}}"
dnsdemo3720a-api-1 dnsdemo3720a-user-db-1
$ docker compose exec worker getent hosts user-db
終了コード: 2
$ docker network create shared-demo
40c5b82cdb2139a84810e72db205de942efd04d7af780899c7dc53896fdfc192
$ docker compose exec worker getent hosts user-db
172.23.0.2        user-db  user-db
終了コード: 0
$ docker compose exec api getent hosts my_db
172.21.0.3        my_db  my_db
終了コード: 0
$ docker compose exec api getent hosts mydb
172.21.0.3        mydb  mydb
終了コード: 0

— 2026-09-23 時点の出力

検証環境

検証日
実行環境
local host (Windows 11 Home, Docker 29.1.3)
バージョン
  • Node.js 22.14.0
  • npm 10.9.2
  • Git 2.48.1.windows.1
  • Docker 29.1.3

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. 別ネットワークに居る: 別 compose.yaml で起動したコンテナ同士は、明示しない限り別ネットワークになり名前解決できない
  2. 起動順の油断: depends_on は起動順を保証するが、プロセスが listen を始めるまで は待ってくれない
  3. host ネットワーク: network_mode: host 配下のコンテナは bridge の DNS テーブルに載らず、サービス名解決ができない
  4. サービス名のアンダースコア: my_db は DNS のラベル仕様(RFC 1035)やホスト名の文法(RFC 952 / 1123)では許されない文字を含む。
    ただし compose の DNS はこの名前も解決するので、詰まるとすればホスト名を厳しく検査するクライアント側であり、名前解決そのものが落ちているわけではない

解決策

1. 同一ネットワークか確認

docker compose ps
docker network inspect <project>_default

Containers 配下に両方のサービスが居れば OK。
別ファイル間で繋ぐ場合は片方を external ネットワークに参加させる:

networks:
  shared:
    external: true
 
services:
  api:
    networks: [shared]

公式のネットワーキングガイド(新しいタブで開く) に external network の使い方が記載されている。

2. depends_on で起動完了まで待つ

services:
  db:
    image: postgres
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 2s
      retries: 10
  api:
    depends_on:
      db:
        condition: service_healthy

condition: service_healthy を指定すると、healthcheck が成功するまで api が起動しない。

3. host ネットワークを避ける

network_mode: host を使うと bridge の DNS が無効になる。
どうしても必要な場合は IP アドレスや host.docker.internal を使うが、原則 bridge を使う方が compose の旨味(サービス名解決)を保てる。

4. サービス名は小文字ハイフン

services:
  user-db:
    image: postgres

アンダースコアを避け、ハイフン区切りか単一単語で命名する。
これは名前解決を直すためというより、文法に厳しいクライアントに当たったときの逃げ道を無くさないための予防である。
既存名を変えにくいなら、aliases で別名を付けてクライアントから使う:

services:
  my_db:
    networks:
      default:
        aliases: [mydb]

この記事は役立ちましたか?