![プロキシ環境でdocker pullがうまくいかないときに試すこと](https://images.ctfassets.net/ct0aopd36mqt/wp-thumbnail-d86ef22d4bf19f60f04f31e2580efc61/ef882535a1191a4a0f19eb8a64048b2a/docker-eyecatch.png)
プロキシ環境でdocker pullがうまくいかないときに試すこと
お疲れさまです。とーちです。
みなさんは社内ネットワークなどのプロキシ環境でDockerを使用していますか?最近、プロキシ環境下でコンテナイメージをpullしようとして少し手こずったので、その解決方法を共有したいと思います。
発生した問題
今回、プロキシのある環境でコンテナイメージをpullしようとしたところ、失敗してしまいました。
環境情報
今回の環境はざっくり書くとこんな感じです。(だいぶ端折って書いてます)
なお、OSは Ubuntu 24.04
を使ってます。
またOSには以下のプロキシ関連の環境変数を設定していました。
- http_proxy:HTTP接続用プロキシ設定
- https_proxy:HTTPS接続用プロキシ設定
- no_proxy:プロキシを使用しないホストの指定
ちなみに、Ubuntuでは環境変数を設定する場所として、代表的なものとしては以下の2種類があります。
- /etc/environment:全ユーザーに適用したい場合
- ~/.profile:特定のユーザーにのみ適用したい場合
今回は/etc/environment
に上記の環境変数を設定していました。
この状態でdocker pull
を試みたところ、pullができませんでした。エラーメッセージの内容は今回の環境固有のものだったのですが、エラーメッセージからはプロキシ経由で通信していないことがわかりました
なぜ/etc/environmentの設定が効かないのか?
結論から言うと、dockerのコマンドはクライアントとして動作しており、実際のpull動作を行うのはdockerデーモンだからです。
こちらの記事に記載されている図が分かりやすいのですが、Docker CLIとDocker daemonの関係は以下のようになっています。
User → docker CLI → Unix Socket → Docker daemon
そしてコンテナイメージのpullを実際に行うのはDocker daemonです。Docker daemonはOSのsystemdによりデーモンとして管理されています。そのため、Dockerデーモンは/etc/environmentを直接読み込みません。結果としてDockerデーモンにプロキシ設定が伝わらないというわけです。
正しい設定方法
ではdokcer CLIでプロキシ設定を行うためにはどうしたらいいでしょうか?これはsystemd側の設定に環境変数を指定してあげればよいということになります。
Dockerの公式ドキュメントにその方法が載っています。
具体的には以下のようなファイルを作ります
# ディレクトリの作成
sudo mkdir -p /etc/systemd/system/docker.service.d
# http-proxy.confの作成
tee /etc/systemd/system/docker.service.d/http-proxy.conf << EOF
[Service]
Environment="HTTP_PROXY=<プロキシURL>"
Environment="HTTPS_PROXY=<プロキシURL>"
EOF
設定ファイルを作ったあとは以下のコマンドでリロードしましょう
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl status docker
さてこれでOKといきたいところですが、この設定だけだと実はdocker buildでプロキシを使う設定になっていません
2. Docker Buildのプロキシ設定
Docker buildのプロキシ設定は別途必要です。なぜなら、buildはコンテナ内で実行されるコマンドだからです。
以下の簡単なDockerfileで動作確認してみましょう
FROM ubuntu:22.04
RUN apt-get update
このままビルドすると以下のようなエラーが発生します:
docker build --progress=plain -t proxy-test .
<中略>
#2 ERROR: failed to copy: httpReadSeeker: failed open: unexpected status code https://registry-1.docker.io/v2/library/ubuntu/blobs/sha256:a24be041d9576937f62435f8564c2ca6e429d2760537b04c50ca50adb0c6d212: 500 Internal Server Error
------
> [internal] load metadata for docker.io/library/ubuntu:22.04:
------
Dockerfile:1
--------------------
1 | >>> FROM ubuntu:22.04
2 | RUN apt-get update
3 |
--------------------
ERROR: failed to solve: ubuntu:22.04: failed to resolve source metadata for docker.io/library/ubuntu:22.04: failed to copy: httpReadSeeker: failed open: unexpected status code https://registry-1.docker.io/v2/library/ubuntu/blobs/sha256:a24be041d9576937f62435f8564c2ca6e429d2760537b04c50ca50adb0c6d212: 500 Internal Server Error
これを解決するには、~/.docker/config.json
に以下の設定を追加します
こちらもDocker公式ドキュメントに記載があります。
{
"proxies": {
"default": {
"httpProxy": "<プロキシURL>",
"httpsProxy": "<プロキシURL>"
}
}
}
上記の設定をしたあと、一度ログインし直すとbuildにおいてもプロキシ設定が使用されるようになります。
# docker build --progress=plain -t proxy-test .
#0 building with "default" instance using docker driver
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 74B done
#1 DONE 0.0s
#2 [internal] load metadata for docker.io/library/ubuntu:22.04
#2 DONE 25.6s
#3 [internal] load .dockerignore
#3 transferring context: 2B done
#3 DONE 0.0s
#4 [1/2] FROM docker.io/library/ubuntu:22.04@sha256:ed1544e454989078f5dec1bfdabd8c5cc9c48e0705d07b678ab6ae3fb61952d2
#4 resolve docker.io/library/ubuntu:22.04@sha256:ed1544e454989078f5dec1bfdabd8c5cc9c48e0705d07b678ab6ae3fb61952d2 0.0s done
#4 sha256:9cb31e2e37eab1bff50f727e979fcacb509e225fb853433a6fe21d2fb34e6305 0B / 29.54MB 0.1s
<以後省略>
まとめ
プロキシ環境でDockerを使用する場合は、以下の2点の設定が必要というお話でした。
- Docker Daemon用のプロキシ設定(systemd設定)
- Docker Build用のプロキシ設定(config.json)
以上、とーちでした。