はじめに
CentOS 7のDockerコンテナ内でsystemdを使ってサービスを起動するに後から追記したが、9月頭くらいから、Dockerの公式CentOS 7イメージの中からsystemdが消え、fakesystemdなるものがインストールされるようになった。
それでサービスを上げることができなくなったので、どう対応したものかしばらく調べる必要があったわけだけど、その過程でDockerの公式CentOSイメージの中身が何によって決まっているかを知ることができたので、以下に示す。
本文
次がイメージの「設計書」たるkickstartファイル等の置き場となる。
https://github.com/CentOS/sig-cloud-instance-build
Dockerのものに限れば次である。
https://github.com/CentOS/sig-cloud-instance-build/tree/master/docker
RHEL系なので例によってkickstartファイルである。
このkickstartファイルに従ってOSの自動インストールを行ったディスクイメージを変換してdockerイメージにするわけである。
このkickstartファイルは大体以下のようなことがわかっていれば読むことができる。
- %package - %end間は「最小限のインストール」をベースとして増減するパッケージ名を列記する。
- 「最小限のインストール」になるのは「--nobase」オプションが付いているから。ただし、CentOS 7では付いていなくても「最小限のインストール」になるようだ。
- 「--excludedocs」オプションはドキュメント系パッケージを除外する。
- パッケージ名は"-"が最初に付いていればインストールをしない。付いていなければ(追加で)インストールをする。
- 「最小限のインストール」に何が含まれるかはCentOS 7インストーラの「ソフトウェアの選択」の中身を調べてみたを参照のこと(CentOS 7についてしか書いてないけど……)。
- %post - %end間はインストール終了直前に実行されるコマンド。
- 他の部分は字面でわかると思われる。わからない箇所は以下で確認できる。
- CentOS 5: https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/5/html/Installation_Guide/s1-kickstart2-options.html
- CentOS 6: https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Installation_Guide/s1-kickstart2-options.html
- CentOS 7: https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/7/html/Installation_Guide/sect-kickstart-syntax.html
CentOS 7のkickstartファイルである https://github.com/CentOS/sig-cloud-instance-build/blob/master/docker/centos-7.ks を見ると、しっかりsystemdに"-"が付いていてインストールされないことがわかるし、fakesystemdが追加されているのも見える。
もっとも、パッケージは依存関係があるので実際に何がインストールされるのかは読みにくい部分がある。
また、%post - %end間でyum removeが何度も実行されているので、%package - %end間に挙げられたパッケージ内容とは変わってしまっている。
CentOS 7のDockerコンテナ内でsystemdを使ってサービスを起動するにコメント頂いたinitscriptsは、kmodをyum removeしたところで依存関係により一緒くたに削除されているようだ。
おまけ
このkickstartファイルを使って(あるいはkickstartファイルを書き換えて)、実際にDockerイメージを作ってみたい場合、以下のような手順でできるようだ。
ただし、本物の公式イメージを作っている人はkickstartファイルと同じディレクトリにあるimg2docker.shを使用していると思われるが、私のやり方では上手く行かないので、何かが違うことは間違いない。
- kvmとvirt-installとdockerがインストールされた環境を用意する。
- 私はkvm, virt-installとdockerとで別コンピュータにインストールした。実際のところkvm環境は随分前に作ったもので手順を書き留めていなかったので正しい手順を示すことができない。たぶん
yum install qemu-kvm libvirt python-virtinst bridge-utils virt-install
してlibvirtdサービスを起動したはずだ。 - dockerの方はdockerをインストールしてdockerサービスを起動した。
- kvmがインストールされたコンピュータにブリッジを作成する。
- ブリッジの作り方についてはpipeworkを使わずにDockerコンテナに任意の固定IPアドレスを割り当てるを参照のこと(これもCentOS 7についてしか書いてないけれど)。
- 私は使っていないが、kvmがインストールされたコンピュータを再起動するだけで勝手に作られるvirbr0ブリッジでも良いはずだ。
- 以下のようにしてkvm上でkickstartファイルを使ってOSのインストールを行う。これは結構時間が掛かる(数十分?)。なおブリッジ名はbr0にした。
# qemu-img create /opt/c7.img 8G
# virt-install -n c7 \
--connect=qemu:///system \
-r 2048 \
--vcpus 1 \
--disk /opt/c7.img \
-w bridge=br0 \
--graphics vnc,listen=0.0.0.0,port=5991 \
--noautoconsole \
--noreboot \
-v \
--accelerate \
--os-type linux \
--os-variant rhel7 \
-l http://ftp.iij.ad.jp/pub/linux/centos/7/os/x86_64 \
-x 'ks=https://raw.githubusercontent.com/CentOS/sig-cloud-instance-build/master/docker/centos-7.ks console=tty0 console=ttyS0,115200n8 keymap=ja'
- virt-manager等で様子を見ていれば、シャットダウンされたらOSインストールが終わったことがわかるので、このイメージファイル(上記では「/opt/c7.img」)をdocker機に持って行って以下のようにする。本当はここでimg2docker.shを使いたかったのだけど。
- 参考: http://yudoufu.github.io/blog/2012/04/28/vm-mount-memo/
# losetup /dev/loop2 /opt/c7.img
# kpartx -av /dev/loop2
# mount /dev/mapper/loop2p1 /mnt
# cd /mnt
# tar --numeric-owner -c . | docker import - c7
- 上記の最後の「c7」はdocker imageのタグである(ので、適当に変えて良い)。よって以下のように起動できる。
- 何故か最初の1回は上手く起動しない。
# docker run -it c7 /bin/bash
- なお、/mntのマウントは以下のように解除する。
# cd
# umount /mnt
# kpartx -dv /dev/loop2
# losetup -d /dev/loop2