Help us understand the problem. What is going on with this article?

Docker利用時のソースコードの変更反映

ソースコード変更の Docker コンテナへの反映について、ちょうどいい機会があったので基礎も含めて整理します。
(タイミングよく投稿されていた) 以下の Qiita の記事に書かれていることが全てだけど、補足してまとめておきます。

References

image と container

抽象化された概念の理解は、以下のような感じでいいと思っています。

  • image: 実行環境の構成を保存した情報
  • container: image を実際に動かした実行環境

その上で、以下の点を理解できていれば、今回の話的には大丈夫です。

  • container を動かすには、ベースとなる image が必ず必要なこと
  • container を破棄しても image が残っている場合があること
  • リポジトリ内のソースコードは、 image 内に含まれている場合と container 上に含まれている場合があること

なお image は実際には layer に分かれて保存されますので、そこが分かっていると image size の削減や差分 build の高速化を図ったりできます。

image の状態管理

image は実際に動いているわけではないので、状態としては存在するか否かの2択です。
そのため、操作としては、簡単に言えば、作成する、破棄するの2つとなります。

デフォルトのオプション設定で、それぞれの操作を行うコマンドは以下のとおりです。

作成する:

  • docker image build
  • docker-compose build

破棄する:

  • docker image rm
  • docker-compose rm

container の状態管理

container は実際に動いているので、状態としては、存在しない <=> 存在する <=> 動いている、の3択です。
よって、それぞれの状態遷移を起こすための操作が行えます。

デフォルトのオプション設定で、それぞれの操作を行うコマンドは以下のとおりです。

作成する:

  • docker container create
  • docker-compose create (Deprecated)

起動する:

  • docker container start
  • docker-compose start

停止する:

  • docker container stop
  • docker-compose stop

破棄する:

  • docker container rm
  • docker-compose rm

作成・起動を一気にやる:

  • docker-compose up

停止・破棄を一気にやる:

  • docker-compose down

host と Docker container の関係

host というのは、 Docker container を動かす実行環境のことですね。
Docker for Mac を使っている場合なら macOS のことです。

Docker container は host とは切り離された状態で (無関係に) 動きますので、一度 container を立ち上げてしまえば、 host 上のファイルの変更は container 上には反映されません。

ただし、 host 上のファイルシステムの一部を volume として、 Docker container に mount することができるので、その場合は、 host 上のファイルの変更が container にそのまま反映されます。

Case Study

Dockerfile を変更した場合

Dockerfile 内の記載内容は、 image を作るためのものなので、 Dockerfile を書き換えた場合は image から作り直す必要があります
もちろん、その image を使って動いている container も作り直す必要があります

docker-compose.yaml を変更した場合

docker-compose.yaml の記載内容のうち build section 以外は、出来上がった image を使って、その設定内容で container, volume, network を作成するためのものなので、これを書き換えた場合は image を作り直す必要はありません。ただ、 container は作成時にこの設定ファイルの内容を取り込みますので、 docker-compose restart (stop -> start) だけではダメで、 container の再作成を行う必要があります

また、 docker-compose.yaml の中の build section の設定内容を書き換えた場合は、 image の再作成が必要になります

その他のファイルを変更した場合

これは本当にケースバイケースなのですが、大きく分けて以下のようなケースが考えられます。

そのファイルが image に含まれている場合

Dockerfile 内で ADDCOPY によって、対象ファイルを image に取り込んでいる場合は、基本的には image (および container) の再作成が必要になります

ただし、そのファイルの変更が動的に動作に反映される場合、 container 上でそのファイルを書き換える (host の volume を mount している場合は host 上で書き換えてもいい) ことで、一時的に、その container での動作に反映することも可能です。その場合、 host 上で永続化していない container に対する変更内容は、 container を再作成することで元に戻ってしまうことに注意が必要です。

例としては、例えば Gemfile は普通 image にも含めると思いますが、 container 動作中に Gemfile を書き換えて bundle install することで、新たな gem を container にインストールすることができます。しかし、この container を再作成すると、このインストールした状態もリセットされてしまうため、再度 Gemfile の書き換え (host の volume を mount していない場合) や bundle install が必要になるわけです。

さらに、その gem のインストールに、 image のビルド中にだけ使って、最終 image には含めていない native library が必要だったりすると、そのインストールも必要だったりして、結局は image の再作成からやり直したほうが効率的だったりします。

そのファイルが image に含まれていない場合

image に含めていないファイルを container が利用するということは、基本的には host などから volume を mount したり、 network 経由等で取得したりという構成になっているかと思います。この場合は、変更反映のための image の再作成は不要です

container については、そのファイル内容の変更が動的に動作に反映されるかどうか (live reload が有効かどうか) によって、 container の再起動や、設定反映のためのコマンド発行が必要かどうかが変わります。この部分は、アプリケーションの実装次第になるため、随時調べるか、とりあえず restart or 再作成 してみる、というのがよいかと思われます。

tearoom6
blog も書いてます。 https://tearoom6.hateblo.jp/
https://tearoom6.github.io/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away