エラーの概要

Docker Composeで401エラーが発生する場合、コンテナレジストリーへの認証に失敗しています。このエラーはプライベートイメージをpullしようとする際に最も頻繁に発生し、レジストリー側が「認証情報が不正または未提供」と判定した状態です。Docker Hubやプライベートレジストリー(ECR、GCR、プライベートDockerレジストリーなど)の両方で起こりえます。

実際のエラーメッセージ例

ERROR: for <service-name>  UnexpectedStatusError(401): 401 Client Error: Unauthorized for url: https://index.docker.io/v2/<image-name>/manifests/latest
{
  "message": "unauthorized: authentication required",
  "details": "https://docs.docker.com/docker-hub/access-tokens/"
}
ERROR: for myapp  pull access denied for myregistry.azurecr.io/myimage, repository does not exist or may require 'docker login': denied: authentication required

よくある原因と解決手順

原因1:docker loginを実行していない

Docker Composeでプライベートイメージをpullする前に、docker loginコマンド認証を済ませていない状況です。認証情報が~/.docker/config.json保存されていないため、レジストリー側は401で応答します。

Before(エラーが起きるコード):

# 認証なしで直接実行
$ docker-compose up
ERROR: for webapp  UnexpectedStatusError(401): 401 Client Error: Unauthorized

After(修正後):

# 1. 先に認証を完了させる
$ docker login
Username: <your-username>
Password: <your-password>
Login Succeeded

# 2. その後にdocker-composeを実行
$ docker-compose up

原因2:compose.ymlで正しい認証情報が参照されていない

compose.ymlにレジストリー認証情報を含めるとき、x-aws-cred-helpercredHelpers設定が不正な場合や、設定ファイル自体が存在しない場合に401が発生します。

Before(エラーが起きるコード):

version: '3.8'
services:
  app:
    image: myregistry.azurecr.io/myapp:latest
    # 認証情報が指定されていない

After(修正後):

version: '3.8'
services:
  app:
    image: myregistry.azurecr.io/myapp:latest
    # ~/.docker/config.json に認証情報があることを確認
    # または以下のように環境ファイルから読み込む
    environment:
      - DOCKER_USERNAME=${DOCKER_USERNAME}
      - DOCKER_PASSWORD=${DOCKER_PASSWORD}

~/.docker/config.jsonの確認:

$ cat ~/.docker/config.json
{
  "auths": {
    "myregistry.azurecr.io": {
      "auth": "base64encodedcredentials"
    }
  }
}

原因3:レジストリーのアクセストークンが期限切れまたは無効

Docker Hubやプライベートレジストリーで生成したアクセストークンが期限切れ、削除された、または権限が制限されている場合です。

Before(エラーが起きるコード):

# 以前のトークンで認証済み
$ docker login
Username: <your-username>
Password: <expired-token>
# 後日、403または401エラーが発生

After(修正後):

# 新しいトークンを生成してログイン(Docker Hubの場合)
# Docker Hub の Account Settings > Security > New Access Token で新規生成
$ docker logout  # 既存認証を削除
$ docker login
Username: <your-username>
Password: <new-access-token>
Login Succeeded

# AWS ECRの場合
$ aws ecr get-login-password --region <your-region> | docker login --username AWS --password-stdin <your-account-id>.dkr.ecr.<your-region>.amazonaws.com

原因4:docker-compose.ymlで間違ったレジストリーURLを指定している

イメージ名またはレジストリーURLのスペルミスや、ホスト名の不一致がある場合です。存在しないレジストリーやアクセス権限がないレジストリーへのアクセスで401が返されます。

Before(エラーが起きるコード):

version: '3.8'
services:
  app:
    # URLが正しくない、またはアクセス権限がないレジストリー
    image: myregisty.azurecr.io/myapp:latest  # typo

After(修正後):

version: '3.8'
services:
  app:
    # 正しいレジストリーURLを指定
    image: myregistry.azurecr.io/myapp:latest

原因5:マルチレジストリー構成で認証スコープが不足している

複数のプライベートレジストリーを使用する場合、各レジストリーに対して別々にdocker loginする必要があります。一つのレジストリーにのみログインしていると、他のレジストリーへのアクセスで401が発生します。

Before(エラーが起きるコード):

version: '3.8'
services:
  app:
    image: registry1.example.com/myapp:latest
  worker:
    # registry2への認証がない
    image: registry2.example.com/myworker:latest
$ docker login registry1.example.com
# registry2には認証していない
$ docker-compose up
# registry2のイメージpullで401エラー

After(修正後):

# 両方のレジストリーに認証
$ docker login registry1.example.com
$ docker login registry2.example.com
$ docker-compose up

Docker Compose固有の注意点

AWS ECR(Elastic Container Registry)での認証

ECRはAWS IAM認証を使用するため、従来のdocker loginでは対応できません。aws ecr get-login-passwordコマンドで一時的な認証トークンを取得する必要があります。

# ECR認証(12時間有効なトークンを生成)
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin <your-account-id>.dkr.ecr.ap-northeast-1.amazonaws.com

# 認証後、docker-composeでECRイメージを参照可能
$ docker-compose up

Azure Container Registry(ACR)での認証

ACRはサービスプリンシパルまたはアクセスキーでの認証が一般的です。

$ az acr login --name <your-acr-name>
# または
$ docker login <your-acr-name>.azurecr.io -u <your-username> -p <your-password>

プライベートDockerレジストリーでの認証

自社ホストのプライベートレジストリーを使用する場合、レジストリーがHTTPSではなくHTTPで動作している場合があります。その場合はdaemon.jsonでレジストリーをinsecureなものとして指定する必要があります。

{
  "insecure-registries": ["myregistry.local:5000"]
}

.dockerconfigjsonの活用

Kubernetesへのデプロイメント前にDocker Compose で動作確認する場合、設定ファイルの一貫性を保つことが重要です。

# ~/.docker/config.jsonが正しく設定されているか確認
$ test -f ~/.docker/config.json && echo "Config file exists" || echo "Missing config file"

それでも解決しない場合

デバッグログを有効化

Docker Composeのデバッグモードで詳細なエラー情報を確認できます。

$ DOCKER_CONTENT_TRUST_DEBUG=1 docker-compose up

レジストリー接続テスト

curlコマンドで認証状態を直接テストします。

# Docker Hubへの接続テスト(認証なし)
$ curl -i https://index.docker.io/v2/library/ubuntu/manifests/latest
# 401が返される場合は認証情報が必要

# 認証後のテスト(Bearer tokenを使用)
$ TOKEN=$(curl -s -u <username>:<password> "https://auth.docker.io/v2/token?service=registry.docker.io&scope=repository:library/ubuntu:pull" | jq -r '.token')
$ curl -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/library/ubuntu/manifests/latest

ログファイルの確認

Dockerデーモンログを確認します。

# Linux(systemd利用)
$ journalctl -u docker --no-pager | tail -50

# macOS(Docker Desktop)
$ log stream --predicate 'process == "com.docker.vmnetd"' --level debug

公式ドキュメント

  • Docker公式ドキュメント:https://docs.docker.com/engine/reference/commandline/login/
  • Docker Compose認証:https://docs.docker.com/compose/compose-file/compose-file-v3/#image
  • AWS ECR認証:https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/getting-started-cli.html

コミュニティリソース

  • Docker Community Forums:https://forums.docker.com/
  • GitHub Issues(docker/compose):https://github.com/docker/compose/issues

免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアの仕様は予告なく変更されることがあります。最新の情報は各ツールの公式サポートページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。