プロキシが必要な環境で、WSL2にDockerをインストールしてDevContainerを利用する
インターネットに出るのにプロキシが必要な環境で、WSL2にDockerをインストールしてDevContainerとして利用しようとしたのですが、嵌りどころが多かったので本記事に残します。
なお、Docker Desktopだと、Windowsのプロキシ設定を見てよきに計らってくれているのか、特に気にすること無く使えました。
このメモは、なんらかの理由でDocker Desktopが使えない&Rancher Desktopもプロキシ周りがよくわからんといった人向けのものになります。
WSL2へのDockerのインストール
WSL2でデフォルトでインストールされるUbuntuで試しました。
Dockerのインストールは公式サイトのUbuntuでの手順に沿うだけです。
「Install using the convenience script」に記載の手順で実施します。
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
何も設定していないとsudo sh get-docker.sh
のapt-get update
部分でエラーになります。
+ sh -c apt-get update -qq >/dev/null
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/jammy/InRelease Cannot initiate the connection to archive.ubuntu.com:80 (2620:2d:4002:1::103). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2620:2d:4000:1::103). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2620:2d:4000:1::101). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2620:2d:4002:1::101). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2620:2d:4000:1::102). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2620:2d:4002:1::102). - connect (101: Network is unreachable) Could not connect to archive.ubuntu.com:80 (185.125.190.81), connection timed out Could not connect to archive.ubuntu.com:80 (91.189.91.82), connection timed out Could not connect to archive.ubuntu.com:80 (91.189.91.83), connection timed out Could not connect to archive.ubuntu.com:80 (185.125.190.82), connection timed out Could not connect to archive.ubuntu.com:80 (91.189.91.81), connection timed out Could not connect to archive.ubuntu.com:80 (185.125.190.83), connection timed out
...
apt-get
でインターネットに接続するためなので、apt-get
でプロキシを経由するように、/etc/apt/apt.conf
を作成して設定します。
後述の/etc/environment
に、http_proxy
とhttps_proxy
を設定することで回避できるので、/etc/apt/apt.conf
側に設定しなくても大丈夫でした。
Acquire::http::Proxy "http://proxy.example.com:3128";
Acquire::https::Proxy "http://proxy.example.com:3128";
これでapt-get
の部分は問題なく動作しますが、その後のcurl
でまたエラーとなります。
+ sh -c curl -fsSL "https://download.docker.com/linux/ubuntu/gpg" -o /etc/apt/keyrings/docker.asc
curl: (28) Failed to connect to download.docker.com port 443 after 278686 ms: Connection timed out
Ubuntuをインストールした際に作成したアカウントは、Windows上のプロキシの設定を引き継ぐ(環境変数に設定してくれる)のですが、他のユーザには設定されません。
そのため、sudo
で実行すると、プロキシの設定がなされていなくて、このようなエラーとなります。
全ユーザに設定されるように /etc/environment
にプロキシ周りの環境変数を追記することで回避します。
HTTP_PROXY="http://proxy.example.com:3128"
HTTPS_PROXY="http://proxy.example.com:3128"
NO_PROXY="localhost,127.0.0.1,::1"
http_proxy="http://proxy.example.com:3128"
https_proxy="http://proxy.example.com:3128"
no_proxy="localhost,127.0.0.1,::1"
環境変数ですが、大文字小文字で区別されるのと、ツール/ライブラリ等によって大文字/小文字のどちらの環境変数を参照するのか異なるので、両方設定しておく形となります。
Dockerでのコンテナ実行
Dockerでのコンテナ実行でも、イメージの取得などで外部と通信する際にプロキシの設定が必要になります。
sudo docker run hello-world
などとした際に、プロキシが設定されていないと、下記のようなエラーになります。
$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded (Client.Timeout exceeded while awaiting headers).
See 'docker run --help'.
/etc/systemd/system/docker.service.d/http-proxy.conf
を作成して、Dockerが利用するプロキシを設定します。
ディレクトリ自体も無いので、mkdir -p /etc/systemd/system/docker.service.d
などでディレクトリを作ったうえでファイルを作成します。
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:3128"
Environment="HTTPS_PROXY=http://proxy.example.com:3128"
Environment="NO_PROXY=localhost,127.0.0.1,::1"
Environment="http_proxy=http://proxy.example.com:3128"
Environment="https_proxy=http://proxy.example.com:3128"
Environment="no_proxy=localhost,127.0.0.1,::1"
設定後はDockerのサービスを再起動します。
sudo systemctl daemon-reload
sudo systemctl restart docker
VSCodeを実行するユーザにdocker実行権限を追加
DevContainerを実行するユーザに権限がない状態で、VSCodeのDevContainerを起動すると、「Current user does not have permission to run 'docker'.」といったエラーダイアログが表示されます。
下記のような形で、dockerグループに追加します。
sudo usermod -aG docker <実行ユーザ>
Dockerfileでビルド時の設定
Dockerfile内で何かをインストールするような場合にも、プロキシが必要となってきます。
docker-compose.yml
でbuild
時のargs
として、環境変数の値を設定しておき、それをDockerfile内で参照、環境変数に設定します。
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
HTTP_PROXY: ${HTTP_PROXY}
HTTPS_PROXY: ${HTTPS_PROXY}
NO_PROXY: ${NO_PROXY}
ARG HTTP_PROXY
ENV HTTP_PROXY=${HTTP_PROXY}
ENV http_proxy=${HTTP_PROXY}
ARG HTTPS_PROXY
ENV HTTPS_PROXY=${HTTPS_PROXY}
ENV https_proxy=${HTTPS_PROXY}
ARG NO_PROXY
ENV NO_PROXY=${NO_PROXY}
ENV no_proxy=${NO_PROXY}
DevContainerでのコンテナ上でのプロキシ設定
実行したコンテナに自動的にプロキシの設定が引き継がれるといったことは無いようです。
そのため、DevContainerで起動したコンテナ上で、インターネットに接続するような処理(npm install
とか)を実行した際に問題になります。
.devcontainer\devcontainer.json
で、プロキシの設定を引き継ぐように設定します。
"containerEnv": {
"HTTP_PROXY": "${localEnv:HTTP_PROXY}",
"HTTPS_PROXY": "${localEnv:HTTPS_PROXY}",
"NO_PROXY": "${localEnv:NO_PROXY}",
"http_proxy": "${localEnv:HTTP_PROXY}",
"https_proxy": "${localEnv:HTTPS_PROXY}",
"no_proxy": "${localEnv:NO_PROXY}"
},
これで一通りのことができるようになりました。
Discussion