ということをやったのでその記録。

都度buildしたらアカンのか?


Dockerを用いて環境を作成する際に都度buildすると下記のような問題点に遭遇することがあります。

  • 公式のイメージを利用している場合にlatestのタグを指定してると意図せずバージョンが上がる
  • Dockerfileその他でインストールしているパッケージ・ライブラリが非対応のバージョンに変わっていたりする
  • 使用しているパッケージ・ライブラリのリポジトリのURLが変わっていたりする

別に都度修正すればよいのですが、特に本番だと使用しているライブラリバージョンをむやみに上げたくないということもありますし、今動いている環境と同様の環境を作成したいということも多々あるでしょう。こういった問題を避けるにはその時点のイメージを保存しておいて、そこから再度コンテナを作成するというのが望ましいと思います。

saveとexport


で、こういうのに対応するのにはdocker savedocker exportを使います。saveexportの違いですが、たぶん下記の通りです。たぶんです。ちょっと自信ない。

- save export
保持する情報 全てのレイヤー情報 そのコンテナのファイルシステムを丸ごと
再作成コマンド load import
再作成方法 イメージからイメージ コンテナからイメージ再作成
形式 tar tar

これの違い書いても解らないですよね。私は解らなかった。

ですのでsaveexportを使用してイメージを再作成してみました。以下は実際のJenkins2.32.3の公式イメージに追加でいろんなパッケージをインストールしたものをsaveexportで保存して再作成したものをdocker imagesで確認したものです。

1
REPOSITORY  TAG     IMAGE ID      CREATED         SIZE
<none>      <none>  86b46bde2552  10 minutes ago  1.2GB    ← export・importで再作成したイメージ
jenkins     2.32.3  cc67e043e7fc  8 days ago      1.23GB   ← save・lodeで再作成したイメージ

上がexportからimportで再作成したものです。この場合はコンテナのファイルシステムを基にしたイメージの新規作成になるのでリポジトリ名・タグ名などは消滅してます。

対して下がsaveからloadで再作成したものです。この場合はリポジトリ名・タグ名はそのまま残ってますが、レイヤーの情報を保持している分、サイズが大きめです。

なお、いろいろ追加しているのでかなりサイズが大きくなっていますが、公式のJenkinsのイメージはここまでサイズは大きくないです。

コマンド


オプションは出力先を指定するくらいのものしかないので省略。

save & load

1
2
docker save repository:tag  > example_save.tar
docker load < example_save.tar

なお、IMAGE IDでsaveするとload後にREPOSITORYとTAGがnoneになるようです

export & import

1
2
docker export container_name > example_export.tar
docker import example_export.tar

どっちつかうのか?


単純にサイズ小さくして最新の情報だけ必要ならexportでいいような気がします。メタ情報も残したいならsaveでいいんじゃないでしょうか。たぶん。まだ、運用に至ってないので自信ないですが。

データの永続化


saveexportもデータをvolumesでホストからマウントしている場合はそれらのデータは別途管理しておく必要があります。つまり、まるまる環境をそのまま再現するにはsaveexportで環境を再作成してかつ、元の環境でホストからマウントしていたデータをvolumesでマウントする必要があります。

ちなみにsaveからloadした際にvolumesave前にホストからマウントしていた通りにパスを指定しないとdocker: Error response from daemon: cannot mount volume over existing file, file exists ...というエラーでコンテナを起動できませんでした。save前の環境通りにホストからマウントすれば起動は起動はできるのですが…。この辺、まだそこまで調べてないので詳しくわかれば別記事で書こうと思います。