リモートLinuxマシンのDockerイメージを作る方法

(Last Updated On: )

手っ取り早くリモートのLinuxマシン(私の場合はVMwareの仮想マシン)からDockerイメージを作りたくなったのでその手順です。

最低限の手順なのでサービス(nginxやhttpd)を動かしたい場合はカスタマイズが必要です。不必要なファイルもコンテナに入るので、サイズを小さくする場合は適当にファイルを削除してください。

きっちり作るにはベースOSに必要最低限のパッケージだけ入れたコンテナを作り、そのコンテナに必要なパッケージを入れて作ります。しかし、コンテナが大きくても構わない、アップデートをベースのコンテナとDockerfileのビルドで行わなくても構わない、といった際にサクっと作るには便利です。

必要な物

ローカル、リモートともにLinuxであることを前提にしています。

  • rsync – リモートとローカル両方
  • ssh – リモートにsshdとローカルにssh
  • docker – ローカル

作る手順

以下のシェルスクリプトを実行し、Docker Imageの元になるディレクトリを作成します。カレントディレクトリにファイルが保存されるので、適当なディレクトリで実行します。

#!/usr/bin/env bash

# Set remote linux host name here
target="remote.example.com"

# Add more --exclude if you have more directories aren't needed
rsync -avz \
        --exclude '/backup' \
        --exclude '/boot' \
        --exclude '/dev' \
        --exclude '/proc' \
        --exclude '/sys' \
        --exclude '/run' \
        --exclude '/selinux' \
        --exclude '/tmp' \
        --exclude '/cgroup' \
        --exclude '/mnt' \
        --exclude '/media' \
        --delete -e ssh \
        "$target":/ "$target"

# Make directories needed
mkdir -p "$target"/{dev,tmp,run}
chmod 1777 "$target"/tmp
chmod 755 "$target"/{dev,run}

# Create basic devices
mknod -m 600 "$target"/dev/console c 5 1
mknod -m 600 "$target"/dev/initctl p
mknod -m 666 "$target"/dev/full c 1 7
mknod -m 666 "$target"/dev/null c 1 3
mknod -m 666 "$target"/dev/ptmx c 5 2
mknod -m 666 "$target"/dev/random c 1 8
mknod -m 666 "$target"/dev/tty c 5 0
mknod -m 666 "$target"/dev/tty0 c 4 0
mknod -m 666 "$target"/dev/urandom c 1 9
mknod -m 666 "$target"/dev/zero c 1 5

$targetディレクトリの中にリモートファイルが保存されます。

ファイルのコピーが完了したら、次のコマンドでイメージを作ります。

# tar -c -C "remote.example.com" . | docker import - my-image:version

remote.example.com は上のシェルスクリプトで設定した$targetと同じにします。

作ったイメージのbashを起動してコンテナが動作することを確認します。

# docker run -it --rm my-image:version bash

イメージ作成後の作業

前提として以下を知っているとします。

  • Dockerfile の書き方とdockerの使い方
  • docker-compose.ymlの書き方とdocker-composeの使い方

rsyncでコピーしたファイル全てがイメージの中に入ってしまいます。普通は

  • /homeの中のデータ
  • /varの中のwwwやpgsql、mysqlといったデータ
  • /etcの中の一部の設定ファイル

をdocker-compose.ymlのボリュームにして、変更を恒久的に保存したいファイル類を定義します。rsyncでコピーしたファイル/ディレクトリを丸ごとローカルファイルシステムボリュームにするだけです。

これらはイメージの中に入れる必要がないので別のディレクトリに移動します。

manファイルなどのドキュメント、rpmのキャッシュデータなど、色々と不必要な物があるハズなので要らない物は消します。

この作業を終わらせたら、もう一度 docker import コマンドを実行して小さくしたイメージを作ります。

後はDockerfileでコンテナに保存しない設定ファイルをコピー、起動したいサービスを定義し、docker-compose.ymlを作って必要なディレクトリをボリュームとしてマウントする定義を書きます。

必要な設定/定義を作った後は docker-compose up -d でコンテナを起動すればリモートマシンと同じ環境のコンテナが起動します。

Dockerを知らない方向け

コンテナは仮想マシンではありません。必要な「コマンド」だけを起動します。dnf/yum/aptなどは動作しますが、基本的にsystemdやjournaldやfirewalldは使いません。

例えば、httpdを起動したい場合はsystemctlを使わずに

httpd -D FOREGROUND

などとして起動します。他のサービスも同様です。複数のサービスをコンテナの立ち上げと同時に起動したい場合、色々方法がありますが、エントリポイントとなるシェルスクリプトを作って起動します。

詳しくはDockerfile、docker-compose.ymlの書き方のマニュアルを参照してください。

投稿者: yohgaki