実行中のLinuxマシンからDockerのベースイメージを生成するスクリプトを書いてみました。
-
このスクリプトは指定されたパッケージの依存性を解決して、パッケージに含まれるコマンドを実行する(プロセスを起動する)のに必要なファイルを集めてDockerのベースイメージを作ります。
-
RPMを使ったシステムなら動くはずですが、今のところCentOS7でしかテストしていません...
-
実用性は低いような気がしますが、古いマシンをDockerに乗せ換えてとりあえず延命したいようなケースでは役に立つかも?
使い方
スクリプトのダウンロード
# git clone https://github.com/hidakanoko/vm2container.git
Cloning into 'vm2container'...
remote: Enumerating objects: 131, done.
remote: Counting objects: 100% (131/131), done.
remote: Compressing objects: 100% (79/79), done.
remote: Total 131 (delta 68), reused 99 (delta 44), pack-reused 0
Receiving objects: 100% (131/131), 34.22 KiB | 0 bytes/s, done.
Resolving deltas: 100% (68/68), done.
Helpの表示
# cd vm2container/
# bin/v2c -h
usage: vm2container [-h] [-p PACKAGE] [-s] [-l] [-a] [-d DIRECTORY]
[-v VERBOSE]
Create docker image from running full Linux environment.
optional arguments:
-h, --help show this help message and exit
-p PACKAGE, --package PACKAGE
-s, --showDeps
-l, --listFiles
-a, --createArchive
-d DIRECTORY, --directory DIRECTORY
-v VERBOSE, --verbose VERBOSE
ERROR, WARN, INFO, DEBUG
パッケージの依存関係をツリー表示する
-p <PACKAGE>
で起動したいコマンドを含むパッケージを指定します。下記サンプルでは/usr/sbin/httpd
を起動するためhttpd
パッケージを指定しています。
-s
で指定されたパッケージの依存関係を表示します。
# bin/v2c -p httpd -s
* Resolving dependency for httpd...
done!
INFO: Total 115 package(s) found
httpd
shadow-utils
audit-libs
libcap-ng
glibc
glibc-common
libselinux
pcre
glibc [*]
libstdc++
libgcc
glibc [*]
libgcc [*]
glibc [*]
libsepol
glibc [*]
bash
ncurses-libs
libstdc++ [*]
libgcc [*]
ncurses-base
glibc [*]
glibc [*]
bash [*]
tzdata
glibc [*]
nss-softokn-freebl
(...omit)
INFO: [*]=Child dependencies are omitted as already described above.
依存性ツリーの中で同じパッケージが繰り返し現れるため、表示済のパッケージの依存関係は省略されます。(末尾に"[*]"がついているパッケージ)
プロセスの起動に必要なファイルを一覧表示する
-l
で指定されたパッケージと、その依存パッケージに含まれるすべてのファイルを一覧表示します。(rpm -ql
で得られるもの)
# bin/v2c -p httpd -l
* Resolving dependency for bash...
done!
INFO: Total 41 package(s) found
* Creating file list of 1 package(s) and its dependent packages...
done!
/
/bin
/bin/egrep
/bin/fgrep
/bin/grep
/bin/sed
/etc
/etc/DIR_COLORS
/etc/DIR_COLORS.256color
/etc/DIR_COLORS.lightbgcolor
/etc/GREP_COLORS
/etc/X11
(...omit)
/usr/share/man/ay/man7 (not found)
/usr/share/man/ay/man7x (not found)
/usr/share/man/ay/man8 (not found)
(...omit)
/var/run
/var/run/setrans
/var/spool
/var/spool/lpd
/var/spool/mail
/var/tmp
/var/yp
INFO: Total 18684 file(s) found, however 13176 file(s) are not present in the file system
パッケージのファイルリストに含まれているものの、ファイルシステム内に存在しないファイルは末尾に"(not found)"がついています。
ユーザーが削除したファイルや、ghostファイルはすでにファイルシステムに存在しないためこのように表示しています。
Dockerのイメージを作成する
-a
でDockerイメージを作成します。
Webコンテンツとhttpdのユーザー設定ファイルを含めるため-d <DIRECTORY>
オプションで/var/www/htmlと/etc/httpd/conf.dをアーカイブに含めるよう指定しています。
# ./bin/v2c -p httpd -d /var/www/html -d /etc/httpd/conf.d -a
* Resolving dependency for httpd...
done!
INFO: Total 115 package(s) found
* Creating file list of 1 package(s) and its dependent packages...
done!
INFO: Total 23237 file(s) found, however 13193 file(s) are not present in the file system
* Creating archive...
done!
INFO: Archive created in /tmp/archive.tgz
Dockerイメージとしてインポートする
生成したアーカイブはそのままDockerにインポートして、ベースイメージとして利用できます。
コンテナ起動時にパラメータを省略できるよう、エントリーポイントとコマンドパラメーターを含めています。
# docker image import /tmp/archive.tgz v2c-httpd:20190302 -c "ENTRYPOINT [\"/usr/sbin/httpd\"]" -c "CMD [\"-DFOREGROUND\"]"
sha256:7908fb6eb6f50618c688a51556b0348de5948fe0a855aa32b515a74182ca1bbe
コンテナを起動する
# docker run -d --rm -p 8080:80 v2c-httpd:20190302
32409c65c9c5ed96103333461eda513fe1d7c9b842dfc4ad17e22258e155e9e6
ブラウザで http://DOCKERHOST:8080/ にアクセスするとApacheのTest Pageが表示されます。
/var/www/htmlに何かコンテンツを置いているのであればそれにアクセスすることもできます。
ざっくりとした仕組み
Dockerはnamespaceやcgroupなどの技術を使って作成したサンドボックス内でプロセスを起動する技術です。そのためイメージの中に必要なファイルがそろっていればプロセスを起動できるはずです。
Dockerのドキュメントにベースイメージの作り方がありますが、これはdebootstrapでパッケージを展開してアーカイブで固めているだけです。
つまり逆に考えれば、実行中の環境でパッケージの依存性を解決して必要なファイルをすべて集めればDockerイメージを作ることが出来るはずです。(という思いつきからこのスクリプトを組んでみました)
v2c
コマンドはパッケージの依存ツリーを解決して(rpm -q --requires
, rpm -q --whatprovides
など)、依存パッケージのファイルをすべて集めて(rpm -ql
)、tgzに固めています。
前述のとおりDockerのベースイメージは基本的に必要なライブラリやコマンド、設定ファイルをtarで固めただけなので、このイメージはそのままベースイメージとしてインポート可能です。
TODO
- パッケージに含まれるドキュメントファイルを除外できるようにする
- DEBパッケージ対応
- ベースイメージ + レイヤーイメージを作れるようにする。例えばベースイメージにはコアパッケージを含めておいて、レイヤーイメージにWebサーバーやMariaDBを起動するためのファイルを含めるような感じ。