PID プロセス群

基本となるプロセスの分離から確認していきます。PIDを分離してps auxを実行する場合のコマンドラインは以下のようになります。


sudo su -l
mkdir -p /opt/container
cd /opt/container
cp -r /usr/bin /usr/lib /usr/lib64 .
unshare -pf chroot . /bin/bash
mkdir -p /proc /dev/pts
mount -t proc proc /proc
mount -t devpts devpts /dev/pts
ps aux

実行結果は以下です。


USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
0              1  0.0  0.0   4332  3696 ?        S    07:22   0:00 bash
0              6  0.0  0.0   6120  3080 ?        R+   07:24   0:00 ps aux

unshare -p bashだけの場合は、bash: fork: Cannot allocate memoryというメッセージが表示されます。このエラーの一番簡単な解決策は、-fオプションをつけることです。

chroot .がないとps auxと打つとホストのプロセスが出てきてしまいます。psが/proc/から読み取った情報を表示するものだからです。chroot .を付けることで、/opt/containerがルート扱いになり、ホストのパスが見えなくなります。psも含めてコマンドが使えなくなってしまうので、cp -r /usr/bin /usr/lib /usr/lib64 .でコマンドをコピーしています。

mkdir -p /proc /dev/ptsとmount -t proc proc /procとmount -t devpts devpts /dev/ptsですが、procはプロセスに関するカーネル情報にアクセスする手段を提供する疑似ファイルシステムで、chroot先のために用意しています。devptsも疑似ファイルシステムでこちらはターミナルを提供するためのものです。

このやり方ではホスト側でmountしてしまっているので、ホストに影響が出てしまいます。--mount-procを付けると、mount名前空間を分離しつつ /proc を再マウントしてくれるのでお手軽です。


unshare -pf --mount-proc /bin/bash
ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.1   7208  3620 pts/0    S    02:22   0:00 /bin/bash
root           9  0.0  0.1   8864  3076 pts/0    R+   02:22   0:00 ps aux

Mount マウントポイント

次にマウントポイントの分離について確認していきましょう。以下のコマンドを実行してみてください。


unshare -m /bin/bash
mount --bind /etc/hosts /root/hosts
mount | grep hosts

結果は以下のようになります。unshareの外では影響を受けないので何も表示されません。

/dev/vda1 on /root/hosts type ext4 (rw,relatime)

これだけではあまり楽しくないので、ルートファイルシステムを入れ替えてみましょう。

ルートファイルシステムの中身を用意する

まずは、ルートファイルシステムの中身を用意します。中身を用意する方法は以下のようにいくつかあります。

  • mmdebstrapやyum install -y --releasever=7 --installroot="/installpath" @base @coreを使って書き出す
  • alpineなどのイメージのダウンロードしてきて展開する
  • DockerのImageを展開する

ここではmmdebstrapを使ってDebian GNU/Linuxのイメージの中身を書き出す方法をやってみます。mmdebstrapはdebootstrapを高速化し、rootでなくても実行できるように改良されるなど、多様化したニーズに対応しています。

mmdebstrapで指定できるのはDebian GNU/Linuxのパッケージですので、Ubuntuから実行する場合はキーリストをダウンロードして--aptopt='Dir::Etc::Trusted "/usr/share/keyrings/debian-archive-keyring.gpg"'のように指定する必要があります。


apt-get update
apt-get install mmdebstrap
apt-get install debian-archive-keyring
mkdir ./images
cd ./images
mmdebstrap stretch ./ --aptopt='Dir::Etc::Trusted "/usr/share/keyrings/debian-archive-keyring.gpg"'

中身をみてみましょう。一通りそろっていることが分かります。

# ll
total 84
drwxr-xr-x 21 root root 4096 Nov  7 08:26 ./
drwx------  5 root root 4096 Nov  7 08:23 ../
drwxr-xr-x  2 root root 4096 Nov  7 08:27 bin/
drwxr-xr-x  2 root root 4096 Jul 10  2020 boot/
drwxr-xr-x  4 root root 4096 Jul 10  2020 dev/
drwxr-xr-x 50 root root 4096 Nov  7 08:27 etc/
drwxr-xr-x  2 root root 4096 Jul 10  2020 home/
drwxr-xr-x 10 root root 4096 Nov  7 08:27 lib/
drwxr-xr-x  2 root root 4096 Nov  7 08:26 lib64/
drwxr-xr-x  2 root root 4096 Nov  7 08:26 media/
drwxr-xr-x  2 root root 4096 Nov  7 08:26 mnt/
drwxr-xr-x  2 root root 4096 Nov  7 08:26 opt/
drwxr-xr-x  2 root root 4096 Jul 10  2020 proc/
drwx------  2 root root 4096 Nov  7 08:26 root/
drwxr-xr-x  3 root root 4096 Nov  7 08:26 run/
drwxr-xr-x  2 root root 4096 Nov  7 08:27 sbin/
drwxr-xr-x  2 root root 4096 Nov  7 08:26 srv/
drwxr-xr-x  2 root root 4096 Jul 10  2020 sys/
drwxrwxrwt  2 root root 4096 Nov  7 08:27 tmp/
drwxr-xr-x 10 root root 4096 Nov  7 08:26 usr/
drwxr-xr-x 11 root root 4096 Nov  7 08:26 var/