WSL2でcontainerdとnerdctlを使えるようにする(initd/systemd両対応)

複数の端末に何度もinstallする機会があったので手順をshell scriptにまとめ。

方針としては、

  • nerdctlのtar ballには対応するバージョンのcontainerdも含まれるが、他にも依存関係があるようなのでまとめてupgradeできるようにaptから導入する。nerdctlもaptで配信して欲しい
  • systemdが有効なWSL2なら常駐させる。
  • init.d向けに別途init.d用scriptを生成する。

早速、諸々をinstallするshell scriptは以下の通り。

事前にsudo apt update && sudo apt upgradeをしておくことを忘れずに…

#!/bin/sh

#
# Download nerdctl
#

VERSION=1.3.1 # see https://github.com/containerd/nerdctl/releases
OS=linux
ARCH=$([ $(uname -m) = "x86_64" ] && echo "amd64" || echo "arm64")

TARNAME=nerdctl-full-$VERSION-$OS-$ARCH.tar.gz
TARPATH=/tmp/$TARNAME

if [ ! -e $TARPATH ]; then
    curl -L "https://github.com/containerd/nerdctl/releases/download/v$VERSION/$TARNAME" -o $TARPATH
fi

#
# Install nerdctl and related softwares
#

sudo apt install uidmap containerd -y
sudo tar xzf $TARPATH -C /usr/local/bin/ --strip-components 1 bin/nerdctl bin/buildctl bin/buildkitd
sudo tar xzf $TARPATH -C /usr/lib/systemd/system/ --strip-components 3 lib/systemd/system/buildkit.service
sudo tar xzf $TARPATH -C /usr/local/ libexec
sudo chmod +s "$(which nerdctl)"

# Set PATH so that CNI can be referenced
echo 'export CNI_PATH=/usr/local/libexec/cni' >> ~/.bashrc
. ~/.bashrc

#
# Start daemon
#

if [ $(ps -p 1 | awk 'NR==2{print $4}') = "systemd" ]; then
    sudo systemctl enable containerd
    sudo systemctl enable buildkit

    sudo service containerd start
    sudo service buildkit start

    echo "Resident daemons: systemd mode"
else
    sudo $(which containerd) &
    sudo $(which buildkitd) &

    echo "Onestart daemons: initd mode"
fi

これを適当な名前でファイルに保存して実行すればdaemonが常駐された状態になる…筈。

init.d用scriptを生成する

MSストア版が導入できないなどsystemdを使えずinit.dで頑張る環境用に、簡易的なinit.d用scriptを生成する汎用的なshell scriptも作ってみた。

なお上記のscriptで既に起動しているprocessがある場合は手動でkillする事。

> sudo kill $(ps -A | grep containerd | awk '{print $1}')  
> sudo kill $(ps -A | grep buildkitd | awk '{print $1}')
#!/bin/sh

if [ $# = 0 ]; then
  echo "daemon name required."
  exit 1
fi

DAEMON_PATH=`which $1`
RETVAL="$?"

if [ $RETVAL != 0 ]; then
  echo "unknown daemon name: $1"
  exit 1
fi

set -e

echo "daemon path: $DAEMON_PATH"

INIT_FILE=/etc/init.d/$1

cat <<-EOF > $INIT_FILE
	#!/bin/sh
	
	set -e

	. /lib/lsb/init-functions
	
	DAEMON=$DAEMON_PATH
	PID_FILE=/var/run/$1.pid
	
	case "\$1" in
	  start)
	    if [ -e \$PID_FILE ]; then
	      exit 1
	    fi
	    start-stop-daemon --start --background --pidfile \$PID_FILE --make-pidfile --exec \$DAEMON
	    ;;
	  stop)
	    start-stop-daemon --stop --oknodo --retry 30 --pidfile \$PID_FILE
	    RETVAL="\$?"
	    if [ \$RETVAL != 0 ]; then
	      exit 1
	    fi
	    rm -f \$PID_FILE
	    ;;
	  status)
	    status_of_proc -p \$PID_FILE "\$DAEMON" $1
	    exit \$?
	    ;;
	  *)
	    echo "service $1 [start|stop|status]"
	    ;;
	esac
EOF

chmod +x $INIT_FILE
echo "maked: $INIT_FILE"

上記のscriptをmakeinit.shなどとした場合、以下の様に使う。

$ sudo ./makeinit.sh containerd
$ sudo ./makeinit.sh buildkitd

/etc/init.dへの書き込みが発生するのでsudoが必要だ。chmod +x makeinit.shも忘れずに…

登録後はsystemdと同様に(?)serviceコマンドを利用して起動できるようになる。

$ sudo service containerd start
$ sudo service buildkit start