読者です 読者をやめる 読者になる 読者になる

Docker コンテナを systemd-nspawn で動かす (作業メモ)

ちょっと前までは machinectl pull-dkr というコマンドがあったんだけど、Docker の考えるコンテナと systemd-nspawn の考えるコンテナの差が大きいこともあって消されている。 とはいえ、Docker コンテナも systemd-nspawn (machinectl) で扱うコンテナも本質的に違うものではないので、Docker で作ったコンテナを systemd-nspawn で動かせないこともない。 以下、mysql:5.6 を例に使った作業メモ。

イメージのままだと export できないので、適当に起動してコンテナを作ってから export して、適当なディレクトリに展開しておく。

% docker run --detach mysql:5.6 false
9872d546b6d1f245f25b895ef4c05725d3fdba30d604c11801b000b78ac79d23
% docker export -o mysql56.tar 9872d546b6d1f245f25b895ef4c05725d3fdba30d604c11801b000b78ac79d23
% mkdir mysql56
% tar -C mysql56 -xf mysql56.tar

export すると Docker の ENV とか ENTRYPOINT とか CMD 等の情報が落ちてしまうため、適当に残しておく。

% docker inspect mysql:5.6 | jq --raw-output '.[].Config.Env | map("export \(.)") | join(";")' > mysql56/env.sh
% cat mysql56/env.sh
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin;export MYSQL_MAJOR=5.6;export MYSQL_VERSION=5.6.29-1debian8
% docker inspect mysql:5.6 | jq --raw-output '.[].Config.Entrypoint | join(" ")'
/entrypoint.sh
% docker inspect mysql:5.6 | jq --raw-output '.[].Config.Cmd | join(" ")'
mysqld

systemd-nspawn でコンテナを起動する。

% sudo systemd-nspawn --ephemeral --directory mysql56 --setenv=MYSQL_ROOT_PASSWORD=notasecret --network-veth
Spawning container mysql56-f4c55f3750654603 on /home/eagletmt/work/.#machine.mysql56f1652daa7d449b0c.
Press ^] three times within 1s to kill container.
root@mysql56-f4c55f3750654603:~#

ここで mysqld を起動しようとすると、systemd によって /run に tmpfs がマウントされてしまっていて /run/mysqld が存在せずエラーになってしまうので、適当に回避する。

root@mysql56-f4c55f3750654603:~# mkdir /run/mysqld
root@mysql56-f4c55f3750654603:~# chown mysql:mysql /run/mysqld

ホスト側から接続できるように設定。

root@mysql56-f4c55f3750654603:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: host0@if28: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 9e:83:dd:e9:23:c2 brd ff:ff:ff:ff:ff:ff
root@mysql56-f4c55f3750654603:~# ip addr add 10.0.0.10/24 dev host0
root@mysql56-f4c55f3750654603:~# ip link set dev host0 up
root@mysql56-f4c55f3750654603:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: host0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 9e:83:dd:e9:23:c2 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.10/24 scope global host0
       valid_lft forever preferred_lft forever
    inet6 fe80::9c83:ddff:fee9:23c2/64 scope link
       valid_lft forever preferred_lft forever

ようやく mysqld を起動。

root@mysql56-f4c55f3750654603:~# source /env.sh
root@mysql56-f4c55f3750654603:~# /entrypoint.sh mysqld
Initializing database
(snip)

ホスト側から接続確認。

% mysql -uroot -h 10.0.0.10 -pnotasecret -e 'SELECT version()'
+-----------+
| version() |
+-----------+
| 5.6.29    |
+-----------+