🐳

プロキシが必要な環境で、WSL2にDockerをインストールしてDevContainerを利用する

2024/06/30に公開

インターネットに出るのにプロキシが必要な環境で、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.shapt-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_proxyhttps_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 にプロキシ周りの環境変数を追記することで回避します。

/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 などでディレクトリを作ったうえでファイルを作成します。

/etc/systemd/system/docker.service.d/http-proxy.conf
[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.ymlbuild時のargsとして、環境変数の値を設定しておき、それをDockerfile内で参照、環境変数に設定します。

docker-compose.yml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        HTTP_PROXY: ${HTTP_PROXY}
        HTTPS_PROXY: ${HTTPS_PROXY}
        NO_PROXY: ${NO_PROXY}
Dockerfile
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で、プロキシの設定を引き継ぐように設定します。

.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