🐳

WSLもDocker Desktopも使わずにDockerをWindowsでやってみる

2024/02/04に公開

概要

この記事では、Windows上でDocker環境を作るための方法を説明します。
今回はDocker Desktopに代表されるGUI系Dokcer管理ツールは使わずに、Windowsコマンドプロンプト、PowerShellだけで実行できるようにします。

経緯

私はDockerの存在自体は知っていましたが、普段はJava開発やWebのフロント系を生業としているため、Eclipseやメモ帳だけで環境が完結できていました。
そんな中でも例えばセルフホスティングのツールを利用したいなとうっすらと思っていたのですが、最近のオープンソースはDockerで環境を作ることが前提、あるいはその方法しか書いていないことも多くあきらめてしまっていました。
ですが知ることを放置していても使いたいツールの代替手段が得られるわけでもないので、いいかげんDockerを始めてみることにしました。

ターゲット

  • Dockerがなんなのかわからないけど、とりあえず説明も聞かずにやってみたいと思ってる人
  • Linuxとかわかんないのでできれば触りたくない人
  • Docker Desktopが有償って聞いたから避けたい人(※個人や小規模の場合は無料です)
  • 代わりのGUIツールがあるといっても『他のサードパーティだってすぐ有償化するでしょ?』と懐疑的な人

こういった方向けですので、手順上の説明はしますが、結局Dockerがなんなのかの説明は一切しません。そういった文書は精錬された有志のドキュメントがZenn上にもたくさんありますので、そちらを探してみてください。

ゴール

  • Dockerのセットアップが完了し、Windows上で操作、管理できるようになること

通常の方法と何が異なるのか

通常はWSL(Windows Subsystem for Linux)やHyper-Vを利用してLinuxを仮想化し、その上にコンテナを用意しますが、今回の方法ではWindowsコンテナを利用します。
コンテナは各OSのカーネルに準拠して動作するため、コンテナが「Linuxベースなのか」「Windowsベースなのか」が大きく異なります。

したがって次のような問題点があります。
これらを踏まえて、「Windowsコンテナは避けるべきだ」とお考えになった方はDocker Desktopから導入する方法、あるいはWSLやはHyper-Vを利用したDockerの導入方法を試してみてください。
おそらく、Windowsコンテナを使用するよりも素直かもしれません。

今回の方法における問題点1

Docker Hub(イメージを配布しているサイト)上に掲載されている「Windowsコンテナ」に対応するイメージが少ないです。
https://hub.docker.com/search?q=&operating_system=windows
このリンクはDocker Hub上に登録されているWindowsコンテナでDockerを実行した場合に対応しているDockerイメージの一覧です。

たとえばRust言語を利用するためのイメージ。
https://hub.docker.com/_/rust
タグlatest(最新タグ)のOSはすべてlinux向けとなっています。

したがって読み込みをしようとするとno matching manifest for windows/amd64 10.0.22631 in the manifest list entries(windows/amd64のコンテナには対応していません)というエラーになります。

逆にPython言語を利用するためのイメージ。
https://hub.docker.com/_/python
タグlatestのOSにWindowsがあります。

ですのでPythonはWindowsコンテナで使用することができます。

もちろんDockerイメージ自体は作ることができますので、自身で作ってしまえば気にならないかもしれませんがいささか不便かもしれません。

今回の方法における問題点2

Windowsコンテナを前提とした記事が非常に少ないです。
MicrosoftやDockerのドキュメントに日本語で解説は乗っていますが、世間的にはLinuxコンテナを利用する手段を採用するのが一般的です。
またDocker Desktopの旧称は「Docker for Windows」だったりしたので、検索するのも苦労すると思います。
そのため、検索に頼ろうとするとシェルをWindowsコマンドに読み替える必要が出てきます。
また、Linuxでしか動かせないプログラムは当然使用できません。

いまどきのプログラマはLinuxになれている方も多いとは思いますが、わたしのようにWindowsを前提としたシステム開発ばかりに携わってきた場合はすこし苦労するかもしれません。

用意するもの

  • Docker Engine
    今回は「docker-25.0.2」を使用しています。
    移行の手順はリンク先を参考にして記載していますので、一度ご覧になっていただくのがいいかなと思います
  • Docker Compose v2
    今回は「v2.24.5」を使用しています。

Docker環境を作る

「コンテナー」を有効にする

まずは「Windowsの機能」を開きます。
コントロールパネルから開く方法もありますが、私はスタートメニューから検索するのをお勧めします。

ツリーから「コンテナー」を有効化します。
「OK」を押下すると再起動を促されるので、再起動しましょう。

Dockerを展開する

Docker Engineをダウンロードします。
「用意するもの」のリンク先内でも入手方法やダウンロードページの紹介はされていますが、いまのところ下記のURLから入手可能です。
https://download.docker.com/win/static/stable/x86_64/
ダウンロードしたファイルはDockerをインストールしたいフォルダで展開しましょう。
私は図のような配置をしました。

フォルダ配置
📂 . (例:D:\service\docker)
├── 📂docker-xx.x.x
│   ├── docker.exe
│   ├── dockerd.exe
│   └── docker-proxy.exe
│
└── (ここには操作するバッチなどを置く予定)

Dockerをインストールする

設定ファイルとなるデーモンファイル、そしてサービスをインストール/アンインストールするバッチを「ここには操作するバッチなどを置く予定」としている場所に配置します。

daemon.json

daemon.json
{
    "group": "xxxxxxx"
}

daemon.jsonはDocker Engineの設定ファイルです。
内容を修正するたびサービスの再起動が必要ですが、このように外部化しておくと設定自体をバックアップしやすいので作成しました。

group

管理者実行の必要がないアカウント/グループを指定することができる設定です。
Windowsの場合、groupはローカルユーザーアカウント名を指定できます。
通常は把握しているかもしれませんが、分からない場合はwhoamiコマンドで確認することができます。

上記の場合、「desktop-■■■■■■■」がグループ名、「admin」がユーザー名なのでdaemon.jsonは次の通り設定します。

daemon.json
{
    "group": "admin"
}

その他の設定方法については下記を参考にしてください。
https://docs.docker.jp/engine/reference/commandline/dockerd.html#daemon-configuration-file

install.bat, uninstall.bat
install.bat
@echo off
pushd %~dp0

rem ディレクトリパスは適時修正
set SERVICE_DIR=%~dp0\docker-xx.x.x
set DAEMON_FILE=%~dp0\daemon.json

%SERVICE_DIR%\dockerd.exe --register-service --config-file %DAEMON_FILE%

popd
exit /b
uninstall.bat
@echo off
pushd %~dp0

rem ディレクトリパスは適時修正
set SERVICE_DIR=%~dp0\docker-xx.x.x

%SERVICE_DIR%\dockerd.exe --unregister-service

popd
exit /b

あとはinstall.batを管理者で実行すれば「Docker Engine」がサービスに登録されます。

初期状態ではDockerは起動していないので、起動しておきましょう。

これでDockerセットアップは完了です。

Hello Worldしてみる

正常に動作が可能か確認しましょう。

バージョンを確認する

ターミナルでdockerをインストールしたディレクトリへ移動し、下記のコマンドでバージョンを確認します。

.\docker.exe version

バージョン情報が正常に表示されれば問題ありません。

hello-worldコンテナを実行する

バージョンを確認出来たらdockerは実行できる状態にあると思われます。
下記のコマンドでhello-worldコンテナを実行してみましょう。

.\docker.exe run hello-world

初めて実行する場合はhello-worldコンテナのダウンロードが行われるのでしばらく待ちます。
Hello from Docker!が表示されて正常終了すれば、セットアップが正常に行われたといえます。

Dockerイメージを作成して実行する

Dockerイメージを作って実行してみましょう。
ここではDocker Hubから、PowershellがセットアップされているWindowsサーバーコンテナを利用してログインユーザーを表示するイメージを作ってみます。
https://hub.docker.com/_/microsoft-powershell

dockerfile
FROM mcr.microsoft.com/powershell:windowsservercore-ltsc2022

# powershellイメージでは「C:\Program Files\PowerShell\pwsh.exe」がpowershellの実行ファイル
SHELL ["pwsh.exe", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

# test用のユーザーを作成
RUN net user testuser /ADD
RUN NET LOCALGROUP Administrators /add testuser

USER testuser

CMD whoami

Dockerfileの作成方法については省きますが、dockerfileを適当なフォルダに入れてイメージ化します。
今回はF:\docker\nginxに放り込み、次のコマンドを実行しました。

cd D:\service\docker
.\docker build F:\docker\nginx -t example


Successfully tagged example:latestが表示されればイメージ化の完了です。
続いて次を実行しましょう。

.\docker run example

ユーザー名が表示されれば成功です。

Docker Composeを追加する(CLIプラグインの導入方法)

Docker Composeの導入方法を説明しますが、おそらく他のCLIプラグインも同様かと思います。

Docker Composeを展開する

まずは「用意するもの」からDocker Composeをダウンロードします。
GitHubなのでReleasesから最新のDocker Composeを入手することができます。
https://github.com/docker/compose/releases
たくさんファイルがあるかと思いますが今回使用するのはdocker-compose-windows-x86_64.exeです。

次にC:\ProgramData\dockerディレクトリにcli-pluginsフォルダを作成してください。
C:\ProgramData\dockerはDockerで作成したコンテナを管理しているデータフォルダで、C:\ProgramData\docker\cli-pluginsはCLIプラグインを格納するディレクトリです。
データフォルダ自体はinstall.batで呼び出しているdockerdのオプションでパスを設定すると保管場所を変更することはできますが、cli-pluginsフォルダの位置は変更できないようです

cli-pluginsフォルダを作成したらダウンロードしていたdocker-compose-windows-x86_64.exedocker-compose.exeにリネームしておきます。

この後、サービスを再起動すればDocker Composeの導入は完了です。

バージョンを確認する

ターミナルを開き、dockerをインストールしたディレクトリへ移動して下記のコマンドでバージョンを確認します。

.\docker.exe compose version

Docker Composeのバージョンが表示されたら導入できていることが確認できます。

ここでdocker: 'compose' is not a docker command.と表示される場合は、cli-pluginsフォルダにdocker-compose.exeという実行ファイルが存在していないことを示します。
以下を確認してみてください。

  • Docker Composeのバージョンはv2であるか
    古いバージョンでは.\docker.exe composeというオプションがありません。
    https://www.konosumi.net/entry/2023/02/26/142508
    v2.x.x以降のDocker Composeを利用しましょう
  • サービスの再起動はしたか
    C:\ProgramData\docker\cli-pluginsの適用はDocker Engineの再起動が必要なようです
  • C:\ProgramData\docker\cli-pluginsにDocker Composeを置いたか
    install.batでC:\ProgramData\dockerを移動したとしても、C:\ProgramData\docker\cli-pluginsディレクトリは移動することができません。
    ディレクトリパスが正しいか確認してください
  • docker-compose.exeにリネームしたか
    docker-compose-windows-x86_64.exeのままでは読み込んでくれません。リネームを舌か確認してください。

Dockerを環境変数PATHに登録する

ここで詳細な手順は記載しませんが、docker-xx.x.xを環境変数PATHに登録しておくとdockerでコマンド実行できるようになるので便利です。

私は環境変数を変更するのは避けたかったのでしませんでしたが、通常は登録するのがいいと思います。

アンインストールをする場合の操作

C:\ProgramData\dockerはシンボリックリンクでシステムに強く結びつくため、単純にDeleteボタンを押下すれば削除できるというわけではありません。
削除する場合は、Docker Engineサービスを停止し、先刻作成したuninstall.batを実行してください。
次に「Windowsの機能」から「コンテナー」を無効化し再起動。その後、下記コードを参考にPowershellを管理者実行することで、C:\ProgramData\Dockerを削除できます。
https://gist.github.com/nicolaskopp/de9fff4889d0ddf4c79da7ebc9e8b918

#take ownership of docker files
if (Test-Path "C:\ProgramData\Docker") { takeown.exe /F "C:\ProgramData\Docker" /R /A /D Y }
if (Test-Path "C:\ProgramData\Docker") { icacls "C:\ProgramData\Docker\" /T /C /grant Administrators:F }
#invoke cmd to delete docker files
cmd /c rmdir /s /q "C:\ProgramData\Docker"

C:\ProgramData\dockerはDocker Engineサービスを起動した段階で生成されます。
クリーンな状態でインストールをし直したい場合は、試してみるのもいいでしょう。

続編

https://zenn.dev/0_0/articles/5c1baf890cd646

参考資料

DockerDesktopやWSLでの方法なども含めて調査をしていたので今回は多め。
https://docs.docker.com/engine/install/binaries/
https://github.com/docker/compose
https://pswork.jp/docker/user-authorization/
https://taktak.jp/2022/07/23/4452/
https://docs.docker.jp/engine/reference/commandline/cli.html
https://vividcode.hatenablog.com/entry/mount-host-directory-as-data-volume-on-power-shell-with-pwd
https://zenn.dev/dozo/articles/8f8a5c51563e2e
https://qiita.com/zembutsu/items/6fb6eface38d62b3584d
https://level69.net/archives/31296
https://eng-blog.iij.ad.jp/archives/14205
https://qiita.com/baku2san/items/30a1e0fc68d190de9471
https://qiita.com/t_ngmn/items/ab8829e50687ff31b558
https://alctail.sakura.ne.jp/contents/pg/docker/kihon/#section2-1
https://emoshu.co.jp/blog/archives/16
https://qiita.com/irico/items/4677334879da859a7c24
https://qiita.com/rubytomato@github/items/eec2118e89ee9bd8d17a#dockerfileの作成
https://www.engineer-route.com/column/8786/
https://qiita.com/gentaro/items/7dec88e663f59b472de6
https://zenn.dev/ttani/articles/wsl2-docker-edit-root-user
https://zenn.dev/ttani/articles/wsl2-docker-setup
https://zenn.dev/fagai/articles/55c1b34172ca5a0bce09
https://zenn.dev/ktsu/articles/56c2c9732af3be
https://blog.jp.square-enix.com/iteng-blog/posts/00024-wsl2-docker-ce/
https://learn.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/container-storage
https://gist.github.com/nicolaskopp/de9fff4889d0ddf4c79da7ebc9e8b918
https://www.konosumi.net/entry/2023/02/26/142508
https://docs.docker.com/compose/install/linux
https://pswork.jp/docker/windows-2019-docker-install/
https://learn.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/container-storage
https://tkyonezu.com/docker-kubernetes/docker-compose-v2-0-0について/
https://docs.docker.com/engine/reference/commandline/dockerd/
https://qiita.com/IntenF/items/e35e0aee8527b16b164e
https://docs.docker.com/engine/install/linux-postinstall/
https://learn.microsoft.com/ja-jp/virtualization/windowscontainers/about/
https://qiita.com/ishibashi-futoshi/items/db807d64624f43be1be9
https://hub.docker.com//microsoft-powershell
https://learn.microsoft.com/ja-jp/virtualization/windowscontainers/manage-containers/container-security
https://learn.microsoft.com/ja-jp/virtualization/windowscontainers/manage-docker/manage-windows-dockerfile
https://hub.docker.com/
/microsoft-windows-server
https://blog.brains-tech.co.jp/windows-docker
https://atmarkit.itmedia.co.jp/ait/articles/1510/07/news021.html
https://github.com/moby/moby/issues/28585
https://y-ni-shi.hatenablog.com/entry/2022/01/03/135000
https://learn.microsoft.com/ja-jp/virtualization/windowscontainers/manage-containers/container-base-images
https://github.com/PowerShell/PowerShell-Docker/blob/master/release/7-3/nanoserver2022/docker/Dockerfile
https://github.com/docker-library/python/blob/master/3.12/windows/windowsservercore-ltsc2022/Dockerfile
https://qiita.com/suzuki-navi/items/cf07965bb59acf492db0

Discussion