Docker学習記録② Docker DesktopでRailsコンテナを作成する

前回は Docker の基本概念について学習した。

今回は実際に Docker Desktop をインストールし、Rails が動作するコンテナを作成してブラウザからアクセスするところまで試した。

なおこの記事はChatGPTとの会話をChatGPTにブログ形式で出力させたものとなっております。

Docker Desktopをインストールした

Windows環境へ Docker Desktop をインストールした。

インストール時には、

  • Hyper-V
  • WSL2

の選択肢が表示されたが、今回は WSL2 を利用する設定を選択した。

現在の Docker Desktop では WSL2 を利用する構成が一般的となっている。

また、Docker Desktop の動作には内部的に Linux 環境が利用されている。

Welcome to Docker コンテナとは何か

Docker Desktop を起動すると、

welcome-to-docker

というコンテナが表示されていた。

これは Docker Desktop の動作確認やチュートリアル用のサンプルコンテナであり、ユーザーが作成したコンテナではない。

Docker Desktop の導入が正常に完了していることを確認するためのものらしい。

RailsイメージではなくRubyイメージを利用する理由

Docker Hub を確認すると Ruby の公式イメージは存在するが、Rails の公式イメージは見当たらなかった。

当初は不思議に思ったが、Rails は独立したアプリケーションではなく Ruby のライブラリである。

そのため一般的には、

FROM ruby:3.3

RUN gem install rails

のように Ruby イメージをベースとして Rails を追加インストールする。

Dockerfileを作成した

学習用として次の Dockerfile を作成した。

FROM ruby:3.3

WORKDIR /app

RUN gem install rails

CMD ["bash"]

この Dockerfile を build すると、

  • Linux
  • Ruby
  • Rails

がインストールされた独自イメージが作成される。

buildとrunの違いを体験した

Dockerを触り始めて最初に混乱したのが build と run の違いだった。

docker build -t my-rails .

を実行するとかなり時間がかかった。

これは Ruby イメージの取得や Rails のインストールが実行されているためである。

一方、

docker run

は作成済みのイメージからコンテナを生成するだけなので非常に高速だった。

実際に触ってみると、

  • build = 環境を作る
  • run = 環境を起動する

という違いが理解しやすかった。

CMD["bash"]の意味を理解した

Dockerfile の最後には

CMD ["bash"]

を記述した。

当初は Docker Desktop の Start ボタンを押せば bash が開くと思っていた。

しかし実際には何も表示されず、コンテナも停止してしまった。

調べてみると、

docker run -it my-rails

のように TTY を接続して起動しなければ、bash はすぐに終了してしまうことが分かった。

Docker Desktop の Start ボタンはコンテナを起動するだけであり、ターミナルへ接続する機能ではない。

コンテナが停止した理由

作成したコンテナの状態を確認すると、

Exited (0)

となっていた。

Dockerではメインプロセスが終了するとコンテナも終了する。

今回の場合、

bash

がメインプロセスだったため、

bash が終了するとコンテナも終了していた。

これは MySQL や nginx のような常駐プロセスとの大きな違いである。

Volumeを利用してローカルフォルダを共有した

Rails プロジェクトをコンテナ内だけに作成すると、コンテナを削除した際にソースコードも失われる。

そこで Volume を利用して、

Windowsフォルダ
⇔
コンテナの /app

を共有した。

これにより、コンテナ内で作成したファイルをホストOS側からも編集できるようになった。

rails newでプロジェクトを作成した

コンテナ内で

rails new .

を実行した。

すると Rails プロジェクト一式が生成された。

実行中には Dockerfile を上書きするか確認された。

これは Rails が独自の Dockerfile を生成しようとしたため。 Rails が生成する Dockerfile は「Railsアプリを配布・実行するための Dockerfile」 であり、今回は学習用に作成した Dockerfile を残すため上書きしなかった。

コンテナ削除後もファイルが残った理由

rails new 実行後にコンテナを削除した。

当初は Rails プロジェクトも消えたと思っていたが、実際にはファイルが残っていた。

理由は Volume を利用していたためである。

生成された Rails プロジェクトはホストOS側に保存されていた。

そのためコンテナを削除しても、

  • app
  • config
  • db
  • Gemfile

などはそのまま残っていた。

ポート公開とは何か

Rails サーバーへブラウザからアクセスするため、

-p 3000:3000

を指定してコンテナを作成した。

これは、

ホストOSの3000番
↓
コンテナの3000番

を接続する設定である。

この設定を追加したことでブラウザから Rails サーバーへ接続できるようになった。

0.0.0.0と127.0.0.1の違いを理解した

Rails を起動する際、

rails s -b 0.0.0.0

を使用した。

最初は、

3000番ポート

0.0.0.0

の違いが理解できなかった。

調べてみると、

IPアドレス
:
ポート番号

という構成になっていた。

例えば、

127.0.0.1:3000

は localhost の 3000 番ポートを意味する。

一方、

0.0.0.0

は特殊なアドレスであり、

すべてのネットワークインターフェースで待ち受ける

という意味になる。

Docker のポートフォワーディングを利用する場合は 0.0.0.0 で待ち受ける必要がある。

Railsのトップページへアクセスできた

最終的に、

rails s -b 0.0.0.0

を実行し、

http://localhost:3000

へアクセスした。

すると Rails のトップページが表示された。

Docker コンテナの中で動作しているアプリケーションへ、ホストOSのブラウザからアクセスできることを確認できた。

Dockerのデータはどこまで削除されるのか

学習中に、

  • コンテナ
  • イメージ
  • Volume

の違いについても理解できた。

コンテナを削除しても、

  • イメージ
  • Volume
  • ホスト側のファイル

は残る。

また Docker には、

docker system prune

という不要データを削除するためのコマンドも存在する。

Docker を使い続けると不要なイメージやビルドキャッシュが蓄積するため、定期的な整理が必要になる。

今回理解できたこと

今回の実践を通して次の点を理解できた。

  • Docker Desktop は WSL2 上で Linux コンテナを動かしている
  • Ruby イメージをベースに Rails 環境を作成できる
  • build と run は役割が異なる
  • bash は TTY がなければ終了する
  • コンテナの終了はメインプロセスの終了を意味する
  • Volume によってソースコードを永続化できる
  • ポート公開によってブラウザからアクセスできる
  • 0.0.0.0 は全インターフェースでの待ち受けを意味する
  • コンテナを削除してもイメージやVolumeは残る

Docker の概念だけでなく、実際にコンテナを作成して Rails を動かしたことで理解が大きく進んだと感じた。