こんにちは、たびとです。
Docker 初心者の頃、既存の WSL2/Ubuntu 環境に Docker Desktop for Windows をインストールし、Docker コンテナを構築するといったよくある使い方をしていました。
しかし、業務で使い込んでいるうちに思わぬ事故に何度も遭遇しました。このままでは実用には耐えられないなと思い、WSL2/Ubuntu 環境に直接 Dokcer をインストールしてみました。
- この記事の対象者
- Docker Desktop for Windowsを諦めた理由
- WSL2/Ubuntu の準備 (20.04 or 22.04)
- Ubuntu 版 Docker のインストール
- Dockerインストール後の設定
- まとめ
この記事の対象者
- WSL2/Linux の構築経験があり、最低限の Linux コマンドを知っている人
- 業務で、Docker Desktop for Windows を使っている人、これから使いたい人
- 自作で Dockerfile や docker-compose.yml を作って、ビルドを繰り返す人
- Docker Desktop for Windows でディスク枯渇を経験し、何度も掃除するのが面倒だと思った人
Docker Desktop for Windowsを諦めた理由
AIのPoC開発で、Webサーバにnginx、APサーバにASP.NET Core(gRPC)、DBサーバにPostgreSQL、バッチサーバに.NET Core(Consoleアプリ)の環境を構成することになりました。
Docker Desktop for Windows採用
最初は VMware や Hyper-V に構築していましたが、GUI だとディスクサイズが巨大になるので、WSL2/Ubuntu で作り直したりしていました。
ひとりで構築から開発までを担当していたので、サーバ構築を自動化してアプリ開発に集中したいと思い、流行りの Docker を採用してみました。 しかし、Docker 初心者のときは、Dockerfile と docker-compose.yml の違いも理解できず、ASP.NET Core や .NET Core のビルド、 ビルドに必要なライブラリのコンパイルをどのように Dockerfile に記述すれば良いのか、わからないことが多過ぎて、苦労の連続でした。
トラブル連発
そうやってコンテナ作りに試行錯誤していると、あるとき、Cドライブが枯渇してしまいビルドができなくなりました。 Docker 関連のイメージなど不要なモノは、こまめに削除していたので、何が領域を圧迫しているのか理解できず、原因究明に苦労することになりました。
詳しい方はご存じだと思いますが、Docker Desktop for Windows はイメージなどを削除してもディスク領域を解放しないという仕様(というかトラップ)があります。 当時は知る由もなく、散々悩んだ挙句に何とか原因を突き止めました。
また、Docker Desktop for Windows のアップデートが何度かあり、毎回軽い気持ちでアップデートしていました。 あるとき、アップデートの最中にクラッシュして、Docker Desktop for Windows が起動しなくなりました。 こうなっては、アンインストールしか方法はありません。データベースをコンテナ内に置いていたため、データも併せて全滅しました。
ただ、もしもに備えて複数の Docker 環境を作っていたため、データのバックアップがあったことは、 不幸中の幸いでした。この後、コンテナの外にデータを配置したのは言うまでもありません。
このクラッシュ現象には何度も遭遇しましたが、複数端末の全滅ではなく、特定の端末がダメになりました(ある一台に集中した訳ではありません)。ダメなときは、アンインストールして再インストールしてもダメでした。古い版数を使うか、次のアップデートを待つしかありません。クラッシュ時のリリースは割と早かったと記憶しています。
そして Docker Desktop for Windows を諦めた
このようなトラブル情報は、読んだ限りの Docker 本にもなく、インターネット上にも情報が少なかったので、Dokcer 初心者のたびとは散々な目に会いました。 今後、このような困った人が減るように記録を残しておきます。
よって、学習向けであれば Docker Desktop for Windows は最高に便利ですが、業務レベルでは実用に耐えれないなという認識です。 ただし、たびとが使っていたのは Docker Desktop for Windows V3 の時代だったので、現在のV4になって改善されている可能性はあります。
ただし、Docker Desktop for Windows を Linux コンテナとしては諦めましたが、アンインストールはせずに「Switch to Windows containers...」に切り替えて Windows コンテナとして利用しています。
WSL2/Ubuntu の準備 (20.04 or 22.04)
Windows Store から 好きな Ubuntu をインストールしてください。
インストール後、必ず wsl
コマンドで、VERSIONが2であることを確認してください。
WSL2でない場合、WSL2に切り替えてください。
PS C:\> wsl -l -v NAME STATE VERSION * Ubuntu-20.04 Running 2
Windows 11 または Windows 10 バージョン 2004 以降の場合、
wsl --install
コマンドで WSL2 の Ubuntu を簡単にインストールすることができます。
※ ただし、既に Linux をインストールしている場合、オプションが必要です。
詳細は、以下の記事を参考にしてください。
Ubuntu 版 Docker のインストール
それでは、WSL2 Ubuntu に Docker をインストールしていきます。
アップデート確認
apt update
コマンドを確認後、アップデートがあれば apt upgrade
してください。
$ sudo apt upadte $ sudo apt upgrade
Dockerに必要なパッケージのインストール
Dokcerに必要なパッケージをインストールします。
$ sudo apt install -y apt-transport-https ca-certificates gnupg-agent software-properties-common
Dockerの公式GPGキーの取得と確認を行います。
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - $ sudo apt-key fingerprint 0EBFCD88 pub rsa4096 2017-02-22 [SCEA] 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 uid [ unknown] Docker Release (CE deb) <docker@docker.com> sub rsa4096 2017-02-22 [S]
リポジトリの設定を行います。
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
Dockerのインストール
Dockerをインストールします。
$ sudo apt update $ sudo apt install -y docker-ce docker-ce-cli containerd.io $ docker --version Docker version 20.10.8, build 3967b7d
最新版 docker-compose のインストール
apt でインストールした docker-compose は、バージョンが古くてビルドができない場合があるため、 最新版のdocker-compose を同じかどうかを確認します。
docker-compose バージョン確認
docker-compose のバージョンを確認します。
$ apt list | grep docker-compose docker-compose/focal 1.25.0-1 all
docker-composeの版数が同じであれば、そのままインストールします。
$ sudo apt install docker-compose
$ docker-compose --version
既存の docker-compose 削除
apt
からインストールした場合、remove オプションで削除します。
$ sudo apt remove docker-compose
直接インストールした場合、 本体はリネームし、シンボリックリンクのみを削除します。 版数は、自分の環境に合わせて変更してください。
$ sudo mv /usr/local/bin/docker-compose /usr/local/bin/docker-compose.1.29.2 $ sudo rm /usr/bin/docker-compose
docker-compose V2 インストール
最新版の docker-compose v2 を GitHub で確認します。
現時点の最新版 v2.10.0 を指定します。
このコマンドは上書き可能なので、最新リリース後に download/v数値
を最新の数値に変更して実行してください。
$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.10.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/libexec/docker/cli-plugins/docker-compose % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 100 24.5M 100 24.5M 0 0 4042k 0 0:00:06 0:00:06 --:--:-- 5628k
次に、シンボリックを作っていきます。こちらは一度限りです。
$ sudo chmod +x /usr/libexec/docker/cli-plugins/docker-compose $ sudo ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/bin/docker-compose
正常にインストールできたことを確認します。
$ docker-compose --version Docker Compose version v2.10.0
プロキシ環境の場合、環境変数にプロキシを設定していても、curlが失敗することがありました。
もし、失敗する場合、proxy オプション -x [http://proxy-server](http://proxy-server/):port
を付けて実行してみてください。
プロキシ設定(プロキシ環境のみ)
エディタで/etc/default/dockerを開きます。
$ sudo vi /etc/default/docker
最終行にプロキシの情報を追加します。
# Set Proxy export http_proxy='http://<user_id>:<password>@<host>:<port>' export HTTP_PROXY="${http_proxy}" export https_proxy="${http_proxy}" export HTTPS_PROXY="${http_proxy}" export no_proxy='127.0.0.1,localhost' export NO_PROXY="${no_proxy}"
認証プロキシでユーザIDやパスワードに @ が含まれる場合、
URLエンコードする必要があります。
@
は%40
に置き換え てください。
(例)tabito@xxxxx.com → tabito%40xxxxx.com
iptable をレガシーへ切り替える
iptable の設定がレガシーになっていないと、Docker サービスが起動したように見えて、 実際にステータスを確認すると起動できていない現象が発生します。
$ sudo service docker start * Starting Docker: docker [ OK ] $ service docker status * Docker is not running ※ 起動していない
個人的に Ubuntu 20.04 は大丈夫で、22.04 で発生しました。 しかし、環境によっては 20.04 でも発生するようです。
強制実行
面倒くさい人は、以下のコマンドを実行することで切り替えることができます。
$ sudo update-alternatives --set iptables /usr/sbin/iptables-legacy $ sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
確認しながら切り替える
以下のコマンドで iptable の状況を確認・切り替えることができます。 レガシーになっていれば、そのまま Enter キーを押して終了します。 レガシーになっていなければ、レガシーの番号を指定して切り替えてください。
例はレガシーのため、そのまま Enter キーを押して終了します。
$ sudo update-alternatives --config iptables There are 2 choices for the alternative iptables (providing /usr/sbin/iptables). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/sbin/iptables-legacy 20 auto mode 1 /usr/sbin/iptables-legacy 20 manual mode 2 /usr/sbin/iptables-nft 10 manual mode Press <enter> to keep the current choice[*], or type selection number:
同様に IPv6 用も変更します。 例はレガシーのため、そのまま Enter キーを押して終了します。
$ sudo update-alternatives --config ip6tables There are 2 choices for the alternative ip6tables (providing /usr/sbin/ip6tables). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/sbin/ip6tables-legacy 20 auto mode 1 /usr/sbin/ip6tables-legacy 20 manual mode 2 /usr/sbin/ip6tables-nft 10 manual mode Press <enter> to keep the current choice[*], or type selection number:
サービス起動
Dockerサービスを起動します。
$ sudo service docker start
Dockerサービスが正常に動作していることを確認します。
$ service docker status
* Docker is running
プロキシ確認(プロキシ環境のみ)
docker info
コマンドの実行結果にプロキシ情報が表示されることを確認します。
$ docker info | grep -i proxy HTTP Proxy: http://<user_id>:<password>@<host>:<port> HTTPS Proxy: http://<user_id>:<password>@<host>:<port> No Proxy: 127.0.0.1,localhost
動作確認
お決まりの hello-world を実行します。ここでは、dockerコマンドにsudoを付ける必要があります。
$ sudo docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 2db29710123e: Pull complete Digest: sha256:9ade9cc2e26189a19c2e8854b9c8f1e14829b51c55a630ee675a5a9540ef6ccf Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
Dockerインストール後の設定
Dockerを便利に使うためには、インストール後にも設定が必要となります。
sudoを付けないでdockerコマンドを使う
dockerコマンドにはsudoが必要になります。セキュリティ等の理由がなければ、sudoを付けなくても動作するように変更しましょう。
まずは、dockerグループを確認します。
$ cat /etc/group|grep docker docker:x:999:
dockerグループに現在のユーザを参加させます。
$ sudo usermod -aG docker $USER
この設定を有効にするために、一度ログアウトします。
$ logout
Dockerコンテナ内からインターネット環境にアクセスする
Dockerコンテナ内からインターネットにアクセスするため、daemon.jsonファイルを新規に作成します。
$ sudo vi /etc/docker/daemon.json
Google Public DNSを設定します。
{ "dns": ["8.8.8.8","8.8.4.4"] }
DNS設定を有効にするため、Dockerサービスを再起動します。
$ sudo service docker restart * Stopping Docker: docker [ OK ] * Starting Docker: docker [ OK ]
プロキシ設定(プロキシ環境のみ)
エディタで ~/.docker/config.json ファイルを開きます。
$ vi ~/.docker/config.json
"proxies" 以下の行を追加します。
ただし、"auths" と "proxies" の区切りにカンマ,
が必要となるため、忘れずに追加してください。
{ "auths": { "https://index.docker.io/v1/": { "auth": "ZmprdXNhbm86MDA0ODMxNzhARko=" } }, ※ 行末のカンマを忘れずに付けてください! "proxies": { "default": { "httpProxy": "http://<user_id>:<password>@<host>:<port>", "httpsProxy": "http://<user_id>:<password>@<host>:<port>", "noProxy": "127.0.0.1,localhost" } } }
インターネットへの接続確認
インターネットの接続を確認するため、alpine Linuxをインストールし、akpでアップデートできるかを確認します。
$ docker run -it alpine /bin/ash Unable to find image 'alpine:latest' locally latest: Pulling from library/alpine a0d0a0d46f8b: Pull complete Digest: sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a Status: Downloaded newer image for alpine:latest / # apk update fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz v3.14.2-68-gbf3cc5c973 [https://dl-cdn.alpinelinux.org/alpine/v3.14/main] v3.14.2-67-gf34feae70e [https://dl-cdn.alpinelinux.org/alpine/v3.14/community] OK: 14938 distinct packages available
プロキシ確認(プロキシ環境のみ)
プロキシが反映されていることを確認します。
/ # printenv | grep -i proxy HTTPS_PROXY=http://<user_id>:<password>@<host>:<port> HTTP_PROXY=http://<user_id>:<password>@<host>:<port> NO_PROXY=127.0.0.1,localhost http_proxy=http://<user_id>:<password>@<host>:<port> https_proxy=http://<user_id>:<password>@<host>:<port> no_proxy=127.0.0.1,localhost / #
Docker Hubにログイン
dokcer login
コマンドでDocker Hubへログインしてください。
$ docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: ユーザ名 Password: WARNING! Your password will be stored unencrypted in /home/tabito/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
ログインしなくても、しばらくはイメージをダウンロードできますが、そのうちエラーが表示されます。 アカウントを未登録の方は、Docker Hub で無料アカウントを作成してください。
Windows起動時にdockerサービスが自動起動するようにする
ここでは、タスクスケジューラによる設定を記載します。
- タスクスケジューラを起動します。
- 「タスクの作成」をクリックし、全般タブ(デフォルト)を表示します。
- 名前(M)は「WSL2 Docker Service」、説明(D)に「WSL2(Ubuntu-20.04 Docker Serviceの自動起動」等、適当にラベリングしてください。
- 「ユーザがログオンしているかどうかにかかわらず実行する(W)」をチェックします。
- 「パスワードを保存しない(P)」をチェックします。
- 「トリガー」タブを選択し、「新規(N)」ボタンをクリックします。
- タスクの開始(G)で「スタートアップ時」を選択し、OKボタンをクリックします。
- 「操作」タブを選択し、「新規(N)」ボタンをクリックします。
- プログラム/スクリプト(P)に「wsl.exe」、引数の追加(オプション)(A)に「-u root — service docker start」と設定します。
- タスクを保存し、タスクスケジューラライブラリから「WSL2 Docker Service」を探して右クリックし、「実行する(R)」を選択します。
- WSL2 Ubuntu上で、「service docker status」で状態を確認します。起動(Docker is running)していればOKです。
まとめ
Docker Desktop for Windows V3とWSL2/Ubuntuの組合せで散々な目に会ったので、WSL2/Ubuntuに直接Dockerをインストールする方法を掲載しました。何かのお役に立てれば幸いです。
Docker Desktop for WindowsのようにGUIで管理したい方は、Portainerのインストールをお勧めします。 sabakunotabito.hatenablog.com
最後に参考サイトを掲載しておきます。
では、皆さん、よい旅を。
参考サイト
- Install Docker Engine on Ubuntu
- WSL2/Ubuntu に Docker をインストールする
- WSLのdocker daemonを自動起動させる
- プロキシーサーバー利用の設定 | Docker ドキュメント
- Proxy環境下のDockerトラブルシューティング - Qiita
- docker login — Docker-docs-ja 20.10 ドキュメント
- WSL2 (Ubuntu 20.04) + docker が動作しなかったことと解決策 - Qiita
アプリ開発者にお薦め
インフラ構築者にお薦め(CentOS ベース)