ホスト側から run
中の Docker コンテナ内へ、ディレクトリごとコピーします。
背景
Docker を運用している上で、動いているコンテナの中にファイルを送り込みたくなったことはないでしょうか。ないですか? 残念ながらあるところにはあるのです。とりあえず今回はあるということにして進みます。
docker cp
コマンドを使用すれば「コンテナからホストへ」のファイル転送は可能ですが、逆に「ホストからコンテナへ」の転送手段は公式では提供されていないはずです。docker run
時に -v
オプションを付けておいて、マウントされたディレクトリをファイルの受け渡し場所として使用することも不可能ではないですが、ご存知の通りすでに稼働しているコンテナに後から -v
を設定することはできません。
無論、コンテナにファイルを送り込むと Dockerfile とコンテナの状態とが乖離することになるため、いわゆる immutable infrastructure の観点からは邪道です。公式で提供されていない理由もそのあたりにあるのでしょう。理想を言えばそういう状況は発生しないに越したことはないのですが、現実というやつはいとも簡単に我々を裏切るわけで、まあそういう経緯でこのツールは制作されました。
インストール
今回は Go のクロスコンパイル機能を使ってバイナリ配布にしてみました。解凍して出てきた実行ファイルを PATH
が通っている場所に置けばそのまま使えます。
Releases · y-taka-23/docker-inject · GitHub
あるいは Go の処理系が手元にあるなら go get
でも使用可能になります。
$ go get https://github.com/y-taka-23/docker-inject
使い方
docker-inject <コピー元> <コンテナ名>:<コピー先>
で動作します。
ちなみに Windows の場合、<コピー元>
のパスは \
区切りですが、<コピー先>
は Linux なので /
区切りで指定する必要があるのでご注意を。
動作原理
基本的には以下のようなコマンドを実行しているだけです。
$ docker exec -i <コンテナ名> bash -c 'cat > <コピー先ファイル>' < <コピー元ファイル>
これを実行すると
docker exec
でコンテナ内でコマンドを実行- その際
-i
オプションによりホスト側の標準入力がコンテナ内の標準入力に接続される - ホスト側ではコピー元ファイルを標準入力に流し込む
- コンテナ内では
cat
が標準入力の内容をコピー先ファイルに書き出す
という過程を経て、ホスト側のファイルがコンテナ内に書き出されます。
直したいところ
現状の問題点として、以下がすぐに思いつきます。
- ファイルごとに毎回
docker exec
を実行しているため動作が遅い - コピー先のファイルは上書きされる。
-f
とか-u
オプションがない。
可能ならばいずれこの辺も対応したいところではありますが、それはまた別の話。