Skip to content

Instantly share code, notes, and snippets.

@hayajo
Last active March 19, 2021 15:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hayajo/36a830ed23266d0728731737c658f4b7 to your computer and use it in GitHub Desktop.
Save hayajo/36a830ed23266d0728731737c658f4b7 to your computer and use it in GitHub Desktop.
pivot_rootとoverlayfsのデモ

機能チェック

  • [x]名前空間
  • [x]バインドマウント
  • [x]chroot, pivot_root
  • [x]capability
  • [ ]cgroup
  • [x]Unionファイルシステム
  • [ ]veth
  1. ルートファイルシステムの準備

ルートファイルシステム内にlibcapとbashが必要です。 centosubuntuでは公式のイメージに含まれています。

$ docker export $(docker create centos) | gzip > centos.tar.gz

公式のalipneイメージを利用する場合は自前にインストールが必要です。

docker export \
$((docker rm -f alpine; docker run --name=alpine alpine /bin/sh -c 'apk update; apk add libcap bash') 1>/dev/null 2>&1 && echo alpine) \
| gzip > alpine.tar.gz
  1. ルートファイルシステムの展開

Vagrantの仮想環境でルートファイルシステムを展開します。

$ vagrant up; vagrant ssh
vagrant$ mkdir centos
vagrant$ tar xzf /vagrant/centos.tar.gz -C centos
  1. コンテナの実行

展開したルートファイルシステムを利用してコンテナを実行します。

vagrant$ sudo /vagrant/test-pivot_root.sh centos # ~/centosディレクトリをルートファイルシステムとして利用

ちなみにルートファイルシステムを指定しない場合はシステムルート(/)をルートファイルシステムとしてコンテナを実行します。

vagrant$ sudo /vagrant/test-pivot_root.sh        # システムルート(/)をルートファイルシステムとして利用
#!/bin/bash
set -e
set -x
lowerdir=$(readlink -f ${1:-/})
basedir=$(mktemp -d /tmp/$(basename $0).XXXXXXXX)
upperdir=$basedir/upper
workdir=$basedir/work
rootdir=$basedir/root
procdir=$basedir/proc
# see. https://github.com/opencontainers/runc/blob/master/libcontainer/SPEC.md#security
dropcaps=${DROPCAPS:-cap_net_broadcast,cap_sys_module,cap_sys_rawio,cap_sys_pacct,cap_sys_admin,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_audit_control,cap_mac_override,cap_mac_admin,cap_net_admin,cap_syslog,cap_dac_read_search,cap_linux_immutable,cap_ipc_lock,cap_ipc_owner,cap_sys_ptrace,cap_sys_boot,cap_lease,cap_wake_alarm,cap_block_suspend}
uid=${CUID:-0}
gid=${CGID:-0}
unshare -mu /bin/sh -c "
mkdir $upperdir $workdir $rootdir $procdir
mount --make-rprivate /
mount -t overlay -o upperdir=$upperdir,lowerdir=$lowerdir,workdir=$workdir overlayfs $rootdir
cp --remove-destination /etc/resolv.conf /etc/hosts $rootdir/etc/
mount -t proc -o ro,nosuid,nodev,noexec proc $procdir
mount -t proc -o rw,nosuid,nodev,noexec,relatime proc $rootdir/proc
mount --bind $procdir/sys $rootdir/proc/sys
mount --bind $procdir/sysrq-trigger $rootdir/proc/sysrq-trigger
mount --bind $procdir/irq $rootdir/proc/irq
mount --bind $procdir/bus $rootdir/proc/bus
umount -l $procdir
mount --rbind /sys $rootdir/sys
mount --rbind /dev $rootdir/dev
cd $rootdir
mkdir oldroot
pivot_root . oldroot
cd /
umount -l /oldroot
rmdir /oldroot
exec capsh --drop=$dropcaps --chroot=. --gid=$gid --uid=$uid -- -l # capshはオプションの重要(とくにchrootやgid,uid)が重要。権限が必要な物から先に指定する。
"
rm -rf $basedir
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure(2) do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://atlas.hashicorp.com/search.
config.vm.box = "boxcutter/ubuntu1604"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
# config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
# vb.memory = "1024"
# end
#
# View the documentation for the provider you are using for more
# information on available options.
# Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
# such as FTP and Heroku are also available. See the documentation at
# https://docs.vagrantup.com/v2/push/atlas.html for more information.
# config.push.define "atlas" do |push|
# push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
# end
# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# sudo apt-get update
# sudo apt-get install -y apache2
# SHELL
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment