DockerComposeを使用した開発のためのRubyonRailsアプリケーションのコンテナー化
序章
アプリケーションを積極的に開発している場合は、 Docker を使用すると、ワークフローとアプリケーションを本番環境にデプロイするプロセスを簡素化できます。 開発中のコンテナを使用すると、次の利点があります。
- 環境は一貫しています。つまり、システムの競合を心配することなく、プロジェクトに必要な言語と依存関係を選択できます。
- 環境が分離されているため、問題のトラブルシューティングや新しいチームメンバーの参加が容易になります。
- 環境は移植可能であり、コードをパッケージ化して他の人と共有することができます。
このチュートリアルでは、Dockerを使用して Ruby onRailsアプリケーションの開発環境をセットアップする方法を説明します。 Docker Compose を使用して、アプリケーション自体、 PostgreSQL データベース、 Redis 、およびSidekiqサービス用に複数のコンテナーを作成します。 セットアップは次のことを行います。
- ホスト上のアプリケーションコードをコンテナ内のコードと同期して、開発中の変更を容易にします。
- コンテナの再起動間でアプリケーションデータを保持します。
- 期待どおりにジョブを処理するようにSidekiqワーカーを構成します。
このチュートリアルの最後に、Dockerコンテナで実行されている動作するサメ情報アプリケーションがあります。
前提条件
このチュートリアルに従うには、次のものが必要です。
- Ubuntu 18.04を実行しているローカル開発マシンまたはサーバー、および
sudo
特権とアクティブなファイアウォールを持つ非rootユーザー。 これらの設定方法のガイダンスについては、この初期サーバー設定ガイドを参照してください。 - Ubuntu18.04にDockerをインストールして使用する方法の手順1と2に従ってローカルマシンまたはサーバーにDockerをインストールします。
- Ubuntu 18.04にDockerComposeをインストールする方法のステップ1に従って、ローカルマシンまたはサーバーにDockerComposeをインストールします。
ステップ1—プロジェクトのクローンを作成して依存関係を追加する
最初のステップは、 DigitalOceanCommunityGitHubアカウントからrails-sidekiqリポジトリのクローンを作成することです。 このリポジトリには、既存のRails5プロジェクトにSidekiqを追加する方法を説明するRubyonRailsアプリケーションにSidekiqとRedisを追加する方法で説明されているセットアップのコードが含まれています。
リポジトリをrails-docker
というディレクトリに複製します。
git clone https://github.com/do-community/rails-sidekiq.git rails-docker
rails-docker
ディレクトリに移動します。
cd rails-docker
このチュートリアルでは、PostgreSQLをデータベースとして使用します。 SQLite 3の代わりにPostgreSQLを使用するには、Gemfileにリストされているプロジェクトの依存関係に pggemを追加する必要があります。 そのファイルを開いて、nano
またはお気に入りのエディターを使用して編集します。
nano Gemfile
メインプロジェクトの依存関係(開発の依存関係の上)の任意の場所にgemを追加します。
〜/ rails-docker / Gemfile
. . . # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.1.0', require: false gem 'sidekiq', '~>6.0.0' gem 'pg', '~>1.1.3' group :development, :test do . . .
sqlite gem はもう使用しないため、コメントアウトすることもできます。
〜/ rails-docker / Gemfile
. . . # Use sqlite3 as the database for Active Record # gem 'sqlite3' . . .
最後に、development
の下にあるspring-watcher-listengemをコメントアウトします。
〜/ rails-docker / Gemfile
. . . gem 'spring' # gem 'spring-watcher-listen', '~> 2.0.0' . . .
このgemを無効にしないと、Railsコンソールにアクセスするときに永続的なエラーメッセージが表示されます。 これらのエラーメッセージは、このgemがファイルシステムの変更をポーリングするのではなく、Railsがlistenを使用して開発の変更を監視しているという事実に由来しています。 このgemは、node_modules
ディレクトリを含むプロジェクトのルートを監視するため、監視されているディレクトリに関するエラーメッセージをスローし、コンソールを乱雑にします。 ただし、CPUリソースの節約が心配な場合は、このgemを無効にしてもうまくいかない可能性があります。 この場合、RailsアプリケーションをRails6にアップグレードすることをお勧めします。
編集が終了したら、ファイルを保存して閉じます。
プロジェクトリポジトリを配置し、pg
gemをGemfileに追加し、spring-watcher-listen
gemをコメントアウトすると、PostgreSQLで動作するようにアプリケーションを構成する準備が整います。
ステップ2—PostgreSQLおよびRedisで動作するようにアプリケーションを構成する
開発中のPostgreSQLとRedisを使用するには、次のことを行います。
- PostgreSQLをデフォルトのアダプターとして使用するようにアプリケーションを構成します。
.env
ファイルを、データベースのユーザー名とパスワード、およびRedisホストを使用してプロジェクトに追加します。init.sql
スクリプトを作成して、データベースのsammy
ユーザーを作成します。- Sidekiq用のinitializerを追加して、コンテナ化された
redis
サービスで動作できるようにします。 .env
ファイルおよびその他の関連ファイルをプロジェクトのgitignore
およびdockerignore
ファイルに追加します。- データベースシードを作成して、アプリケーションの起動時に使用できるレコードがアプリケーションに含まれるようにします。
まず、config/database.yml
にあるデータベース構成ファイルを開きます。
nano config/database.yml
現在、このファイルには次のdefault
設定が含まれています。これらの設定は、他の設定がない場合に適用されます。
〜/ rails-docker / config / database.yml
default: &default adapter: sqlite3 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000
postgresql
アダプターを使用するという事実を反映するために、これらを変更する必要があります。これは、Docker Composeを使用してPostgreSQLサービスを作成し、アプリケーションデータを永続化するためです。
SQLiteをアダプターとして設定するコードを削除し、次の設定に置き換えます。これにより、アダプターと接続に必要なその他の変数が適切に設定されます。
〜/ rails-docker / config / database.yml
default: &default adapter: postgresql encoding: unicode database: <%= ENV['DATABASE_NAME'] %> username: <%= ENV['DATABASE_USER'] %> password: <%= ENV['DATABASE_PASSWORD'] %> port: <%= ENV['DATABASE_PORT'] || '5432' %> host: <%= ENV['DATABASE_HOST'] %> pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 . . .
次に、development
環境の設定を変更します。これは、このセットアップで使用している環境だからです。
セクションが次のようになるように、既存のSQLiteデータベース構成を削除します。
〜/ rails-docker / config / database.yml
. . . development: <<: *default . . .
最後に、production
およびtest
環境のdatabase
設定も削除します。
〜/ rails-docker / config / database.yml
. . . test: <<: *default production: <<: *default . . .
デフォルトのデータベース設定に対するこれらの変更により、バージョン管理にコミットされない.env
ファイルで定義された環境変数を使用してデータベース情報を動的に設定できるようになります。
編集が終了したら、ファイルを保存して閉じます。
Railsプロジェクトを最初から作成する場合は、 How To Use PostgreSQL with Your Ruby onのステップ3で説明されているように、rails new
コマンドを使用してアダプターを設定できます。 Ubuntu18.04上のRailsアプリケーション。 これにより、アダプターがconfig/database.yml
に設定され、pg
gemがプロジェクトに自動的に追加されます。
環境変数を参照したので、好みの設定でそれらのファイルを作成できます。 この方法で構成設定を抽出することは、アプリケーション開発への 12ファクターアプローチの一部であり、分散環境でのアプリケーションの復元力のベストプラクティスを定義します。 現在、本番環境とテスト環境を将来セットアップする場合、データベース設定を構成するには、追加の.env
ファイルを作成し、DockerComposeファイルで適切なファイルを参照する必要があります。
.env
ファイルを開きます。
nano .env
次の値をファイルに追加します。
〜/ rails-docker / .env
DATABASE_NAME=rails_development DATABASE_USER=sammy DATABASE_PASSWORD=shark DATABASE_HOST=database REDIS_HOST=redis
データベース名、ユーザー、パスワードの設定に加えて、DATABASE_HOST
の値も設定しました。 値database
は、DockerComposeを使用して作成するdatabase
PostgreSQLサービスを指します。 また、REDIS_HOST
を設定して、redis
サービスを指定します。
編集が終了したら、ファイルを保存して閉じます。
sammy
データベースユーザーを作成するには、init.sql
スクリプトを記述して、起動時にデータベースコンテナーにマウントできます。
スクリプトファイルを開きます。
nano init.sql
次のコードを追加して、管理者権限を持つsammy
ユーザーを作成します。
〜/ rails-docker / init.sql
CREATE USER sammy; ALTER USER sammy WITH SUPERUSER;
このスクリプトは、データベース上に適切なユーザーを作成し、このユーザーに管理者権限を付与します。
スクリプトに適切な権限を設定します。
chmod +x init.sql
次に、コンテナ化されたredis
サービスと連携するようにSidekiqを構成します。 イニシャライザーをconfig/initializers
ディレクトリーに追加できます。ここで、Railsは、フレームワークとプラグインがロードされると構成設定を検索し、Redisホストの値を設定します。
sidekiq.rb
ファイルを開いて、次の設定を指定します。
nano config/initializers/sidekiq.rb
次のコードをファイルに追加して、REDIS_HOST
およびREDIS_PORT
の値を指定します。
〜/ rails-docker / config / initializers / sidekiq.rb
Sidekiq.configure_server do |config| config.redis = { host: ENV['REDIS_HOST'], port: ENV['REDIS_PORT'] || '6379' } end Sidekiq.configure_client do |config| config.redis = { host: ENV['REDIS_HOST'], port: ENV['REDIS_PORT'] || '6379' } end
データベース構成設定と同様に、これらの設定により、ホストとポートのパラメーターを動的に設定できるため、アプリケーションコード自体を変更することなく、実行時に適切な値に置き換えることができます。 REDIS_HOST
に加えて、他に設定されていない場合に備えて、REDIS_PORT
のデフォルト値が設定されています。
編集が終了したら、ファイルを保存して閉じます。
次に、アプリケーションの機密データがバージョン管理にコピーされないようにするために、プロジェクトの.gitignore
ファイルに.env
を追加して、プロジェクトで無視するファイルをGitに指示します。 編集用にファイルを開きます。
nano .gitignore
ファイルの最後に、.env
のエントリを追加します。
〜/ rails-docker / .gitignore
yarn-debug.log* .yarn-integrity .env
編集が終了したら、ファイルを保存して閉じます。
次に、.dockerignore
ファイルを作成して、コンテナーにコピーしないものを設定します。 編集用にファイルを開きます。
.dockerignore
次のコードをファイルに追加します。これにより、Dockerは、コンテナーにコピーする必要のないものの一部を無視するようになります。
〜/ rails-docker / .dockerignore
.DS_Store .bin .git .gitignore .bundleignore .bundle .byebug_history .rspec tmp log test config/deploy public/packs public/packs-test node_modules yarn-error.log coverage/
このファイルの最後にも.env
を追加します。
〜/ rails-docker / .dockerignore
. . . yarn-error.log coverage/ .env
編集が終了したら、ファイルを保存して閉じます。
最後のステップとして、アプリケーションを起動したときにいくつかのレコードが含まれるように、いくつかのシードデータを作成します。
db
ディレクトリにあるシードデータのファイルを開きます。
nano db/seeds.rb
次のコードをファイルに追加して、4つのデモサメと1つのサンプル投稿を作成します。
〜/ rails-docker / db / seeds.rb
# Adding demo sharks sharks = Shark.create([{ name: 'Great White', facts: 'Scary' }, { name: 'Megalodon', facts: 'Ancient' }, { name: 'Hammerhead', facts: 'Hammer-like' }, { name: 'Speartooth', facts: 'Endangered' }]) Post.create(body: 'These sharks are misunderstood', shark: sharks.first)
このシードデータは、最初のサメに関連付けられた4つのサメと1つの投稿を作成します。
編集が終了したら、ファイルを保存して閉じます。
アプリケーションがPostgreSQLで動作するように構成され、環境変数が作成されたら、アプリケーションDockerfileを作成する準備が整います。
ステップ3—Dockerfileおよびエントリポイントスクリプトの記述
Dockerfileは、作成時にアプリケーションコンテナに含まれるものを指定します。 Dockerfileを使用すると、コンテナー環境を定義し、依存関係またはランタイムバージョンとの不一致を回避できます。
最適化されたコンテナの構築に関するこれらのガイドラインに従い、アルパインベースを使用し、画像レイヤーを一般的に最小化することで、画像を可能な限り効率的にします。
現在のディレクトリでDockerfileを開きます。
nano Dockerfile
Dockerイメージは、相互に構築される一連のレイヤードイメージを使用して作成されます。 最初のステップは、アプリケーションのベースイメージを追加することです。これにより、アプリケーションビルドの開始点が形成されます。
次のコードをファイルに追加して、 Ruby alpineimageをベースとして追加します。
〜/ rails-docker / Dockerfile
FROM ruby:2.5.1-alpine
alpine
イメージは、Alpine Linuxプロジェクトから派生したものであり、イメージサイズを小さく抑えるのに役立ちます。 alpine
イメージがプロジェクトに適しているかどうかの詳細については、 DockerHubRubyイメージページのImageVariantsセクションの詳細な説明を参照してください[ X210X]。
開発でalpine
を使用する際に考慮すべきいくつかの要因:
- 画像サイズを小さくすると、特にボリュームを最小限に抑える場合は、ページとリソースの読み込み時間が短縮されます。 これにより、開発におけるユーザーエクスペリエンスを迅速に保ち、コンテナ化されていない環境でローカルで作業している場合のエクスペリエンスに近づけることができます。
- 開発イメージと本番イメージの間に同等性があると、展開の成功が容易になります。 チームはスピードのメリットのために本番環境でアルパインイメージを使用することを選択することが多いため、アルパインベースで開発すると、本番環境に移行する際の問題を相殺するのに役立ちます。
次に、環境変数を設定して、Bundlerバージョンを指定します。
〜/ rails-docker / Dockerfile
. . . ENV BUNDLER_VERSION=2.0.2
これは、環境で使用可能なデフォルトのbundler
バージョンと、Bundler2.0.2を必要とするアプリケーションコードとの間のバージョンの競合を回避するために実行する手順の1つです。
次に、アプリケーションでの作業に必要なパッケージをDockerfileに追加します。
〜/ rails-docker / Dockerfile
. . . RUN apk add --update --no-cache \ binutils-gold \ build-base \ curl \ file \ g++ \ gcc \ git \ less \ libstdc++ \ libffi-dev \ libc-dev \ linux-headers \ libxml2-dev \ libxslt-dev \ libgcrypt-dev \ make \ netcat-openbsd \ nodejs \ openssl \ pkgconfig \ postgresql-dev \ python \ tzdata \ yarn
これらのパッケージには、nodejs
およびyarn
などが含まれます。 アプリケーションはwebpackでアセットを提供するため、アプリケーションが期待どおりに機能するには、Node.jsとYarnを含める必要があります。
alpine
イメージは非常に最小限であることに注意してください。ここにリストされているパッケージは、独自のアプリケーションをコンテナー化するときに開発で必要になる可能性のあるものを網羅しているわけではありません。
次に、適切なbundler
バージョンをインストールします。
〜/ rails-docker / Dockerfile
. . . RUN gem install bundler -v 2.0.2
この手順により、コンテナー化された環境と、このプロジェクトのGemfile.lock
ファイルの仕様との間の同等性が保証されます。
次に、コンテナにアプリケーションの作業ディレクトリを設定します。
〜/ rails-docker / Dockerfile
. . . WORKDIR /app
Gemfile
とGemfile.lock
をコピーします。
〜/ rails-docker / Dockerfile
. . . COPY Gemfile Gemfile.lock ./
これらのファイルを独立した手順としてコピーし、その後にbundle install
を実行すると、アプリケーションコードに変更を加えるたびにプロジェクトgemを再構築する必要がなくなります。 これは、Composeファイルに含めるgemボリュームと連携して機能します。このボリュームは、サービスが再作成されてもプロジェクトgemが同じである場合に、アプリケーションコンテナーにgemをマウントします。
次に、nokogiri
gemビルドの構成オプションを設定します。
〜/ rails-docker / Dockerfile
. . . RUN bundle config build.nokogiri --use-system-libraries . . .
このステップでは、上記のRUN apk add…
ステップでアプリケーションコンテナに追加したlibxml2およびlibxsltライブラリバージョンを使用してnokigiri
をビルドします。
次に、プロジェクトgemをインストールします。
〜/ rails-docker / Dockerfile
. . . RUN bundle check || bundle install
この手順では、gemをインストールする前に、gemがまだインストールされていないことを確認します。
次に、JavaScriptパッケージと依存関係を使用してgemで使用したのと同じ手順を繰り返します。 最初にパッケージメタデータをコピーし、次に依存関係をインストールし、最後にアプリケーションコードをコンテナイメージにコピーします。
DockerfileのJavascriptセクションを開始するには、package.json
とyarn.lock
をホスト上の現在のプロジェクトディレクトリからコンテナにコピーします。
〜/ rails-docker / Dockerfile
. . . COPY package.json yarn.lock ./
次に、yarn install
を使用して必要なパッケージをインストールします。
〜/ rails-docker / Dockerfile
. . . RUN yarn install --check-files
この命令には、yarn
コマンドを伴う--check-files
フラグが含まれています。これは、以前にインストールされたファイルが削除されていないことを確認する機能です。 gemの場合と同様に、Composeファイルを作成するときに、ボリュームを使用してnode_modules
ディレクトリ内のパッケージの永続性を管理します。
最後に、残りのアプリケーションコードをコピーして、エントリポイントスクリプトを使用してアプリケーションを起動します。
〜/ rails-docker / Dockerfile
. . . COPY . ./ ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"]
エントリポイントスクリプトを使用すると、コンテナを実行可能ファイルとして実行できます。
最終的なDockerfileは次のようになります。
〜/ rails-docker / Dockerfile
FROM ruby:2.5.1-alpine ENV BUNDLER_VERSION=2.0.2 RUN apk add --update --no-cache \ binutils-gold \ build-base \ curl \ file \ g++ \ gcc \ git \ less \ libstdc++ \ libffi-dev \ libc-dev \ linux-headers \ libxml2-dev \ libxslt-dev \ libgcrypt-dev \ make \ netcat-openbsd \ nodejs \ openssl \ pkgconfig \ postgresql-dev \ python \ tzdata \ yarn RUN gem install bundler -v 2.0.2 WORKDIR /app COPY Gemfile Gemfile.lock ./ RUN bundle config build.nokogiri --use-system-libraries RUN bundle check || bundle install COPY package.json yarn.lock ./ RUN yarn install --check-files COPY . ./ ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"]
編集が終了したら、ファイルを保存して閉じます。
次に、エントリポイントスクリプト用にentrypoints
というディレクトリを作成します。
mkdir entrypoints
このディレクトリには、メインのエントリポイントスクリプトとSidekiqサービスのスクリプトが含まれます。
アプリケーションエントリポイントスクリプトのファイルを開きます。
nano entrypoints/docker-entrypoint.sh
次のコードをファイルに追加します。
rails-docker / entrypoints / docker-entrypoint.sh
#!/bin/sh set -e if [ -f tmp/pids/server.pid ]; then rm tmp/pids/server.pid fi bundle exec rails s -b 0.0.0.0
最初の重要な行はset -e
です。これは、スクリプトを実行する/bin/sh
シェルに、スクリプトの後半で問題が発生した場合に高速で失敗するように指示します。 次に、スクリプトはtmp/pids/server.pid
が存在しないことを確認して、アプリケーションの起動時にサーバーの競合が発生しないようにします。 最後に、スクリプトはbundle exec rails s
コマンドを使用してRailsサーバーを起動します。 このコマンドで-b
オプションを使用して、サーバーをデフォルトのlocalhost
ではなく、すべてのIPアドレスにバインドします。 この呼び出しにより、Railsサーバーは着信要求をデフォルトのlocalhost
ではなくコンテナIPにルーティングします。
編集が終了したら、ファイルを保存して閉じます。
スクリプトを実行可能にします。
chmod +x entrypoints/docker-entrypoint.sh
次に、Sidekiqジョブを処理するsidekiq
サービスを開始するスクリプトを作成します。 このアプリケーションがSidekiqを使用する方法の詳細については、SidekiqとRedisをRubyonRailsアプリケーションに追加する方法を参照してください。
Sidekiqエントリポイントスクリプトのファイルを開きます。
nano entrypoints/sidekiq-entrypoint.sh
Sidekiqを起動するには、ファイルに次のコードを追加します。
〜/ rails-docker / entrypoints / sidekiq-entrypoint.sh
#!/bin/sh set -e if [ -f tmp/pids/server.pid ]; then rm tmp/pids/server.pid fi bundle exec sidekiq
このスクリプトは、アプリケーションバンドルのコンテキストでSidekiqを起動します。
編集が終了したら、ファイルを保存して閉じます。 実行可能にする:
chmod +x entrypoints/sidekiq-entrypoint.sh
エントリポイントスクリプトとDockerfileを配置すると、Composeファイルでサービスを定義する準備が整います。
ステップ4—DockerComposeを使用したサービスの定義
Docker Composeを使用すると、セットアップに必要な複数のコンテナーを実行できるようになります。 メインのdocker-compose.yml
ファイルでComposeservicesを定義します。 Composeのサービスは実行中のコンテナーであり、サービス定義(docker-compose.yml
ファイルに含める)には、各コンテナーイメージの実行方法に関する情報が含まれています。 作成ツールを使用すると、複数のサービスを定義して、マルチコンテナーアプリケーションを構築できます。
アプリケーションのセットアップには、次のサービスが含まれます。
- アプリケーション自体
- PostgreSQLデータベース
- Redis
- Sidekiq
また、セットアップの一部としてバインドマウントを含めるため、開発中に行ったコードの変更は、このコードにアクセスする必要のあるコンテナーとすぐに同期されます。
テストはこのチュートリアルとシリーズの範囲外であるため、ではなく test
サービスを定義していることに注意してください。ただし、前例に従うことでそうすることができます。ここではsidekiq
サービスに使用しています。
docker-compose.yml
ファイルを開きます。
nano docker-compose.yml
まず、アプリケーションサービス定義を追加します。
〜/ rails-docker / docker-compose.yml
version: '3.4' services: app: build: context: . dockerfile: Dockerfile depends_on: - database - redis ports: - "3000:3000" volumes: - .:/app - gem_cache:/usr/local/bundle/gems - node_modules:/app/node_modules env_file: .env environment: RAILS_ENV: development
app
サービス定義には、次のオプションが含まれています。
build
:これは、context
やdockerfile
など、Composeがアプリケーションイメージをビルドするときに適用される構成オプションを定義します。 Docker Hub などのレジストリの既存のイメージを使用する場合は、代わりに image命令を使用して、ユーザー名、リポジトリ、イメージタグに関する情報を使用できます。context
:これは、イメージビルドのビルドコンテキスト(この場合は現在のプロジェクトディレクトリ)を定義します。dockerfile
:これは、Composeがアプリケーションイメージのビルドに使用するファイルとして、現在のプロジェクトディレクトリのDockerfile
を指定します。depends_on
:これにより、database
およびredis
コンテナーが最初にセットアップされ、app
より前に稼働します。ports
:これは、ホストのポート3000
をコンテナーのポート3000
にマップします。volumes
:ここには2種類のマウントが含まれています: 1つ目は、ホスト上のアプリケーションコードをコンテナの/appディレクトリにマウントするバインドマウントです。 これにより、ホストコードに加えた変更がすぐにコンテナに入力されるため、迅速な開発が容易になります。 2つ目は、名前付きボリュームgem_cacheです。 バンドルインストール命令がコンテナで実行されると、プロジェクトgemがインストールされます。 このボリュームを追加すると、コンテナを再作成すると、gemが新しいコンテナにマウントされます。 このマウントは、プロジェクトに変更がないことを前提としているため、開発中にプロジェクトgemに変更を加える場合は、アプリケーションサービスを再作成する前に、このボリュームを削除することを忘れないでください。 3番目のボリュームは、node_modulesディレクトリーの名前付きボリュームです。 node_modulesをホストにマウントして、開発中にパッケージの不一致や権限の競合を引き起こす可能性があるのではなく、このボリュームは、このディレクトリ内のパッケージが永続化され、プロジェクトの現在の状態を反映することを保証します。 この場合も、プロジェクトのノードの依存関係を変更する場合は、このボリュームを削除して再作成する必要があります。env_file
:これは、ビルドコンテキストにある.env
というファイルから環境変数を追加することをComposeに通知します。environment
:このオプションを使用すると、機密性の低い環境変数を設定して、Rails環境に関する情報をコンテナーに渡すことができます。
次に、app
サービス定義の下に、次のコードを追加してdatabase
サービスを定義します。
〜/ rails-docker / docker-compose.yml
. . . database: image: postgres:12.1 volumes: - db_data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql
app
サービスとは異なり、database
サービスは、 DockerHubからpostgres
イメージを直接プルします。 バージョンをlatest
に設定したり、指定しない(デフォルトではlatest
)のではなく、ここでもバージョンを固定していることに注意してください。 このようにして、このセットアップがここで指定されたバージョンで機能することを確認し、イメージへのコード変更を壊すことによる予期しない驚きを回避できます。
ここにはdb_data
ボリュームも含まれています。これにより、コンテナーの起動間でアプリケーションデータが保持されます。 さらに、sammy
データベースユーザーを作成するために、init.sql
起動スクリプトをコンテナーの適切なディレクトリdocker-entrypoint-initdb.d/
にマウントしました。 イメージエントリポイントは、デフォルトのpostgres
ユーザーとデータベースを作成した後、docker-entrypoint-initdb.d/
ディレクトリにあるスクリプトを実行します。このスクリプトは、必要な初期化タスクに使用できます。 詳細については、PostgreSQLイメージドキュメントの初期化スクリプトセクションを参照してください。
次に、redis
サービス定義を追加します。
〜/ rails-docker / docker-compose.yml
. . . redis: image: redis:5.0.7
database
サービスと同様に、redis
サービスはDockerHubのイメージを使用します。 この場合、Sidekiqジョブキャッシュを永続化することはありません。
最後に、sidekiq
サービス定義を追加します。
〜/ rails-docker / docker-compose.yml
. . . sidekiq: build: context: . dockerfile: Dockerfile depends_on: - app - database - redis volumes: - .:/app - gem_cache:/usr/local/bundle/gems - node_modules:/app/node_modules env_file: .env environment: RAILS_ENV: development entrypoint: ./entrypoints/sidekiq-entrypoint.sh
sidekiq
サービスは、いくつかの点でapp
サービスに似ています。同じビルドコンテキストとイメージ、環境変数、およびボリュームを使用します。 ただし、app
、redis
、およびdatabase
サービスに依存しているため、最後に開始します。 さらに、Dockerfileで設定されたエントリポイントをオーバーライドするentrypoint
を使用します。 このentrypoint
設定は、entrypoints/sidekiq-entrypoint.sh
を指します。これには、sidekiq
サービスを開始するための適切なコマンドが含まれています。
最後のステップとして、sidekiq
サービス定義の下にボリューム定義を追加します。
〜/ rails-docker / docker-compose.yml
. . . volumes: gem_cache: db_data: node_modules:
トップレベルのボリュームキーは、ボリュームgem_cache
、db_data
、およびnode_modules
を定義します。 Dockerがボリュームを作成すると、ボリュームのコンテンツは、Dockerによって管理されるホストファイルシステム/var/lib/docker/volumes/
の一部に保存されます。 各ボリュームの内容は、/var/lib/docker/volumes/
の下のディレクトリに保存され、ボリュームを使用する任意のコンテナにマウントされます。 このように、ユーザーが作成するサメ情報データは、database
サービスを削除して再作成しても、db_data
ボリュームに保持されます。
完成したファイルは次のようになります。
〜/ rails-docker / docker-compose.yml
version: '3.4' services: app: build: context: . dockerfile: Dockerfile depends_on: - database - redis ports: - "3000:3000" volumes: - .:/app - gem_cache:/usr/local/bundle/gems - node_modules:/app/node_modules env_file: .env environment: RAILS_ENV: development database: image: postgres:12.1 volumes: - db_data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql redis: image: redis:5.0.7 sidekiq: build: context: . dockerfile: Dockerfile depends_on: - app - database - redis volumes: - .:/app - gem_cache:/usr/local/bundle/gems - node_modules:/app/node_modules env_file: .env environment: RAILS_ENV: development entrypoint: ./entrypoints/sidekiq-entrypoint.sh volumes: gem_cache: db_data: node_modules:
編集が終了したら、ファイルを保存して閉じます。
サービス定義を記述したら、アプリケーションを開始する準備が整います。
ステップ5—アプリケーションのテスト
docker-compose.yml
ファイルを配置したら、 docker-compose up コマンドを使用してサービスを作成し、データベースをシードできます。 docker-compose down を使用してコンテナーを停止および削除し、それらを再作成することで、データが保持されることをテストすることもできます。
まず、コンテナイメージをビルドし、docker-compose up
を-d
フラグで実行してサービスを作成します。これにより、コンテナがバックグラウンドで実行されます。
docker-compose up -d
サービスが作成されたという出力が表示されます。
OutputCreating rails-docker_database_1 ... done Creating rails-docker_redis_1 ... done Creating rails-docker_app_1 ... done Creating rails-docker_sidekiq_1 ... done
また、サービスからのログ出力を表示することにより、起動プロセスに関するより詳細な情報を取得できます。
docker-compose logs
すべてが正しく開始されている場合は、次のように表示されます。
Outputsidekiq_1 | 2019-12-19T15:05:26.365Z pid=6 tid=grk7r6xly INFO: Booting Sidekiq 6.0.3 with redis options {:host=>"redis", :port=>"6379", :id=>"Sidekiq-server-PID-6", :url=>nil} sidekiq_1 | 2019-12-19T15:05:31.097Z pid=6 tid=grk7r6xly INFO: Running in ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-musl] sidekiq_1 | 2019-12-19T15:05:31.097Z pid=6 tid=grk7r6xly INFO: See LICENSE and the LGPL-3.0 for licensing details. sidekiq_1 | 2019-12-19T15:05:31.097Z pid=6 tid=grk7r6xly INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org app_1 | => Booting Puma app_1 | => Rails 5.2.3 application starting in development app_1 | => Run `rails server -h` for more startup options app_1 | Puma starting in single mode... app_1 | * Version 3.12.1 (ruby 2.5.1-p57), codename: Llamas in Pajamas app_1 | * Min threads: 5, max threads: 5 app_1 | * Environment: development app_1 | * Listening on tcp://0.0.0.0:3000 app_1 | Use Ctrl-C to stop . . . database_1 | PostgreSQL init process complete; ready for start up. database_1 | database_1 | 2019-12-19 15:05:20.160 UTC [1] LOG: starting PostgreSQL 12.1 (Debian 12.1-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit database_1 | 2019-12-19 15:05:20.160 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432 database_1 | 2019-12-19 15:05:20.160 UTC [1] LOG: listening on IPv6 address "::", port 5432 database_1 | 2019-12-19 15:05:20.163 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432" database_1 | 2019-12-19 15:05:20.182 UTC [63] LOG: database system was shut down at 2019-12-19 15:05:20 UTC database_1 | 2019-12-19 15:05:20.187 UTC [1] LOG: database system is ready to accept connections . . . redis_1 | 1:M 19 Dec 2019 15:05:18.822 * Ready to accept connections
docker-compose ps を使用して、コンテナのステータスを確認することもできます。
docker-compose ps
コンテナが実行されていることを示す出力が表示されます。
Output Name Command State Ports ----------------------------------------------------------------------------------------- rails-docker_app_1 ./entrypoints/docker-resta ... Up 0.0.0.0:3000->3000/tcp rails-docker_database_1 docker-entrypoint.sh postgres Up 5432/tcp rails-docker_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp rails-docker_sidekiq_1 ./entrypoints/sidekiq-entr ... Up
次に、データベースを作成してシードし、次のdocker-composeexecコマンドを使用してデータベースで移行を実行します。
docker-compose exec app bundle exec rake db:setup db:migrate
docker-compose exec
コマンドを使用すると、サービスでコマンドを実行できます。 ここでは、これを使用して、アプリケーションバンドルのコンテキストでrake db:setup
およびdb:migrate
を実行し、データベースを作成してシードし、移行を実行します。 開発作業中、docker-compose exec
は、開発データベースに対して移行を実行する場合に役立ちます。
このコマンドを実行すると、次の出力が表示されます。
OutputCreated database 'rails_development' Database 'rails_development' already exists -- enable_extension("plpgsql") -> 0.0140s -- create_table("endangereds", {:force=>:cascade}) -> 0.0097s -- create_table("posts", {:force=>:cascade}) -> 0.0108s -- create_table("sharks", {:force=>:cascade}) -> 0.0050s -- enable_extension("plpgsql") -> 0.0173s -- create_table("endangereds", {:force=>:cascade}) -> 0.0088s -- create_table("posts", {:force=>:cascade}) -> 0.0128s -- create_table("sharks", {:force=>:cascade}) -> 0.0072s
サービスを実行している状態で、ブラウザでlocalhost:3000
またはhttp://your_server_ip:3000
にアクセスできます。 次のようなランディングページが表示されます。
これで、データの永続性をテストできます。 Get Shark Info ボタンをクリックして新しいサメを作成します。これにより、sharks/index
ルートに移動します。
アプリケーションが機能していることを確認するために、いくつかのデモ情報をアプリケーションに追加できます。 NewSharkをクリックします。 プロジェクトの認証設定のおかげで、ユーザー名( sammy )とパスワード( shark )の入力を求められます。
New Shark ページで、 Name フィールドに「Mako」を入力し、Factsフィールドに「Fast」を入力します。
サメの作成ボタンをクリックしてサメを作成します。 サメを作成したら、サイトのナビゲーションバーでホームをクリックして、メインのアプリケーションランディングページに戻ります。 これで、Sidekiqが機能していることをテストできます。
どのサメが危険にさらされていますか?ボタンをクリックします。 絶滅危惧種のサメをアップロードしていないため、endangered
index
ビューに移動します。
絶滅危惧種のサメのインポートをクリックして、サメをインポートします。 サメが輸入されたことを知らせるステータスメッセージが表示されます。
インポートの開始も表示されます。 ページを更新して、テーブル全体を表示します。
Sidekiqのおかげで、絶滅危惧種のサメの大量のバッチアップロードは、ブラウザをロックしたり、他のアプリケーション機能に干渉したりすることなく成功しました。
ページの下部にあるホームボタンをクリックすると、アプリケーションのメインページに戻ります。
ここから、どのサメが危険にさらされていますか?をもう一度クリックします。 アップロードされたサメがもう一度表示されます。
アプリケーションが正しく機能していることがわかったので、データの永続性をテストできます。
ターミナルに戻り、次のコマンドを入力して、コンテナを停止して削除します。
docker-compose down
--volumes
オプションは含まれていないことに注意してください。 したがって、db_data
ボリュームは削除されません。
次の出力は、コンテナとネットワークが削除されたことを確認します。
OutputStopping rails-docker_sidekiq_1 ... done Stopping rails-docker_app_1 ... done Stopping rails-docker_database_1 ... done Stopping rails-docker_redis_1 ... done Removing rails-docker_sidekiq_1 ... done Removing rails-docker_app_1 ... done Removing rails-docker_database_1 ... done Removing rails-docker_redis_1 ... done Removing network rails-docker_default
コンテナを再作成します。
docker-compose up -d
docker-compose exec
およびbundle exec rails console
を使用して、app
コンテナーでRailsコンソールを開きます。
docker-compose exec app bundle exec rails console
プロンプトで、データベースのlast
シャークレコードを調べます。
Shark.last.inspect
作成したばかりのレコードが表示されます。
IRB session Shark Load (1.0ms) SELECT "sharks".* FROM "sharks" ORDER BY "sharks"."id" DESC LIMIT $1 [["LIMIT", 1]] => "#<Shark id: 5, name: \"Mako\", facts: \"Fast\", created_at: \"2019-12-20 14:03:28\", updated_at: \"2019-12-20 14:03:28\">"
次に、次のコマンドを使用して、Endangered
サメが持続していることを確認できます。
Endangered.all.count
IRB session (0.8ms) SELECT COUNT(*) FROM "endangereds" => 73
db_data
ボリュームは、再作成されたdatabase
サービスに正常にマウントされ、app
サービスが保存されたデータにアクセスできるようになりました。 localhost:3000/sharks
またはhttp://your_server_ip:3000/sharks
にアクセスしてindex
shark
ページに直接移動すると、次のレコードも表示されます。
絶滅危惧種のサメもlocalhost:3000/endangered/data
またはhttp://your_server_ip:3000/endangered/data
ビューに表示されます。
これで、アプリケーションは、データの永続性とコードの同期が有効になっているDockerコンテナで実行されます。 app
サービスの一部として定義したバインドマウントのおかげで、ホストでローカルコードの変更をテストできます。これは、コンテナに同期されます。
結論
このチュートリアルに従うことで、Dockerコンテナーを使用してRailsアプリケーションの開発セットアップを作成しました。 機密情報を抽出し、アプリケーションの状態をコードから切り離すことで、プロジェクトをよりモジュラーでポータブルにしました。 また、開発のニーズや要件の変化に応じて修正できる定型文docker-compose.yml
ファイルを構成しました。
開発するにつれて、コンテナ化された CloudNativeワークフロー用のアプリケーションの設計についてさらに学ぶことに興味があるかもしれません。 これらのトピックの詳細については、Kubernetes用アプリケーションのアーキテクチャおよびKubernetes用アプリケーションの最新化を参照してください。 または、Kubernetesの学習シーケンスに投資したい場合は、フルスタック開発者向けKubernetesカリキュラムをご覧ください。
アプリケーションコード自体の詳細については、このシリーズの他のチュートリアルを参照してください。