MacでDocker Desktopを入れずにDocker CLI+Multipassで代替してみる
※このやり方はIntel Macでのみ動作します。
M1 MacはMultipass(virtualbox)が動作しないので使えません。
概要
Docker Desktopが従業員250人以上だと有料化しました.
(※Docker CLIやDocker Engineは引き続き無料で使うことができます)
MacやWindowsだとDocker Desktopを入れないとDockerを使えないかと思いきやDocker CLIだけ個別に入手することができるようです.
この記事では仮想マシンにDockerを入れ,そこからホストのMac上のDocker CLIから操作する方法を紹介します.
Docker CLI単独のバイナリはこちらから入手できます
(業務で使う場合はライセンス等きっちり調べてから使ってください)
この辺の使います
内容を理解するにはこの辺に関する知識があると良いです
- Docker CLI
- Docker Context
- Multipass
- cloud-init
- VirtualBox
環境構築
multipassとVirtualBoxのインストール
brew install --cask virtualbox virtualbox-extension-pack
brew install multipass
# multipassのバックエンドをhyperkit->virtualboxに変更
sudo multipass set local.driver=virtualbox
multipassのインスタンス初期設定
cloud-initという仕組みを使ってインスタンス作成時に自動で下記設定をします.
- Dockerインストール + SSH経由でDocker使えるようにする設定
- docker.ioのインストール- dockerグループにubuntuユーザーを追加する
- multipass (VirtualBox)でローカルディレクトリをマウントできるようにする
- multipass-sshfsをインストール
cloud-initで初期設定するためのcloud-configの記述例
(ここではcloud-config.yamlというファイル名で)
#cloud-config
groups:
- docker
system_info:
default_user:
groups: ["docker"]
package_update: true
packages:
- docker
- docker.io
snap:
commands:
- 'snap install multipass-sshfs'
注意事項
↑のYAMLファイル先頭の#cloud-config
の記述は必須です.これがないとcloud-initが認識してくれません.
参考
他の設定はこちらを参考にしてください。
(aptのプロキシ設定や/etc/environmentにプロキシ設定を書き込む方法など)
インスタンス起動
この設定でインスタンスを作成します
- インスタンス名: Docker
- CPU: 4コア
- メモリ: 4GB
- ストレージ: 40GB
multipass launch --name docker --mem 4G --disk 40G --cpus 4 --cloud-init cloud-config.yaml
注意事項
この時タイムアウトと出る可能性がありますがインスタンスは作成されています.
インスタンスがまだバックグラウンドでDockerをインストールしている最中の可能性があるのでこのコマンドでインスタンスにDockerが入っているのが確認できるまで放置しましょう.
multipass exec docker -- docker --version
Multipassインスタンスへ接続するSSHポート設定
VirtualBoxバックエンドなMultipassのインスタンスへSSH接続するにはVirtualBox VMのポートフォワーディング設定が必要です.
今回はlocalhost:10022がインスタンスの22番ポートに飛ぶ設定で説明します.
# ポートフォワーディング追加 (VM起動中の場合)
sudo VBoxManage controlvm "docker" natpf1 "docker-ssh,tcp,,10022,,22"
# ポートフォワーディング追加 (VM停止中の場合)
sudo VBoxManage modifyvm "docker" --natpf1 "docker-ssh,tcp,,10022,,22"
注意事項
↑コマンドのdocker-ssh
はVirtualBox上のポートフォワーディング設定名です. 設定名はssh
以外の名前にしてください.
ssh
はmultipass本体がインスタンスを制御するために使用している設定で,インスタンス起動時に毎回設定を書き換えてランダムポートが割り当てているようです.
補足1
設定したポートフォワーディング削除はこちらのコマンドで.
# ポートフォワーディング削除 (VM起動中の場合)
sudo VBoxManage controlvm "docker" natpf1 delete "docker-ssh"
# ポートフォワーディング削除 (VM停止中の場合)
sudo VBoxManage modifyvm "docker" --natpf1 delete "docker-ssh"
補足2
コマンドじゃなくGUIの方が好きな人はこちらで(VMがルート権限で動いてるので表示させるにはsudoが必要です).
sudo VirtualBox
muitipassインスタンスへアクセスするためのホストのSSH設定
multipassのインスタンスへアクセスするための秘密鍵をホストへコピーします.
(ここではファイル名は適当にmultipass.pemとします)
sudo install -m 600 -o $USER -g $(id -g) /var/root/Library/Application\ Support/multipassd/ssh-keys/id_rsa ~/.ssh/multipass.pem
~/.ssh/configにSSHアクセス情報を設定します.
Host multipass-docker
Hostname localhost
user ubuntu
port 10022
IdentityFile ~/.ssh/multipass.pem
念のためSSHフィンガープリントを削除します.
(手動で~/.ssh/known_hosts
の中身を消してもいいですがコピペできるようにコマンドで)
ssh-keygen -R "[localhost]:10022"
フィンガープリント登録とSSH疎通確認
(yesとCtlr+Cを入力するのがめんどくさいのでコマンド1つでできるようにしてます)
echo exit | ssh -oStrictHostKeyChecking=no multipass-docker
Docker CLI単品ダウンロード
Docker CLI単品をダウンロードしてきて~/bin/docker
にコピーします.
ついでにパスも通します.
mkdir ~/.src && cd ~/.src
wget https://download.docker.com/mac/static/stable/x86_64/docker-20.10.8.tgz
tar xzvf docker*
sudo xattr -rc docker
mkdir ~/bin
cp docker/docker $HOME/bin/docker
echo "export PATH=$PATH:$HOME/bin" >> ~/.zshrc
土下座事項 (202109182230追記)
sudo xattr -rc docker
入れ忘れてました。追記。
参考
Docker公式ドキュメントにちらっとだけMac版Docker CLIの情報が記載してます.
Docker CLIの接続先をmultipassのdockerにする
docker context create multipass --docker "host=ssh://ubuntu@multipass-docker"
docker context use multipass
土下座事項 (202109182230追記)
docker context use multipass
コマンド入れ忘れてました。追記。
Dockerを動かす
Dockerが使えているかどうかの確認
# 地獄の世界へようこそ
docker run --rm -it hello-world
ローカルディレクトリをDockerコンテナへマウントする方法
ローカルディレクトリをDockerコンテナへマウントするためには,ローカルディレクトリ→Multipassインスタンス→Dockerコンテナの順でマウントする必要があります.
また,VirtulBoxバックエンドでマウントするためにはインスタンスにmultipass-sshfsがインストールされている必要があります.
(※cloud-config.yamlでインスタンス作成時に自動インストールするように設定済みです)
例 (ローカルのホームディレクトリを同じパスでそっくりそのままマウントする)
multipass mount $HOME docker:$HOME
docker run --rm -it -v $HOME:$HOME bash -c "echo $HOME; ls $HOME"
余談1
↑のマウントしておけばVSCodeのRemote-ContainersのOpen Folder in Container
使えるようになります.
余談2
ディレクトリのマウントはSSHFSで行っています.
Macbook Pro 2020で計測したらスループットは80~100MB/sでした.
multipassインスタンスのメモリサイズ変更方法
multipassコマンドにはメモリサイズを変更する機能が実装されていません.
そのため,メモリサイズを変更するには直接VirtualBox VMの設定を変更する必要があります.
# メモリを4GBに変更する (インスタンス停止中のみ変更可)
multipass stop docker
sudo VBoxManage modifyvm "docker" --memory 4000
multipass start docker
補足
hyperkitバックエンドだとmultipassd-vm-instances.json
を編集すればメモリサイズを変更できますが,VirtualBoxバックエンドだとmultipassd-vm-instances.json
の編集は無意味です.
参考 (hyperkitバックエンドでのメモリサイズ変更方法)
現状困っているところ
- VirtualBoxバックエンドだとM1 Macで動かない
- hyperkitバックエンドでもほぼ同じことできるけどだと多分IP固定が出来ない.
- Podmanとかlimaでよくない?
- はい…
- Lima詳しくなかったので後から調べてみましたがよざげな記事を発見
- Docker CLI + Lima + Docker Engine on Limaの構成がほぼこの記事と同じアプローチです。 おすすめ。
- https://qiita.com/yoichiwo7/items/44aff38674134ad87da3
- ローカルディレクトリのマウントで手動操作が入ってくるのでめんどくさい。
- どうしようねこれ…
- 追記: 普通にローカルのホームディレクトリマウントしておけば普段の作業で困ることはなかった。
multipass mount $HOME docker:$HOME
Discussion
cloud-config.yamlでプロキシ設定例
引数
--cloud-init
の値を-
にすると標準入力でcloud-configを渡すことができます。こうすればホストのプロキシ環境変数も引き継げるんじゃないかな思います。
multipassのhyperkitバックエンドの場合は
/var/db/dhcpd_leases
を編集して割り振られるIPアドレスを調整できるようなのでやろうと思えば固定IP化できるようです。
これができたらApple SiloconのMACでもmultipass使ってdocker使うことができるかもしれないです。
(持ってないので検証できないのと、x86なインスタンスが実行できるのか怪しいですが)
※割り振られるIPの範囲は192.168.64.0/24
参考
/var/db/dhcpd_leases
の中身の例