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/