coreosのisoイメージファイルからdockerベースイメージを作ってみた

この記事はフィードフォースエンジニア Advent Calendar 2015、7日目の記事です。
6日目はtjinjin氏のオフィス移転に向けてインフラエンジニアが検討したことでした!

改めましてこんにちは。アウトドア派のLorentzcaです。
先日、会社の忘年会が中華レストランでありまして、私は体調がベストではなかったのですがそんなことは気にせず紹興酒をたくさん飲んだところ次の日体調も良くなり酒も残っていなかったので紹興酒は体にいいことがわかりました。これからも機会を逃さず紹興酒を口にしていこうと思います。

さて、今回の記事のネタとして、「coreosのisoイメージファイルからdockerベースイメージを作ってみた」を考えておりました。

既存のdockerのベースイメージから新しいイメージを作成する方法に関してはやり方を書いた記事もたくさんあり、わかりやすい公式のドキュメントもあるのですが、

大元となるdockerベースイメージそのものの作成方法に関してはあまり情報がなく(あるにはあるのですが特定のディストリビューションに限定されている)、面白そうだったからです。

しかし!何の成果も得られませんでした!!

というのは言い過ぎで、ちょっとは得るものもあったので記事化に踏み切ります!!!

未練がましく記事書きながら色々試していたらうまく行ったので当初の予定通り「coreosのisoイメージファイルからdockerベースイメージを作ってみた」をお送りします。

環境

作業環境

  • Mac OSX El Capitan
  • Docker 1.9.1

対象のcoreos

  • CoreOS 835.8.0 (stable)

準備

まずはdocker-machin立ち上げてdockerを使えるようにする。

$ docker-machine create -d virtualbox dev
Running pre-create checks...  
Creating machine...  
(dev) OUT | Creating VirtualBox VM...
(dev) OUT | Creating SSH key...
(dev) OUT | Starting VirtualBox VM...
(dev) OUT | Starting VM...
Waiting for machine to be running, this may take a few minutes...  
Machine is running, waiting for SSH to be available...  
Detecting operating system of created instance...  
Detecting the provisioner...  
Provisioning created instance...  
Copying certs to the local machine directory...  
Copying certs to the remote machine...  
Setting Docker configuration on the remote daemon...  
To see how to connect Docker to this machine, run: docker-machine env dev

$ docker-machine ls
NAME   ACTIVE   DRIVER       STATE     URL                         SWARM  
dev    -        virtualbox   Running   tcp://192.168.99.100:2376

$ eval "$(docker-machine env dev)"

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES  

coreosのisoファイルをダウンロードしておく。

$ wget http://stable.release.core-os.net/amd64-usr/current/coreos_production_iso_image.iso

coreosのdockerベースイメージ作成に挑戦

dockerベースイメージの概要

とりあえず何をすればいいかわからないので調査。

  • ベースイメージはディレクトリツリーをtar等で固めたファイルから作成できる
  • ベースイメージ+差分がイメージとして保存される
    • 例: ベースイメージにapache入れてdocker commitしたものがイメージ
  • ベースイメージを作成するコマンドとして、docker importコマンドが用意されている

isoの中身をそのままtarで固めてdockerベースイメージを作成

まず何も考えずisoの中身そのままtarで固めてみた。
流石にこの方法ではダメだった。

isoをファイルをマウント。

$ hdid coreos_production_iso_image.iso
/dev/disk4                                              /Volumes/CDROM

マウントしたisoファイルの中身をtarで固めてdocker importする。

$ sudo tar -C /Volumes/CDROM -c . | docker import - lorentzca/test
Password:  
0dc6429db2122bd9a6ac92ea35a8aaf15df4e204df68e85efdc4beff9ec8a5a9

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE  
lorentzca/test      latest              0dc6429db212        About a minute ago   222.1 MB  

このようにコマンドが存在しないと出る。

$ docker run -t -i --rm lorentzca/test ls
exec: "ls": executable file not found in $PATH  
Error response from daemon: Cannot start container 77423642119a6750de9b742e9f948d36811022707487803f4ceeaba243a3af11: [8] System error: exec: "ls": executable file not found in $PATH  

dockerベースイメージの概要にあるように、ルートファイルシステムがtarで固まってる必要がある。isoファイルの中身は、

coreos/  
isolinux/  
syslinux/  

のようになっておりルートファイルシステムになっていないので出来なくてので当然か…。coreos以下にvmlinuz等のカーネルを内包したファイルがあり、OSインストールの過程でこれらを展開したものがルートファイルシステムになるはず。

vmにインストールしてからルートファイルシステムをtarで固めてみる 1

coreosのisoファイルからvirtualboxを使ってvmを作成。

その後coreos上から以下を実行。無限ループにならないよう作成されるファイル名は除外。

$ sudo su -
# cd /
# tar -cvpzf rootfs.tar.gz --exclude=/rootfs.tar.gz /

出来上がったrootfs.tar.gzをvmからダウンロードし、以下を実行。

$ docker import rootfs.tar
Error response from daemon: Untar re-exec error: exit status 1: output: unexpected EOF  

失敗…。

何かヒントがあるかと思い、ダウンロードしたrootfs.tar.gzを展開してみたところ、proc/kcoreを展開するところで止まった。kcoreってなんだろうと思いvm内に入りls -lh /proc/kcoreを見たところなんと128TB…!?

これはまずいと思ったところでMacさんがブラックアウト&バルーン。強制終了。

呆然としつつkcoreでググると、どうやら物理メモリを示すファイルらしい。メモリのファイルイメージ的なもの?なぜ128TBとなっているのかよくわからないがとにかく要注意人物。

この辺で心が折れた orz

vmにインストールしてからルートファイルシステムをtarで固めてみる 2

vm作るところまでは同じ。

記事書きながら、coreosには最初からdockerが入っているから、tarでファイル固めてダウンロードする手間はいらないなと思い、以下を実行。

$ sudo su -
# cd /
# tar cv --exclude ./proc/kcore . | docker import -

kcoreを除外しないと容量足りないよ!と怒られる。kcore除外しなくても足りないと言われるので、vm作成時にメモリを2GBくらいにしとくと良い。

するとどうやらimportに成功…。

疑いつつdocker runしてみたら動いた!!!

localhost / # docker run -t -i --rm 84649b5a927f ls  
bin   dev  home  lib64    mnt   root  sbin  sys  usr  
boot  etc  lib     media  proc  run   srv   tmp  var  

さっそくイメージにlorentzca/coreタグを付け直してからdocker hubにプッシュ。

$ docker login
$ docker push lorentzca/coreos

プッシュしたイメージを使ってみる

Macでも動かしてみる。

まずはpull。

$ docker pull lorentzca/coreos

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE  
lorentzca/coreos    latest              115b66fa4f8c        14 minutes ago      596.7 MB  

runしてみる。

$ docker run -t -i --rm lorentzca/coreos ls
bin   dev  home  lib64    mnt   root  sbin  sys  usr  
boot  etc  lib     media  proc  run   srv   tmp  var  

グッド!

まとめ

  • dockerのベースイメージがどういうものか概要を紹介しました
  • coreosのisoファイルを使ってdockerのベースイメージを作成しました
    • いったんvmにインストールしてからベースイメージ化してるのでタイトル詐欺説はある
  • ルートファイルシステムを固めるにあたり/proc/kcoreは要注意人物
  • ディストリビューションにかかわらずベースイメージの作成ができそうなことがわかった
  • vmにインストールしてからルートファイルシステムをtarで固めてみる 1の方式でも、固めるときkcore除いたりすればちゃんと使えるファイルができたのかも…
  • 人間諦めないことが肝心

おまけ

coreosをインストールしたvmの実体ファイルが異様に小さい

色々試行錯誤中に発見。なんでこんなにvmファイル(coreos.vdi)のサイズが小さいんだ…!?

$ du -sh ~/VirtualBox\ VMs/coreos/*
352K    /Users/cocoa/VirtualBox VMs/coreos/Logs  
8.0K    /Users/cocoa/VirtualBox VMs/coreos/coreos.vbox  
8.0K    /Users/cocoa/VirtualBox VMs/coreos/coreos.vbox-prev  
2.0M    /Users/cocoa/VirtualBox VMs/coreos/coreos.vdi  

coreosはほぼすべてメモリ上(tmpfs)にファイルを展開し動作していたためだった!!

core@localhost ~ $ df -h  
Filesystem      Size  Used Avail Use% Mounted on  
devtmpfs        898M     0  898M   0% /dev  
tmpfs          1003M     0 1003M   0% /dev/shm  
tmpfs          1003M   17M  987M   2% /run  
tmpfs          1003M     0 1003M   0% /sys/fs/cgroup  
tmpfs          1003M  6.8M  997M   1% /  
/dev/loop0      183M  183M     0 100% /usr
tmpfs          1003M     0 1003M   0% /media  
tmpfs          1003M     0 1003M   0% /tmp  

vm起動時に毎回iso上(たぶん)からvmlinuzやcpio.gzファイルを展開して配置しているようだった。ディスクにインストールする方法として、coreos-installコマンドがある。

ubuntuやcentosのベースイメージ化

debian系は最小構成のルートファイルシステムを指定したディレクトリにインストールすることができるdebootstrapコマンドを使えば簡単に作成できる。

以前debootstrapを使った方法は、debianで試してみたことがある。

redhat系はdebootstrapのようなものがなく、結構めんどくさそうだが、dockerからスクリプトが用意されている。

参考


さて!明日は再びhapickyさんが担当です!楽しみ!!