Dockerイメージ内のコードを直接編集する方法

programming

はじめに

急ぎの修正対応のために本番環境で動いているDockerコンテナ内のコードを編集したかったのですが、訳あってコードを修正してDockerイメージのビルドをし直すのが大変だったため、緊急的、一時的に、既にあるイメージ内のコードを直接変更して対応するということをしたので、そのやり方を備忘録として残しておきます。

方法

基本的な流れとしては docker exec などでコンテナに入りコードを編集してから、 docker commit コマンドを使って新しくイメージを作成します。 大抵の場合Dockerイメージには entrypoint が設定されているため、 docker run では vimsh などを開いてコードを編集することはできないと思います。 そのため僕は docker exec を利用しています。

まずはバックグラウンドで docker run します。 今回編集したいDockerイメージを DOCKER_IMAGE_TO_EDIT:v1.0 とし、コンテナには edit-code-in-image と名前をつけておきます。

docker run -d --name edit-code-in-image DOCKER_IMAGE_TO_EDIT:v1.0

次に docker execsh などを起動します。

docker exec -it edit-code-in-image sh

もしコンテナで既にVimやEmacsなどのエディタが利用できればそれを使ったり、なければ入れるか sed コマンドなどでコードを直接編集します。 編集し終わったら exit します。

vim XXX.py
sed ...
# 編集し終わったら
exit

これで現在動いているコンテナ edit-code-in-image はコードが編集された状態になっています。 ここで docker commit コマンドを利用してこのコンテナをもとに新たなイメージ DOCKER_IMAGE_TO_EDIT:v1.1 を作成します。

以下のコマンドで可能です。

docker commit edit-code-in-image DOCKER_IMAGE_TO_EDIT:v1.1

これにて完了です!

別解

docker run -d からの docker exec の流れをしなくても、 docker run --entrypoint '' などで entrypoint を上書きすれば自由なコマンドを実行できるので一気にコード編集まで可能です。 ですが、後に docker commit したときにDockerイメージの entrypoint'' に上書きされてしまいます。

この場合は、 docker commit--change オプションで entrypoint を上書きしつつイメージを作成するという方法で対処できます。(公式マニュアル

docker commit --change='ENTRYPOINT ["/bin/entrypoint.sh"]' edit-code-in-image DOCKER_IMAGE_TO_EDIT:v1.1

ENTRYPOINT ["/bin/entrypoint.sh"] の部分はもともとイメージに設定されていた entrypoint に読み替えてください。)

おわりに

公式のマニュアルに

Generally, it is better to use Dockerfiles to manage your images in a documented and maintainable way. https://docs.docker.com/engine/reference/commandline/commit/

とあるように、今回のように直接イメージを編集してコミットするという方法は推奨されている方法では無いと思います。

あくまでも緊急用ですね。