LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術

第17回 LXCの構築・活用 [4] ― 一般ユーザによるLXCコンテナの利用

この記事を読むのに必要な時間:およそ 7 分

各ユーザのLXCの設定ファイル

それでは一般ユーザでコンテナを起動するためのLXCの準備をしていきましょう。

第14回でも簡単に方法に触れていますが,ここでもう一度じっくり手順を追ってみます。

まずは設定ファイルを置くディレクトリがない場合は作成しましょう。

$ mkdir -p ~/.config/lxc

Ubuntuではシステム設定ファイルであるlxc.confはデフォルトでは使われていません。コンテナイメージが置かれる場所を変えたいなど,必要があれば~/.config/lxc/lxc.confファイルを作成して設定を書いておきましょう。設定についてはman lxc.system.confをご覧ください。

次はコンテナのデフォルト設定ファイルであるdefault.confです。これはLXCパッケージをインストールしたときに作成されますので,それを元に一般ユーザでコンテナを起動する際に必要な設定を追加すれば良いでしょう。

$ cp /etc/lxc/default.conf ~/.config/lxc/default.conf
$ vi ~/.config/lxc/default.conf

ここで追加する設定は/etc/subuid/etc/subgidで行ったようなユーザ名前空間を使うときのマッピング情報です。この設定はlxc.id_mapです。

この設定は4つのフィールドから成っています。最初から順に以下のようになります。

  • uidのマッピングの場合は"u",gidのマッピングの場合は"g"の一文字
  • あとの3つは第16回で紹介した/proc/[PID]/uid_map/proc/[PID]/gid_mapと同じ書式

たとえばUIDをマッピングする場合で,コンテナ内のrootをコンテナ外で100000のUIDにマッピングし,コンテナ内で65536個のUIDを使う場合は

lxc.id_map = u 0 100000 65536

となります。

GIDにも同様のマッピングをすると,~/.config/lxc/default.confは以下のようになります。

# /etc/lxc/default.conf に書かれていた設定
lxc.network.type = veth
lxc.network.link = lxcbr0
lxc.network.flags = up
lxc.network.hwaddr = 00:16:3e:xx:xx:xx
# このあとが一般ユーザ向けに追加する行
lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536

コンテナの作成

一般ユーザのコンテナイメージと設定ファイルは,システム設定ファイルで場所を設定していない場合は~/.local/share/lxcにコンテナ名のディレクトリを作成してそのディレクトリ以下に置かれます。

このディレクトリ(~/.local/share/lxc)がない場合はコンテナ作成時に自動的に作成されますので,設定ファイルの準備ができたら早速コンテナを作成してみましょう。

一般ユーザ権限の場合は,第7回第8回で紹介したダウンロードテンプレートを使います。

lxc-ubuntulxc-centosなどの各ディストリビューション用のテンプレートは使えません。これは,テンプレート内でユーザ名前空間内のrootが許可されていない処理を実行する場合が多いためです。

一般ユーザでコンテナを作成する場合もrootで実行する場合と同じようにlxc-createを使います。使い方もrootで実行する場合と同じです。

$ lxc-create -n ct01 -t download -- -d ubuntu -r trusty -a amd64
Using image from local cache
Unpacking the rootfs

---
You just created an Ubuntu container (release=trusty, arch=amd64, variant=default)

To enable sshd, run: apt-get install openssh-server

For security reason, container images ship without user accounts
and without a root password.

Use lxc-attach or chroot directly into the rootfs to set a root password
or create user accounts.

以上はUbuntu Trusty(amd64)のコンテナイメージをダウンロードして作成た例です。

ところで上記の例で表示されているように,ダウンロードテンプレートを使ってダウンロードしたコンテナイメージにはユーザアカウントは作成されておらず,rootのパスワードも設定されていません。

以前はダウンロードしたイメージには各ディストリビューションのテンプレートで設定されるデフォルトのユーザやパスワードが設定されていました。しかし第14回で田向さんによる説明があった通り,コンテナの初期パスワードがセキュリティ上の問題として報告されることが多くなり,ダウンロードテンプレート用のイメージではrootのパスワードや初期ユーザは設定されなくなりました。

作成されたコンテナディレクトリを確認しておきましょう。

$ ls -F ~/.local/share/lxc
ct01/
$ ls -F ~/.local/share/lxc/ct01
config  rootfs/

以上のようにroot権限で/var/lib/lxc以下に作成されたコンテナと同様に作成されています。

設定ファイルは以下のようになっています。

$ cat ~/.local/share/lxc/ct01/config 
  :(略)
# Distribution configuration
lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.include = /usr/share/lxc/config/ubuntu.userns.conf
lxc.arch = x86_64

# Container specific configuration
lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536
lxc.rootfs = /home/ubuntu/.local/share/lxc/ct01/rootfs
lxc.utsname = ct01

# Network configuration
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = lxcbr0
lxc.network.hwaddr = 00:16:3e:9f:c4:5a

root権限で作成したコンテナと一般ユーザで作成したコンテナの違いはubuntu.userns.confをincludeしている部分です。これは一般ユーザでコンテナを作成する際に使用する共通の設定をまとめたファイルで,ディストリビューションごとに準備されています。

$ ls /usr/share/lxc/config/*.userns.conf
/usr/share/lxc/config/centos.userns.conf
/usr/share/lxc/config/debian.userns.conf
/usr/share/lxc/config/fedora.userns.conf
/usr/share/lxc/config/gentoo.userns.conf
/usr/share/lxc/config/oracle.userns.conf
/usr/share/lxc/config/plamo.userns.conf
/usr/share/lxc/config/ubuntu-cloud.userns.conf
/usr/share/lxc/config/ubuntu.userns.conf

たとえばubuntuの場合以下のような内容です。デバイスファイルを作成するなどのユーザ名前空間内では実行できない処理の代わりに,ホストOSのファイルをバインドマウントする設定などが書かれています。

$ cat /usr/share/lxc/config/ubuntu.userns.conf 
# CAP_SYS_ADMIN in init-user-ns is required for cgroup.devices
lxc.cgroup.devices.deny =
lxc.cgroup.devices.allow =

# We can't move bind-mounts, so don't use /dev/lxc/
lxc.devttydir =

# Extra bind-mounts for userns
lxc.mount.entry = /dev/console dev/console none bind,create=file 0 0
lxc.mount.entry = /dev/full dev/full none bind,create=file 0 0
lxc.mount.entry = /dev/null dev/null none bind,create=file 0 0
lxc.mount.entry = /dev/random dev/random none bind,create=file 0 0
lxc.mount.entry = /dev/tty dev/tty none bind,create=file 0 0
lxc.mount.entry = /dev/urandom dev/urandom none bind,create=file 0 0
lxc.mount.entry = /dev/zero dev/zero none bind,create=file 0 0

# Extra fstab entries as mountall can't mount those by itself
lxc.mount.entry = /sys/firmware/efi/efivars sys/firmware/efi/efivars none bind,optional 0 0
lxc.mount.entry = /proc/sys/fs/binfmt_misc proc/sys/fs/binfmt_misc none bind,optional 0 0

# Default seccomp policy is not needed for unprivileged containers, and
# non-root users cannot use seccmp without NNP anyway.
lxc.seccomp =

著者プロフィール

加藤泰文(かとうやすふみ)

2009年頃にLinuxカーネルのcgroup機能に興味を持って以来,Linuxのコンテナ関連の最新情報を追っかけたり,コンテナの勉強会を開いたりして勉強しています。英語力のない自分用にLXCのmanページを日本語訳していたところ,あっさり本家にマージされてしまい,それ以来日本語訳のパッチを送り続けています。

Plamo Linuxメンテナ

Twitter:@ten_forward
技術系のブログ:http://tenforward.hatenablog.com/