👀

コマンドから見るnerdctlとdockerの違い

2022/12/13に公開

背景

Kubernetes 1.24でついにDockerShimが廃止になり、containerdのランタイムを使用する必要が出てきた。
当然、kubernetesのデバッグ作業にもdockerコマンドが使用できなくなり、nerdctlというコマンドに代替されるとのこと。基本的にはdockerコマンドとの互換性があるとのことだが、いくつか新しいコマンドがあったり、逆に使えなくなるコマンドもあるようなので、その辺りを一通り調べてみた。

ちなみに、dockerとcontainerdの違いやcontainerdへの移行方法については、dockerやcontainerdのメンテナーであるNTTの須田さんと徳永さんの記事が非常に参考になった。
Dockerからcontainerdへの移行 (NTT Tech Conference 2022発表レポート)

環境

MacBook Air (M2 2022)
macOS Monterey v12.6.1

dockerとnerdctlはRancher Desktop経由でインストールしたものを使用した。

% docker version
Client:
 Version:           20.10.17-rd
 API version:       1.41
 Go version:        go1.17.11
 Git commit:        c2e4e01
 Built:             Fri Jul 22 18:32:57 2022
 OS/Arch:           darwin/arm64
 Context:           rancher-desktop
 Experimental:      true

% nerdctl version
Client:
 Version:       v0.23.0
 OS/Arch:       linux/arm64
 Git commit:    660680b7ddfde1d38a66ec1c7f08f8d89ab92c68
 buildctl:
  Version:      v0.10.4
  GitCommit:    a2ba6869363812a210fcc3ded6926757ab780b5f

nerdctlで新しく追加されたコマンド

completion

% nerdctl completion --help
Generate the autocompletion script for nerdctl for the specified shell.
See each sub-command's help for details on how to use the generated script.

Usage: nerdctl completion [command]

Commands:
  bash        Generate the autocompletion script for bash
  fish        Generate the autocompletion script for fish
  powershell  Generate the autocompletion script for powershell
  zsh         Generate the autocompletion script for zsh

Flags:
  -h, --help   help for completion

See also 'nerdctl --help' for the global flags such as '--namespace', '--snapshotter', and '--cgroup-manager'.

各種シェルのコマンド補完用スクリプトを生成してくれる。dockerでも探せばコマンド補完スクリプトはあるが、さくっと生成できるのは便利かも。

internal

% nerdctl internal --help 
DO NOT EXECUTE MANUALLY

Usage: nerdctl internal [command]

Commands:
  oci-hook  OCI hook

Flags:
  -h, --help   help for internal

See also 'nerdctl --help' for the global flags such as '--namespace', '--snapshotter', and '--cgroup-manager'.

押すなよ!絶対押すなよ!なコマンド。
適当な引数で実行してみたが、レスポンスが返ってこないだけで環境が破壊されるとかはなかった。なぜ内部用コマンドが実行できる場所に置いてあるのかは謎。

apparmor

% nerdctl apparmor --help
Manage AppArmor profiles

Usage: nerdctl apparmor [flags]

Commands:
  inspect  Display the default AppArmor profile "nerdctl-default". Other profiles cannot be displayed with this command.
  load     Load the default AppArmor profile "nerdctl-default". Requires root.
  ls       List the loaded AppArmor profiles
  unload   Unload an AppArmor profile. The target profile name defaults to "nerdctl-default". Requires root.

Flags:
  -h, --help   help for apparmor

See also 'nerdctl --help' for the global flags such as '--namespace', '--snapshotter', and '--cgroup-manager'.

AppArmorはオープンソースのLinux向けセキュリティ機能で、プログラムがどのファイルにアクセスできるかを制御している。この制御内容の単位であるprofileを管理することができるコマンドだが、defaultのprofileしかloadできず、自作のprofileはloadできないようにみえる。
その癖unloadはdefault以外のprofileも対象なため、いまいち使い道がわからない。apparmor_parserなど他のコマンドと組み合わせる前提?

ipfs

% nerdctl ipfs --help
Distributing images on IPFS

Usage: nerdctl ipfs [flags]

Management commands:
  registry  Manage read-only registry backed by IPFS

Flags:
  -h, --help   help for ipfs

See also 'nerdctl --help' for the global flags such as '--namespace', '--snapshotter', and '--cgroup-manager'.

IPFSはP2Pデータ共有プロトロコルであり、nerdctlではIPFSを利用してP2Pのコンテナイメージのやり取りができる。
例えば、nerdctl push ipfs://ubuntu:20.04といったコマンドでコンテナイメージをIPFSにpushできる。(詳細はこちら
nerdctl ipfsコマンドは、IPFSの背後で動作している分散型Registryを管理するためのコマンド。IPFSでP2P通信したいユースケースはよくわからない。

namespace

% nerdctl namespace --help
Unrelated to Linux namespaces and Kubernetes namespaces

Usage: nerdctl namespace [flags]

Aliases: namespace, ns
Commands:
  create   Create a new namespace
  inspect  Display detailed information on one or more namespaces.
  ls       List containerd namespaces
  remove   Remove one or more namespaces
  update   Update labels for a namespace

Flags:
  -h, --help   help for namespace

See also 'nerdctl --help' for the global flags such as '--namespace', '--snapshotter', and '--cgroup-manager'.

nerdctlには独自のnamespaceがあり、デフォルトではbuildkit, default, k8s.ioの3種類が存在する。(もちろん後から独自のnamespaceを追加もできる)

% nerdctl namespace ls
NAME        CONTAINERS    IMAGES    VOLUMES    LABELS
buildkit    0             0         0              
default     0             0         0              
k8s.io      0             0         0  

namespaceを指定するには、--namespaceのオプションを利用する。指定しない場合は自動的にdefaultのnamespaceが選択される。また、k8s.ioのnamespaceはkubernetesで利用される。

% nerdctl images
REPOSITORY    TAG       IMAGE ID        CREATED               PLATFORM          SIZE         BLOB SIZE
nginx         latest    ab589a3c466e    About a minute ago    linux/arm64/v8    142.5 MiB    52.8 MiB

% nerdctl --namespace k8s.io images
REPOSITORY    TAG       IMAGE ID        CREATED               PLATFORM          SIZE       BLOB SIZE
alpine        latest    8914eb54f968    About a minute ago    linux/arm64/v8    7.8 MiB    3.1 MiB
<none>        <none>    8914eb54f968    About a minute ago    linux/arm64/v8    7.8 MiB    3.1 MiB

ちなみにデフォルトのnamespaceを変更する方法を探したが見つからなかった。毎回指定するのは地味に面倒そうなのでalias登録しておくのがよさそう。

nerdctlでは削除されているコマンド

一覧がGitHubにまとまっていたのでそこから拝借した。量が多いので各コマンドのhelpメッセージは省略する。
全体的に他のコマンドで代替できるコマンドや、あまり使われていないコマンドが削除されている。

attach

もともとdocker execと機能が被っていたので影響は少ないか。
個人的にもexecの方しか使ったことがない。

diff

コンテナ起動後に変更されたファイルの一覧を出力できるコマンド。使ったことはなかったが、意外と便利そう。

checkpoint

dockerでも試験的機能とのことで、使ったことがない。

compose create|events|scale|start

composeはあまり使ったことがないが、upとdownがあれば何とかなるイメージ。

context

nerdctlにはcontextという概念が存在しない。namespaceが代替のようなものか?

export

コンテナをtarファイルにエクスポートするコマンド。nerdctl saveでコンテナイメージのtarファイルエクスポートはできるので、まあ問題なさそう。

import

コンテナをtarファイルにインポートするコマンド。こちらはnerdctl loadでコンテナイメージインポートができる。

docker hubで検索しようねということか…

manifest

これもdockerで試験的機能。コンテナイメージのメタデータを管理するコマンド?

network connect|disconnect

作成済のコンテナをネットワークにアタッチしたりデタッチしたりできなくなった。まあ、コンテナ作成時にネットワーク接続しておけばよいのだが。

plugin

plugin機能が存在しないのは拡張性に欠ける気がするので今後の追加に期待。

swarm|mode|service|config|secret|stack

docker swarmに関するコマンドは総じて削除。kubernetesがコンテナオーケストレーションのデファクトスタンダードのため致し方なし。

system df

イメージやコンテナなどのディスク使用率が表示されるコマンド。使ったことはなかったが地味に便利そうなので残念。

trust

コンテナイメージに署名・検証するためのコマンド。nerdctlではcosignという機能があり、nerdctl pull --verify=cosignnerdctl push --verify=cosignで代替できるとのこと。

感想

全体的な印象としては、dockerとの互換を保ちつつ、冗長なコマンドを省いておりシンプルに使えると感じた。plugin機能が存在しないのも、スリムな構成にするためかもしれない。
また、調べている中で、今まで使ったことがなかった便利そうなコマンドがいくつか発見できて思わぬ掘り出し物になった。
今回は触れなかったが、nerdctlにはlazy-pullingなど、他にもいくつかdockerにはない機能があるのでその辺りもいつか検証してみたい。

Discussion