我的服务器建设日志:ZFS 上的 Docker
书法
我的服务器建设日志:自宅服务器的重新规划和搭建的续篇。
上次我安装了LXD,并试用了一下。这次我会在与LXD共存的情况下安装Docker。
然而,LXD的官方似乎也对与Docker同时安装持否定态度。我会进一步确认这一点。
目標 (Mù
-
- 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设置为一个独立的数据集会更便于管理。
- ZFS on linuxでdockerを使う – Zenn
这次的前提条件是事先安装了LXD。
- 私的サーバー構築日誌:LXD- Qiita
应用程序容器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 引擎了!最好使用最新版本。
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」这一行,但实际上它却给我们展示了许多不同的信息。一瞬间,我误以为发生了错误。
结束后,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"
网络相关
兰西大学
轻轻地检查。
看起来UbuntuServer和Xubuntu的网络行为是不同的。如果有了解的人,请编写详细的文章,并在评论中提供详细信息。我不知道该怎么办了。
在Xubuntu的情况下,LXD容器在这一点上的行为看起来像是网络被阻断了。关于这个问题,请参阅之前的文章。在Ubuntu Server上似乎没有问题,所以这次我们将省略它。
暫時只需要確認一下網絡。我們在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仍然存在,请跳过此次创建,并仅执行下一个端口添加。
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命令时,指定了一个横杠-作为输出(表示标准输出),但由于这个莫名其妙的规格,不知道为什么会将一些奇怪的数据附加到输出的开头(而且无法抑制),所以无法将其整理到一行中。奇怪的是,进程替换也会导致错误,所以不起作用。
因为无法做任何事情,我创建了一个临时文件于/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可以同时运行。