やったこと
-
Dockerfile
で、rubyイメージをベースにwebコンテナ(railsサーバー)のイメージを作成し、コンテナを起動してみた。 - その後、
docker-compose.yml
を作成し、webコンテナとdbコンテナの2つのコンテナをまとめて起動できるようにした。
用語について
-
Docker Engine: 各アプリケーションコンテナを載せている基盤部分のソフトウェア。Linuxカーネルを利用。Docker CLIを提供。
-
Docker CLI:
docker container run
など、docker
で始まるコマンドを提供。 -
Docker Desktop: WindowsやMacでDockerを使うためのGUIアプリケーション。Docker EngineやLinuxカーネルが含まれているため(Docker Composeも)、Linux以外のOSでもDocker Engineを動かせる!
-
Docker Compose: Docker CLIのコマンドをまとめて実行してくれる便利ツール。
docker compose
で始まるコマンドを提供。ymlファイルに実行させたいコマンドの手順書を記述する。 -
Docker Hub: Dockerのイメージレジストリを提供するサービス。ここで公開されているイメージを
pull
したり、構築したイメージをここにpush
したりできる。 -
コンテナ: ホストマシン上の隔離されたプロセス(LinuxのNamespaceという機能により他と分離されている)。イメージをもとに作られる。複数のコンテナは互いに独立し、影響を与えない。起動するたびに新しいコンテナが作られる。
-
イメージ: コンテナの実行に必要なパッケージ。ファイルやメタ情報を集めたもの。複数のレイヤーからなる。Docker Hubで公開されている。
-
レイヤー: ベース(例: Ubuntu), インストールされているもの(例: PHP), 環境変数, 設定ファイル, デフォルト命令などの情報。
- デフォルト命令:コンテナ起動時に実行するコマンド。任意の命令を実行することも可能(コンテナ起動時に指定)。コンテナはメインプロセス(
PID=1
。デフォルト命令or起動時に指定された命令)が終了すると自動停止する。
- デフォルト命令:コンテナ起動時に実行するコマンド。任意の命令を実行することも可能(コンテナ起動時に指定)。コンテナはメインプロセス(
-
Dockerfile: 既存のイメージにさらにレイヤーを積み重ねるためのテキストファイル。既存のイメージをもとに、自分のアプリに合ったイメージになるようカスタマイズする。
-
FROM
: ベースイメージを指定 -
RUN
: 任意のコマンドを実行 -
COPY
: ホストマシンのファイルをイメージに追加 -
CMD
: デフォルト命令を指定 -
ENV
: コンテナにインストールされているソフトウェアの環境変数を設定(=コンテナ内に環境変数を埋め込む) -
ARG
: Dockerfile内で使える変数を設定 -
ENTRYPOINT
: コンテナの実行時にデフォルトで実行するコマンドや引数を設定。CMD
にデフォルトの引数や推奨のパラメータを設定し、コンテナ起動時にオプション付与で引数・パラメータを任意に変更できる。 -
EXPOSE
: コンテナの実行時、指定した ネットワーク・ポートをコンテナがリッスンするように、Docker へ通知。docker run
で-p
フラグを使い、ポートを指定することで実際にそのポートは公開される。
-
-
ボリュームのマウント: コンテナ内のファイルの変更を、ホストマシンに共有する。ボリュームマウントとバインドマウントの2つの方法がある。
- ボリュームマウント: Docker Engine上に領域(=ボリューム)を確保し、コンテナ上にデータを保管する。データの保管場所は、コンテナごとに異なっている。Docker Hubの「Where to Store Data」の項目に記載がある。ホストマシンでの変更を反映させる必要がないものに向いている。(DBコンテナのデータなど)
- バインドマウント: ホストマシンの任意のディレクトリをコンテナにマウントする。ソースコードの共有などに活用。ホストマシンでコード変更時に更新や同期の手間なく反映させることができる。絶対パスを指定することで、バインドマウントだと判断される。
コマンド
-
container run [option] <image> [command]
: イメージからコンテナ起動 (image pull
+container create
+container start
)-
--rm
オプション:コンテナ停止時に自動削除 -
--interactive --tty
: コンテナを対話操作(コンテナの標準入力に接続&疑似ターミナルを割り当て)
-
-
image build [option] <path>
: Dockerfileからイメージ作成-
--tag
オプション: イメージに名前をつけられる。イメージを参照・指定する際に便利。 -
<path>
:COPY
するファイルのパス
-
-
container exec [option] <container> command
: 起動中のコンテナに接続し、linuxコマンドを実行-
-it
オプション: コンテナを対話操作
-
手順
- railsコンテナのイメージを作成
- イメージのビルド
docker image build --tag rails:server .
- イメージがビルドできているか確認
docker image ls
- railsコンテナとdbのコンテナを起動するようなdocker-compose.ymlの作成
- railsコンテナが正常に起動することを確認
docker compose up
→ブラウザで開けるか確認
実際に作成したDockerの設定ファイル
Dockerfile
FROM ruby:3.1.2
ARG ROOT="/karoyaka"
ENV TZ=Asia/Tokyo
WORKDIR ${ROOT}
# 必須ではないパッケージも一緒にインストールされないようにオプション付与
# MariaDB: mysqlから派生。高性能。
RUN apt-get update && \
apt-get install -y --no-install-recommends \
mariadb-client tzdata libvips
COPY Gemfile ${ROOT}
COPY Gemfile.lock ${ROOT}
RUN gem install bundler
RUN bundle install --jobs 4
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
docker-compose.yml
version: "3.9"
services:
web:
build: .
command: bash -c "rm -f karoyaka/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/karoyaka:cached
- bundle:/usr/local/bundle
ports:
- '3001:3000'
depends_on:
- db
stdin_open: true
tty: true
environment:
MYSQL_PASSWORD: password
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
ports:
- '3307:3306'
volumes:
- mysql_data:/var/lib/mysql
volumes:
bundle:
mysql_data:
それぞれのファイルで何をしているか
Dockerfile
- ベースイメージに
ruby:3.1.2
を指定 - タイムゾーンの設定
- 作業ディレクトリを命名して指定
- コンテナ内に必要なライブラリをインストール
- mariadb-client: MariaDBとは、MySQLから派生した高性能なRDBMS
- tzdata: タイムゾーンに関するデータ集
- libvips: 画像処理ソフトパッケージ(解析や変形)
- GemfileとGemfile.lockを作業ディレクトリ内にコピー
- bundlerをインストールし、gemたちもインストール(並列処理で高速化)
- コンテナの実行時、指定したポート(3000)をコンテナがリッスンするように、Dockerへ通知(ポートの解放)
- バインドするIPアドレスを指定してrailsサーバー起動
- バインディングアドレス:外部からのリクエストを受け付けるために結び付けられているIPアドレス。
-
0.0.0.0
=ワイルドカード。 - →全てのIPアドレスからのリクエストを受け付けられるようになり、ブラウザなどコンテナ外からもコンテナ内にアクセスが可能に。
docker-compose.yml
- webコンテナの定義
- ./Dockerfileに書かれたイメージからビルド
- pidファイルが存在していた場合、エラーになり新たにコンテナ起動ができないので削除する(
bash -c
: -cで渡される文字列をコマンドとして認識して実行する)。そして、すべてのIPアドレスをバインディングアドレスとして設定してrailsサーバー起動。(command
は、Dockerfileに書いたデフォルト命令CMD
を上書きする) - ホストマシンのカレントディレクトリのソースコードをバインドマウント(
cached
:ホスト→コンテナへの反映を効率的に行うモード) & bundleというボリュームに、インストールしたgemを保管。(rubyのコンテナでは、インストールされたgemはusr/local/bundle
に入るように設定されている) - ホストのポート番号は3001, コンテナのポート番号は3000に設定(ポートの定義によって、ホストマシンからコンテナへのアクセスが可能に)
- dbコンテナの起動後に起動するよう設定
- 標準入出力とエラー出力をコンテナに結びつけるよう設定。=
docker container run -i
- 擬似端末(キーボードによる入力)をコンテナに結びつけるよう設定。=
docker container run -t
- dbコンテナの定義
- イメージを指定
- mysqlにログインするルートユーザのパスワードを定義
- ホストマシンのポート番号は3007, コンテナのポート番号は3006に設定
- mysql_dataというボリュームに、DBのデータを保管(永続化)
- ボリュームの作成(bundleとmysql_data)
これから
Dockerで、webコンテナとdbコンテナを起動させることができるようになった
次はシステムテスト用のchromeコンテナ、そしてジョブ永続化のためにredisコンテナ、sidekiqコンテナも起動できるように設定していく!
参考
- 実践 Docker - ソフトウェアエンジニアの「Docker よくわからない」を終わりにする本
- Dockerfile のベストプラクティス
- dockerfileのenvを使って環境変数を渡す【ARGとの違いも説明する】
- ENTRYPOINTは「必ず実行」、CMDは「(デフォルトの)引数」
- シェルスクリプトの罠を避ける三つの tips
- What does set -e and exec "$@" do for docker entrypoint scripts?
- rails s -b 0.0.0.0 のオプション-bの意味
- Bind Addressの意味がようやく分かった
- docker-compose.yml個人的Tips集
- shellの-cオプションについてUbuntuのsh(dash)、bash、zshはそれぞれ違う挙動をする
- 知識0から始めるRails on Docker
- 既存のrailsプロジェクトをDockerで開発する手順
- 既存のRailsアプリにDockerを導入する手順
- Ruby on Rails7.0.3 × MySQL8.0 のDocker環境構築