能書き
私的サーバー構築日誌:仕切り直しからの自宅サーバー構築の続きです。
前回はLXDをインストールして、一通り触ってみました。今回はLXDと併存する形でDockerをインストールします。
但しDockerとの同時インストールはLXDの公式も否定的であるようです。その辺も確認します。
目標
- Dockerでアプリケーションコンテナを起動
- Dockerコンテナに外部からアクセス
- LXDのシステムコンテナも同時に動く事を確認
参考文献
- 自宅サーバー構築譚:Docker - Qiita
- Install Docker Engine on Ubuntu - Docker Engine - docker docs
- Docker Composeを使ってサクッとNginxコンテナを起動する - Qiita
- コマンドでDockerコンテナを停止・削除、イメージの削除をする - Qiita
- LXD と Docker の問題を回避する - ファイアウォールを設定するには
- LXDとDockerを同時利用するためにiptables設定を調整 - hnakamur's blog
zfsを利用する時には/var/lib/docker
を独立したデータセットにしておいた方が、管理上、都合が良いです。
事前にLXDをインストールしている事が、今回の前提条件です。
アプリケーションコンテナDocker
スナップショット
今回のスナップショットはこんな感じです。
sudo zfs snapshot tank/root/ubuntu@$(date +%Y%m%d_%H%M%S)_before_Docker
zfs
最初にdocker用のデータセットを作ります。
sudo zfs create -o mountpoint=/var/lib/docker tank/docker
インストール
定番のapt update
。
sudo apt update
Dockerのaptリポジトリを追加するのに必要な道具をインストールします。
sudo apt install -y ca-certificates curl gnupg
DockerのGPG鍵を追加します。
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
リポジトリのセットアップ。
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
そして再度apt update
です。
sudo apt update
ここでいよいよ Docker Engine のインストール!最新バージョンが良いでしょう。
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
インストールは以上となります。
docker --version
/etc
/etc
はこんな風に変化しました。
$ sudo svn st /etc
? /etc/apt/keyrings/docker.gpg
? /etc/apt/sources.list.d/docker.list
? /etc/bash_completion.d
? /etc/containerd
? /etc/default/docker
? /etc/docker
M /etc/group
M /etc/gshadow
? /etc/init.d/docker
M /etc/ld.so.cache
? /etc/perl
? /etc/rc0.d/K01docker
? /etc/rc1.d/K01docker
? /etc/rc2.d/S01docker
? /etc/rc3.d/S01docker
? /etc/rc4.d/S01docker
? /etc/rc5.d/S01docker
? /etc/rc6.d/K01docker
? /etc/systemd/system/multi-user.target.wants/containerd.service
? /etc/systemd/system/multi-user.target.wants/docker.service
? /etc/systemd/system/multi-user.target.wants/snap-core20-2015.mount
? /etc/systemd/system/snap-core20-2015.mount
? /etc/systemd/system/snapd.mounts.target.wants/snap-core20-2015.mount
? /etc/systemd/system/sockets.target.wants/docker.socket
- いつもの
ld.so.cache
、init.d関連、systemd関連。 - perlの
/etc
が追加された模様です。中身を調べるとlibnetとかいう物のようです。 - docker関連の
/etc
設定。 -
/etc/containerd
というのがありますが、containerdとはコンテナのライフサイクルを管理する為のDockerコンポーネントの一つ、らしい。 -
/etc/bash_completion.d
はbashの補完スクリプト…?何やってくれるんでしょうね。 - keyringsとsources.list.dは、恐らく、Dockerインストールに先立って入れたキーなどでしょう。
- dockerグループが追加されています(groupとgshadow)
Subversionで登録します。
sudo svn st /etc | grep "^?" | cut -b9- | xargs -I{} sudo find {} -type f -or -type d -or -type l | xargs -t sudo svn add
sudo svn ci /etc -m"install Docker"
ユーザーグループ
dockerグループに所属しているユーザーならば、docker
コマンド実行時にsudo
は不要のようです。
sudo usermod -aG docker $USER
自分自身のグループを変更したので、反映させる為に一度ログアウトしてログインし直します。
logout
正しく動作できるかの確認は、下記を実行します。
docker run hello-world
「hello, world」の1行を表示するだけかと思ったら、何だか色々とメッセージを表示してくれますね。一瞬、エラーが発生したのかと勘違いしました。
終わった後もDockerが残っています。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
302ff60f2e92 hello-world "/hello" 16 seconds ago Exited (0) 15 seconds ago gifted_wright
zfs にも痕跡が残っています。
$ zfs list -r tank/docker
NAME USED AVAIL REFER MOUNTPOINT
tank/docker 716K 1.80T 456K /var/lib/docker
tank/docker/0212ade3da9f427cf650704111949e1f7e3a516660788ba6a65906a880649b48 64K 1.80T 116K legacy
tank/docker/0212ade3da9f427cf650704111949e1f7e3a516660788ba6a65906a880649b48-init 88K 1.80T 116K legacy
tank/docker/e100ba7cebe0945b77644f7cd60774da7119b74599aecad44171e2de3bd74e78 108K 1.80T 108K legacy
綺麗に消しましょう。
docker ps -aq | xargs -rt docker rm
docker images -q | xargs -rt docker rmi
zfs上の痕跡も消えます。
$ zfs list -r tank/docker
NAME USED AVAIL REFER MOUNTPOINT
tank/docker 368K 1.80T 368K /var/lib/docker
上手くいったので/etc
を確認。
sudo svn st /etc
グループ追加の影響が出てます。
$ sudo svn st /etc
M /etc/group
M /etc/gshadow
いつもの手順で登録。
sudo svn st /etc | grep "^?" | cut -b9- | xargs -I{} sudo find {} -type f -or -type d -or -type l | xargs -rt sudo svn add
sudo svn ci /etc -m"set $USER's group"
ネットワークについて
LXD
軽くチェック
どうやらUbuntuServerとXubuntuとで、ネットワークの挙動が違うようです。どなたか詳しい方がいらっしゃいましたら、詳細について記事を書いて、コメントください。私はお手上げです。
Xubuntuの場合、この時点でLXDコンテナはネットワークが遮断されたような挙動になります。これについては以前の記事を参照ください。UbuntuServerでは問題無いようなので、今回は省略します。
取り敢えず、ネットワークの確認だけ。LXDコンテナ内でpingを実行してみます。
lxc launch images:ubuntu/22.04 test --device eth0,ipv4.address=192.168.0.2
lxc exec test -- ping -c2 example.com
成功します。
$ lxc launch images:ubuntu/22.04 test --device eth0,ipv4.address=192.168.0.2
Creating test
Starting test
$ lxc exec test -- ping -c2 example.com
PING example.com (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=1 ttl=52 time=94.3 ms
64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=2 ttl=52 time=110 ms
--- example.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 94.276/102.383/110.491/8.107 ms
動作確認
コンテナ内から外部へのネットワーク接続を確認できたら、ソフトをインストールしてみます。
lxc exec -- test apt install -y nginx
外部からコンテナ内への接続を定義。
-
lxdbr0
は今回のLXDコンテナのブリッジネットワーク -
172.16.1.2
はホストマシンのIPアドレス -
192.168.0.2
はLXDコンテナのIPアドレス
※前回の続きでlxdbr0
の設定が残っていたら、このcreate
は飛ばして次のport add
だけ実行してください。
lxc network forward create lxdbr0 172.16.1.2
lxc network forward port add lxdbr0 172.16.1.2 tcp 10080 192.168.0.2 80
ここで……
食らえ!HTTP/0.9!
echo -en "GET /\r\n" | nc 172.16.1.2 10080
なぜ化石のような規格のHTTP/0.9を使うかと言いますとですね。レスポンスにヘッダが付かないというメリットがあるんですね。
だからこんな荒技も出来るんです。
diff -s --label GET <(echo -en "GET /\r\n" | nc 172.16.1.2 10080) --label IN_CONTAINER <(lxc file pull test/var/www/html/index.nginx-debian.html -)
実行結果はこうなります。
$ diff -s --label GET <(echo -en "GET /\r\n" | nc 172.16.1.2 10080) --label IN_CONTAINER <(lxc file pull test/var/www/html/index.nginx-debian.html -)
Files GET and IN_CONTAINER are identical
美しい……
以上でLXDの方は動作確認できました。
Docker
今度はDockerです。
まず設定ファイルdocker-compose.yml
を準備。難しい事はしないのでDockerfile
は要りません。
mkdir ~/nginx
cd ~/nginx
cat >docker-compose.yml <<___
version: '3'
services:
nginx:
image: nginx:latest
build: .
ports:
- "20080:80"
___
バックグラウンドで起動します。
docker compose up -d
今度もHTTP/0.9でアクセスしますが……
今回は、docker compose cp
コマンドで出力にハイフン - を指定する(これは標準出力を表す)と、良く分からないデータを頭にくっつけやがる(そして抑制できない)という謎仕様の為、1行に纏める事が出来ませんでした。
なぜかプロセス置換もエラーになってしまってダメです。
仕方が無いので/tmp
に一時ファイルを作成しました。
docker compose cp nginx:/usr/share/nginx/html/index.html /tmp/test.html >&/dev/null
diff -s --label GET <(echo -en "GET /\r\n" | nc 172.16.1.2 20080) --label IN_CONTAINER /tmp/test.html
実行結果。
$ docker compose cp nginx:/usr/share/nginx/html/index.html /tmp/test.html >&/dev/null
$ diff -s --label GET <(echo -en "GET /\r\n" | nc 172.16.1.2 20080) --label IN_CONTAINER /tmp/test.html
Files GET and IN_CONTAINER are identical
ま、とにかく、Dockerコンテナがちゃんと動いている事は間違い無いようです。
確認が終わったら、綺麗に消しましょう。
docker compose down --rmi all --volumes
cd ..
rm -r nginx
仕舞い
今回はDockerをインストールし、LXDとDockerが同時に稼働できる事を確認しました。