Created: 2024/10/19

Dockerの run コマンドについて勘違いしたこと

とりあえずDockerとは

一言で Doker を表すと、「コンテナ型の仮想化ソフトウェア」であると言えます。コンテナ型仮想化技術 は、従来のハイパーバイザー型仮想化技術よりも軽量でOS資源を効率的に節約できます。

また、コンテナ単位 で稼働しているアプリケーションの共有や移動もより簡易的であり、実際にこのWebアプリケーションもDockerを利用して運用しています。

Dockerについて詳しく学びたい方は公式へ

続いてvolumesとは

volumesは簡単にいうとコンテナの外部にデータを保存できる機能です。

例えば、開発中にサンプルアカウントを5人作成します。その後、コンテナを削除すると用意したサンプルアカウントのデータが消えます。

しかし、volumesを使うことでコンテナを削除しても外部にデータが保管されているため、再度コンテナを立ち上げても同じデータを参照することができます。

このことを、データの永続化といいます。

volumesで手こずったこと

このWebアプリの開発にもDockerを活用しています。その際に手こずったことを紹介しながら、現状の自分の理解をここに残します。

手こずったことは「volumesの更新」です。

実例

このWebアプリの開発でvolumesに指定しているのは以下の2つです。

compose.yml
1
2
3
volumes:
  gemdata:
  mysqldata:
  • gemdataは、Railsのライブラリデータ用のボリューム。
  • mysqldataは、MySQLのデータ用のボリューム。

この2つのデータを永続化しています。

gemdataの方で手こずりました。gemdataは利用しているライブラリの情報が保管されています。

便利な点は、いちいちライブラリをインストールする手間が省ける点です。
一度インストールしたライブラリはvolumesで保管されているので、コンテナを削除してもvolumesからライブラリの情報を参照できるため、スムーズに開発を進めることができます。

手こずったのは、前述した通りvolumesの更新です。

開発中にライブラリを追加することがありました。そこで、追加したライブラリを反映するためにdocker-compose buildを行なっても

ログ
1
Could not find kaminari-1.2.2, ... in locally installed gems (Bundler::GemNotFound)

というエラーが出ました。docker-compose downをして、やり直してもgemがインストールされませんでした。

結論として、docker-compose buildを実行しても、volumesが既に存在しているため、再構築された内容がvolumesに反映されませんでした。そのため、buildをした後にdocker-compose upを行うと build 前のvolumesを参照して起動するのでBundler::GemNotFoundが出力されるというわけです。docker-compose buildで、既存のvolumesを上書きすることができないということになります。

そこで、行なったのがdocker-compose run コンテナ名 bundle installです。その結果、gemのインストールが反映されてうまく実行できました。(でも、なぜか余分なコンテナが生成されてる?...
そのためrunでvolumesを更新」できた!!

っと勘違いしました😅

実際には、docker-compose runにvolumesを更新する機能はありません。では、なぜうまくいったのか順番に説明します。

1. docker-compose runで起きたこと


run には、新しいコンテナを生成する機能があります。そのため、docker-compose run コンテナ名 bundle installを実行することで、全く別の新しいコンテナが生成されます。これが、余分に生成されたコンテナの正体です。
そして、run コマンドにはすでにあるvolumesを再利用する仕様があります。そのため、すでに docker-compose.ymlファイルで定義してあるvolumesを再利用します。すると、そのvolumesにgemのデータがインストールされます。

2. volumesの参照


実行したrun によってvolumesにgemのデータがインストールされ、そのvolumesを今まで稼働していたコンテナが参照することでBundler::GemNotFoundを解消することができました。

3. 勘違い


この一連の流れで、私はrun でvolumesを更新できる!!と勘違いしました。
整理すると、run で新しく別のコンテナを生成することで、volumesにgemのデータを「強引に」追加したというのが正確な捉え方だと思います。

まとめ

  • volumesの永続化
    • volumesを使うことで、コンテナを削除してもデータを外部に保管でき、再度コンテナを立ち上げた際に同じデータを参照できる。
  • docker-compose runの動作
    • docker-compose runは新しいコンテナを生成し、既存のvolumesを再利用する。 そのため、新しいコンテナ内でデータを保存すれば、volumesを通じて他のコンテナからもそのデータが参照できる。
  • 勘違いの原因
    • runでvolumesが「更新」されたと思ったが、実際には新しいコンテナで同じvolumesにデータが書き込まれただけだった。
  • 学び
    • volumesは複数のコンテナ間で共有されるため、新しいデータが追加されれば他のコンテナからも参照可能。
    • volumes自体を更新するのではなく、データが書き込まれたことが他のコンテナに反映される仕組みを理解した。

参考

docker-compose 'up' とか 'build' とか 'start' とかの違いを理解できていなかったのでまとめてみた

Docker の Volume がよくわからないから調べた

Docker Compose + Railsでイメージ内でbundle installしているはずなのにgemが無いとエラーがでる。