containerdのセットアップ + nerdctlを動かした際の作業ログ

# モチベーション
nerdctlコマンドを手元のマシン(Ubuntu-22.04)で稼働させたかったということで導入しました。
せっかくなのでルートレスモードで動かしてみたときの作業ログです。

# 前提
- Ubuntu-22.04を利用しています。
- containerdは下記手順に従い1.7.25-1をパッケージでインストールしています。
  - https://docs.docker.com/engine/install/ubuntu/
- ダウンロードするパッケージはその時の最新を指定しています。

# 作業の流れ
- nerdctlを入れる
- containerd-rootless-setuptool.sh installの実行
- CNI プラグインを入れる
- BuildKitを入れる
- containerd-rootless-setuptool.sh install-buildkit-containerdの実行

# 作業ログ
nerdctlをダウンロードします。
```
$ wget https://github.com/containerd/nerdctl/releases/download/v2.0.3/nerdctl-2.0.3-linux-amd64.tar.gz
$ mkdir targz
$ mv nerdctl-2.0.3-linux-amd64.tar.gz targz
$ cd targz/
```

展開し、バイナリを~/.local/binへと移動します。
```
$ tar zvxf nerdctl-2.0.3-linux-amd64.tar.gz 
nerdctl
containerd-rootless-setuptool.sh
containerd-rootless.sh
$ mv containerd-rootless-setuptool.sh  containerd-rootless.sh nerdctl ~/.local/bin
```

では、インストールしましょう。下記コマンドを実行します。が、エラーが出ます。
```
$ containerd-rootless-setuptool.sh install
[INFO] Checking RootlessKit functionality
[rootlesskit:parent] error: failed to setup UID/GID map: newuidmap 873607 [0 1000 1 1 100000 65536] failed: : exec: "newuidmap": executable file not found in $PATH
[ERROR] RootlessKit failed, see the error messages and https://rootlesscontaine.rs/getting-started/common/ .
```

エラーが出ましたが、newuidmapがないとのことですので下記でインストールします。
```
$ sudo apt-get install uidmap
```

気を取り直して再度実行してみます。
```
$ containerd-rootless-setuptool.sh install
[INFO] Checking RootlessKit functionality
[INFO] Checking cgroup v2
[WARNING] The cgroup v2 controller "cpu" is not delegated for the current user ("/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/cgroup.controllers"), see https://rootlesscontaine.rs/getting-started/common/cgroup2/
[INFO] Checking overlayfs
[INFO] Requirements are satisfied
[INFO] Creating "/home/tsuyoshi/.config/systemd/user/containerd.service"
[INFO] Starting systemd unit "containerd.service"
+ systemctl --user start containerd.service
+ sleep 3
+ systemctl --user --no-pager --full status containerd.service
● containerd.service - containerd (Rootless)
     Loaded: loaded (/home/tsuyoshi/.config/systemd/user/containerd.service; disabled; vendor preset: enabled)
     Active: active (running) since Mon 2025-02-24 19:28:58 JST; 3s ago
   Main PID: 874120 (rootlesskit)
      Tasks: 29
     Memory: 23.0M
        CPU: 133ms
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/containerd.service
             ├─874120 rootlesskit --state-dir=/run/user/1000/containerd-rootless --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --copy-up=/var/lib --propagation=rslave /home/tsuyoshi/.local/bin/containerd-rootless.sh
             ├─874138 /proc/self/exe --state-dir=/run/user/1000/containerd-rootless --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --copy-up=/var/lib --propagation=rslave /home/tsuyoshi/.local/bin/containerd-rootless.sh
             ├─874157 slirp4netns --mtu 65520 -r 3 --disable-host-loopback --enable-sandbox --enable-seccomp 874138 tap0
             └─874164 containerd

Feb 24 19:28:58 tsuyoshi-Diginnos-PC containerd-rootless.sh[874164]: time="2025-02-24T19:28:58.314123596+09:00" level=error msg="failed to load cni during init, please check CRI plugin status before setting up network for pods" error="cni config load failed: no network config found in /etc/cni/net.d: cni plugin not initialized: failed to load cni config"
Feb 24 19:28:58 tsuyoshi-Diginnos-PC containerd-rootless.sh[874164]: time="2025-02-24T19:28:58.314293435+09:00" level=info msg="Start subscribing containerd event"
Feb 24 19:28:58 tsuyoshi-Diginnos-PC containerd-rootless.sh[874164]: time="2025-02-24T19:28:58.314395273+09:00" level=info msg="Start recovering state"
Feb 24 19:28:58 tsuyoshi-Diginnos-PC containerd-rootless.sh[874164]: time="2025-02-24T19:28:58.314466363+09:00" level=info msg=serving... address=/run/containerd/containerd.sock.ttrpc
Feb 24 19:28:58 tsuyoshi-Diginnos-PC containerd-rootless.sh[874164]: time="2025-02-24T19:28:58.314508236+09:00" level=info msg="Start event monitor"
Feb 24 19:28:58 tsuyoshi-Diginnos-PC containerd-rootless.sh[874164]: time="2025-02-24T19:28:58.314546582+09:00" level=info msg=serving... address=/run/containerd/containerd.sock
Feb 24 19:28:58 tsuyoshi-Diginnos-PC containerd-rootless.sh[874164]: time="2025-02-24T19:28:58.314548659+09:00" level=info msg="Start snapshots syncer"
Feb 24 19:28:58 tsuyoshi-Diginnos-PC containerd-rootless.sh[874164]: time="2025-02-24T19:28:58.314604805+09:00" level=info msg="Start cni network conf syncer for default"
Feb 24 19:28:58 tsuyoshi-Diginnos-PC containerd-rootless.sh[874164]: time="2025-02-24T19:28:58.314621031+09:00" level=info msg="Start streaming server"
Feb 24 19:28:58 tsuyoshi-Diginnos-PC containerd-rootless.sh[874164]: time="2025-02-24T19:28:58.314663758+09:00" level=info msg="containerd successfully booted in 0.214151s"
+ systemctl --user enable containerd.service
Created symlink /home/tsuyoshi/.config/systemd/user/default.target.wants/containerd.service → /home/tsuyoshi/.config/systemd/user/containerd.service.
[INFO] Installed "containerd.service" successfully.
[INFO] To control "containerd.service", run: `systemctl --user (start|stop|restart) containerd.service`
[INFO] To run "containerd.service" on system startup automatically, run: `sudo loginctl enable-linger tsuyoshi`
[INFO] ------------------------------------------------------------------------------------------
[INFO] Use `nerdctl` to connect to the rootless containerd.
[INFO] You do NOT need to specify $CONTAINERD_ADDRESS explicitly.
```

では、nerdctl runしてみましょう。しかし、どうやらCNI Pluginがないとエラーになるようです。
```
$ nerdctl run docker.io/hello-world
docker.io/library/hello-world:latest:                                             resolved       |++++++++++++++++++++++++++++++++++++++| 
index-sha256:e0b569a5163a5e6be84e210a2587e7d447e08f87a0e90798363fa44a0464a1e8:    done           |++++++++++++++++++++++++++++++++++++++| 
manifest-sha256:03b62250a3cb1abd125271d393fc08bf0cc713391eda6b57c02d1ef85efcc25c: done           |++++++++++++++++++++++++++++++++++++++| 
config-sha256:74cc54e27dc41bb10dc4b2226072d469509f2f22f1a3ce74f4a59661a1d44602:   done           |++++++++++++++++++++++++++++++++++++++| 
layer-sha256:e6590344b1a5dc518829d6ea1524fc12f8bcd14ee9a02aa6ad8360cce3a9a9e9:    done           |++++++++++++++++++++++++++++++++++++++| 
elapsed: 7.2 s                                                                    total:  1.0 Ki (143.0 B/s)                                       
FATA[0007] failed to verify networking settings: failed to create default network: needs CNI plugin "bridge" to be installed in CNI_PATH ("/opt/cni/bin"), see https://github.com/containernetworking/plugins/releases: exec: "/opt/cni/bin/bridge": stat /opt/cni/bin/bridge: no such file or directory 
```

CNIプラグインが必須なので用意します。
```
$ cd targz
$ wget "https://github.com/containernetworking/plugins/releases/download/v1.6.2/cni-plugins-linux-amd64-v1.6.2.tgz"
$ sudo mkdir -p /opt/cni/bin/
$ cd /opt/cni/bin/
```

取得したパッケージを/opt/cni/bin/配下に展開します。
```
$ sudo tar zvxf ~/targz/cni-plugins-linux-amd64-v1.6.2.tgz 
./
./ipvlan
./tap
./loopback
./host-device
./README.md
./portmap
./ptp
./vlan
./bridge
./firewall
./LICENSE
./macvlan
./dummy
./bandwidth
./vrf
./tuning
./static
./dhcp
./host-local
./sbr
```

以上で準備が整いましたので、再度コンテナをnerdctl runで実行してみます。
```
$ nerdctl run docker.io/hello-world

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/
```

今更ですが、nerdctlのバージョンも見ておきます
```
$ nerdctl -v
nerdctl version 2.0.3
```

続いてnerdctl buildをする際にも、依存としてBuildkitが必要らしいのでまずはそのセットアップをします。
```
$ cd ~/targz/
$ wget "https://github.com/moby/buildkit/releases/download/v0.20.0/buildkit-v0.20.0.linux-amd64.tar.gz"
```

展開します。

```
$ tar zvxf buildkit-v0.20.0.linux-amd64.tar.gz 
bin/
bin/buildctl
bin/buildkit-cni-bridge
bin/buildkit-cni-firewall
bin/buildkit-cni-host-local
bin/buildkit-cni-loopback
bin/buildkit-qemu-aarch64
bin/buildkit-qemu-arm
bin/buildkit-qemu-i386
bin/buildkit-qemu-ppc64le
bin/buildkit-qemu-riscv64
bin/buildkit-qemu-s390x
bin/buildkit-runc
bin/buildkitd
```

ローカルのbinに配置します。
```
$ mv bin/*  ~/.local/bin
```

ではbuildkitをインストールしてみます。
```
$ CONTAINERD_NAMESPACE=default containerd-rootless-setuptool.sh install-buildkit-containerd
[INFO] Creating "/home/tsuyoshi/.config/systemd/user/default-buildkit.service"
[INFO] Starting systemd unit "default-buildkit.service"
+ systemctl --user start default-buildkit.service
+ sleep 3
+ systemctl --user --no-pager --full status default-buildkit.service
● default-buildkit.service - BuildKit (Rootless)
     Loaded: loaded (/home/tsuyoshi/.config/systemd/user/default-buildkit.service; disabled; vendor preset: enabled)
     Active: active (running) since Mon 2025-02-24 19:39:57 JST; 3s ago
   Main PID: 875190 (buildkitd)
      Tasks: 10 (limit: 9042)
     Memory: 7.7M
        CPU: 94ms
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/default-buildkit.service
             └─875190 buildkitd --oci-worker=false --containerd-worker=true --containerd-worker-rootless=true --addr=unix:///run/user/1000/buildkit-default/buildkitd.sock --root=/home/tsuyoshi/.local/share/buildkit-default --containerd-worker-namespace=default --containerd-worker-net=bridge

Feb 24 19:39:57 tsuyoshi-Diginnos-PC systemd[2796]: Started BuildKit (Rootless).
Feb 24 19:39:57 tsuyoshi-Diginnos-PC containerd-rootless-setuptool.sh[875190]: time="2025-02-24T19:39:57+09:00" level=info msg="found worker \"m6d6lyrnbolg39udz2zcavz64\", labels=map[org.mobyproject.buildkit.worker.containerd.namespace:default org.mobyproject.buildkit.worker.containerd.uuid:701277c1-05af-4e2b-95f5-8bd06ff3d6d7 org.mobyproject.buildkit.worker.executor:containerd org.mobyproject.buildkit.worker.hostname:tsuyoshi-Diginnos-PC org.mobyproject.buildkit.worker.network:cni org.mobyproject.buildkit.worker.selinux.enabled:false org.mobyproject.buildkit.worker.snapshotter:overlayfs], platforms=[linux/amd64 linux/amd64/v2 linux/amd64/v3 linux/386]"
Feb 24 19:39:57 tsuyoshi-Diginnos-PC containerd-rootless-setuptool.sh[875190]: time="2025-02-24T19:39:57+09:00" level=info msg="found 1 workers, default=\"m6d6lyrnbolg39udz2zcavz64\""
Feb 24 19:39:57 tsuyoshi-Diginnos-PC containerd-rootless-setuptool.sh[875190]: time="2025-02-24T19:39:57+09:00" level=warning msg="currently, only the default worker can be used."
Feb 24 19:39:57 tsuyoshi-Diginnos-PC containerd-rootless-setuptool.sh[875190]: time="2025-02-24T19:39:57+09:00" level=info msg="running server on /run/user/1000/buildkit-default/buildkitd.sock"
+ systemctl --user enable default-buildkit.service
Created symlink /home/tsuyoshi/.config/systemd/user/default.target.wants/default-buildkit.service → /home/tsuyoshi/.config/systemd/user/default-buildkit.service.
[INFO] Installed "default-buildkit.service" successfully.
[INFO] To control "default-buildkit.service", run: `systemctl --user (start|stop|restart) default-buildkit.service`
```

起動プロセスも確認できました。
```
$ ps auxww | grep buildkit
tsuyoshi  875190  0.1  0.4 1269852 34632 ?       Ssl  19:39   0:00 buildkitd --oci-worker=false --containerd-worker=true --containerd-worker-rootless=true --addr=unix:///run/user/1000/buildkit-default/buildkitd.sock --root=/home/tsuyoshi/.local/share/buildkit-default --containerd-worker-namespace=default --containerd-worker-net=bridge
```

折角なので何かをビルドしてみましょう。ルートレスですのでnerdctl buildの際のsudoの指定は不要です。
```
$ cat Dockerfile
FROM ubuntu:24.04
RUN echo "hello world" > sample
$ nerdctl build -t helloworld .
[+] Building 35.7s (6/6) FINISHED                                                                                                                                         
 => [internal] load build definition from Dockerfile                                                                                                                 0.7s
 => => transferring dockerfile: 87B                                                                                                                                  0.0s
 => [internal] load metadata for docker.io/library/ubuntu:24.04                                                                                                      3.9s
 => [internal] load .dockerignore                                                                                                                                    0.5s
 => => transferring context: 2B                                                                                                                                      0.0s
 => [1/2] FROM docker.io/library/ubuntu:24.04@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782                                               13.5s
 => => resolve docker.io/library/ubuntu:24.04@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782                                                0.4s
 => => sha256:5a7813e071bfadf18aaa6ca8318be4824a9b6297b3240f2cc84c1db6f4113040 29.75MB / 29.75MB                                                                    11.0s
 => => extracting sha256:5a7813e071bfadf18aaa6ca8318be4824a9b6297b3240f2cc84c1db6f4113040                                                                            1.2s
 => [2/2] RUN echo "hello world" > sample                                                                                                                           10.7s
 => exporting to image                                                                                                                                               4.4s
 => => exporting layers                                                                                                                                              2.3s
 => => exporting manifest sha256:5081936dce2fb7aa27abc14fc35cd901e8d79fc9787eaba954b1ff036d456f9f                                                                    0.3s
 => => exporting config sha256:454c3b8d0f6897fafd88c645c15456c8914f9b632d2c0842aa4ce79684b898e6                                                                      0.3s
 => => naming to docker.io/library/helloworld:latest                                                                                                                 0.1s
 => => unpacking to docker.io/library/helloworld:latest                                                                                                              1.4s
$ nerdctl image ls helloworld
REPOSITORY    TAG       IMAGE ID        CREATED           PLATFORM       SIZE       BLOB SIZE
helloworld    latest    5081936dce2f    12 seconds ago    linux/amd64    87.61MB    29.76MB
```

とりあえずnerdctlが使えるところまでできたので、一旦ここまで。

# 参考記事
- https://tech.virtualtech.jp/entry/2023/07/14/182708
  - ほとんどこの記事の後を辿っただけです。