メインコンテンツまでスキップ

Windows用Docker CLIを自前でビルドしてみた

· 約7分
moritalous

Dockerはサーバー側のDockerデーモンとクライアント側のDocker CLIで構成されています。Windows上でDocker環境を構築する場合は、Docker Desktopなどを使用しますが、裏側でWSL2上のDockerデーモンをWindowsのDocker CLIから操作しています。

Docker CLIのバイナリは個別には公開されていないと思いますが、GitHubに公開されているソースから自前でビルドしてみました。

概要
  • Docker CLIはソースコードがGitHubで公開されている
  • ビルドはとても簡単
  • 使い所は難しい

ビルド

環境構築

Docker CLIのビルドにはDocker環境が必要です。(なのでLinux環境が必要です) 簡単にLinux環境が構築できるmultipassを使用しました。

ヒント

multipassではDockerインストール済みの仮想環境をコマンド一つで構築できます。

multipass launch docker --name multipass-docker

仮想環境が作成できたらシェルでログインします。

multipass shell multipass-docker

ビルド手順

  1. ソースの取得

    git clone https://github.com/docker/cli.git
  2. ビルド

    cd cli
    docker buildx bake --set binary.platform=windows/amd64

以上です。簡単ですね。buildディレクトリにdocker-windows-amd64.exeが生成されます。

ヒント

platformを変更することで、arm64版バイナリ(windows/arm64)やmac版バイナリ(darwin/amd64darwin/arm64)も生成できるようです。

Windowsへバイナリのコピー

Linux環境からログアウトします。

exit

transferコマンドで仮想環境からホスト側へファイルをコピーします。

multipass transfer multipass-docker:/home/ubuntu/cli/build/docker-windows-amd64.exe .

使ってみる

作成したDocker CLIを使用してみます。

.\docker-windows-amd64.exe version
Client:
Version: 22.06.0-beta.0-195-g3dfef7691e.m
API version: 1.42
Go version: go1.19.2
Git commit: 3dfef7691e
Built: Fri Nov 4 04:23:20 2022
OS/Arch: windows/amd64
Context: default
error during connect: this error may indicate that the docker daemon is not running: Get "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/version": open //./pipe/docker_engine: The system cannot find the file specified.

通信するDockerサーバー側が設定できていないためエラーになりました。

Dockerサーバー側の設定

multipassの環境をDockerサーバーとします。Docker CLIとDockerデーモンの通信にSSH接続を使用する方法を試しました。

  1. 認証鍵の作成 Linux側で鍵を生成します。

    ssh-keygen -t rsa -b 4096

    いくつか質問が表示されますが、全て未入力とします。

  2. 公開鍵の方をauthorized_keysに登録

    cat ~/.ssh/id_rsa.pub >>  ~/.ssh/authorized_keys
  3. 秘密鍵をWindows側にコピー Linux環境を抜け、Windows上で実行します。

    multipass transfer multipass-docker:/home/ubuntu/.ssh/id_rsa .
    注記

    秘密鍵はユーザーフォルダ(C:\Users\xxx)配下に置くのが良いようです。

  4. SSH接続情報を登録 SSH設定ファイル(%USERPROFILE%\.ssh\config)に以下の内容を記載します。

    Host multipass-docker
    HostName 172.17.xxx.xxx
    User ubuntu
    IdentityFile ~/.ssh/id_rsa
    注記

    仮想環境のIPアドレスはmultipass info multipass-dockerで確認できます。

これでWindows環境からSSH接続ができるようになったと思います。パスワード無しでログインできることを確認してください。

ssh multipass-docker

Docker CLI側の設定

Docker CLIのグローバルオプションとして-H ホスト名を渡すことで、接続サーバーを指定できます。

.\docker-windows-amd64.exe -H "ssh://multipass-docker" version
Client:
Version: 22.06.0-beta.0-195-g3dfef7691e.m
API version: 1.41 (downgraded from 1.42)
Go version: go1.19.2
Git commit: 3dfef7691e
Built: Fri Nov 4 04:23:20 2022
OS/Arch: windows/amd64
Context: default

Server: Docker Engine - Community
Engine:
Version: 20.10.21
API version: 1.41 (minimum version 1.12)
Go version: go1.18.7
Git commit: 3056208
Built: Tue Oct 25 17:59:49 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.9
GitCommit: 1c90a442489720eec95342e1789ee8a5e1b9536f
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0

無事、サーバー側に接続ができました。(OS/Archlinux/amd64になっているのでLinuxへ接続できていることが確認できると思います。)

常に-Hオプションを指定するのは大変なので、contextを登録します。

.\docker-windows-amd64.exe context create multipass-docker --docker "host=ssh://multipass-docker"

作成したcontextを使用するように設定します。

.\docker-windows-amd64.exe context use multipass-docker

これで常にmultipass-dockerをサーバーとして使用する用に設定ができました。

.\docker-windows-amd64.exe version
Client:
Version: 22.06.0-beta.0-195-g3dfef7691e.m
API version: 1.41 (downgraded from 1.42)
Go version: go1.19.2
Git commit: 3dfef7691e
Built: Fri Nov 4 04:23:20 2022
OS/Arch: windows/amd64
Context: multipass-docker

Server: Docker Engine - Community
Engine:
Version: 20.10.21
API version: 1.41 (minimum version 1.12)
Go version: go1.18.7
Git commit: 3056208
Built: Tue Oct 25 17:59:49 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.9
GitCommit: 1c90a442489720eec95342e1789ee8a5e1b9536f
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0

docker runも動作することを確認します。

.\docker-windows-amd64.exe run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:e18f0a777aefabe047a671ab3ec3eed05414477c951ab1a6f352a06974245fe7
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/

使った感想

  • VolumeはLinux側のディレクトリがマウントされる

-vオプションでコンテナにマウントできるディレクトリはDockerサーバー側(Linux側)のディレクトリになります。

  • docker buildができない?

設定が不十分なのか、docker buildがエラーになります。

[+] Building 0.0s (0/0)
error: failed to get status: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing cannot connect to the Docker daemon. Is 'docker daemon' running on this host?: context canceled"

無理せず、Docker DesktopやRancher Desktopを使うのが良さそうです。