Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

既存のRailsアプリケーションのコンテナ化

コンテナ化ソフトウェアは、開発と展開を容易にするために、標準化されたユニットにパッケージ化しています。コンテナは、アプリケーションのコードとそのすべての依存関係をバンドルします。コンテナは完全にスタンドアロンにすることができます。これには、ソフトウェア、ランタイム環境、およびシステムライブラリを含むパッケージが含まれています。コンテナは、開発者と運用チームが、環境に関係なく、ソフトウェアが同じように実行されることを保証するのに役立ちます。コードをインフラストラクチャから分離することで、「コンテナ化」されたアプリは、ローカル環境、テスト環境、本番環境で同じように実行されます。

Dockerは、ソフトウェアを開発およびデプロイするための最も人気のあるプラットフォームの1つです。 Dockerは、ソフトウェアを「イメージ」としてパッケージ化します。これは、Dockerイメージで実行されると、実行時にコンテナーに変換されます。分離により、開発者は単一のホストで同時に多くのコンテナーを実行できます。

Railsの開発者は、既存のアプリケーションをコンテナ化するときに、独自の一連の課題に直面します。この記事では、機能的なRailsアプリをコンテナー化するためのウォークスルーを提供し、その過程で重要な概念と落とし穴について説明します。この記事は、コンテナーまたはDockerの基本的な説明ではありません。代わりに、本番アプリケーションをコンテナ化するときに開発者が直面する問題の説明です。

前提条件

フォローしている場合は、まだドッキングされていないRailsアプリケーションが必要になることは明らかです(これは、「コンテナー化」のDocker固有の用語です)。私は、完全な機能を備えたサイドプロジェクトであるRailsWorkを使用します。発売。 Railsで作成され、Herokuにデプロイされた求人掲示板ですが、コンテナ化されていません。

それ以外にも、Dockerをインストールする必要があります。インストールする一般的な方法は、公式WebサイトからダウンロードできるDockerデスクトップを使用することです。

既存のRailsアプリケーションのコンテナ化

アプリがダウンロードされたら、インストーラーを実行します。実行後、アプリケーションをアプリケーションフォルダにドラッグするように求められます。次に、アプリケーションフォルダからアプリを起動する必要があります 要求された特権権限を付与します。 Dockerが正しくインストールされていることを確認する最後のチェックとして、次のコマンドを実行して、端末からマシンで実行されているコンテナーを一覧表示してみてください。

docker ps

Dockerがインストールされている場合(そしてコンテナーを実行していない場合)、次のようなヘッダーのみを含む空のリストが表示されます。

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Dockerfile

深く掘り下げる前に、明確な用語から始めることが重要です。

Railsアプリケーションが「Dockerized」されると、コンテナで実行されます。 。コンテナはスタンドアロンで、交換可能で、多くの場合再構築されます。

コンテナは画像から構築されます 。イメージは、メタデータとペアになったファイルシステムの仮想スナップショットです。

Dockerfile 画像の作成方法を説明するソースコードです。 Dockerfileは、Docker化されたアプリのリポジトリに含まれ、アプリの他の部分と一緒にバージョン管理で追跡されることがよくあります。

Dockerfileの作成は、思ったより簡単です。 Dockerは、何かをコンテナー化するという大変な作業を抽象化する特別な構文を提供します。まず、コンテナ化するアプリのルートディレクトリに移動します。作業を開始する準備ができたので、gitを使用している場合は、新しいブランチを作成することをお勧めします。 dockerize-this-appという名前の新しいブランチを簡単に作成できます 次のコマンドを実行します:

git checkout -b dockerize-this-app

次に、Dockerfileを作成し、Rubyアプリケーションに基づいてイメージを構築するように指示します。これは、コマンドラインから次のコマンドを実行して実行できます。

echo "FROM ruby:3.0.0" > Dockerfile

ここでは、Dockerfileを作成し、Rubyコンテナイメージの場所を指定する行を追加しています。私のプロジェクトはRuby3.0.0を使用しているので、適切なイメージを使用しました。別のバージョンのRubyを使用している場合は、問題ありません。 Dockerには、サポートされているすべてのイメージのリストがあります。

次に、DockerにDockerイメージを作成するように手動で指示します。

docker build -t rails_work .

ここで、rails_workを置き換えることができます 画像に任意の名前を付けます。また、必ず最後にピリオドを含めてください!

イメージが作成されたことを確認したい場合は、次の方法でシステム上のイメージを一覧表示できます。

docker image list

ただし、この画像はほとんど空です。現在、アプリケーションは含まれていません。 Dockerfileの最後に以下を追加することで、アプリからコードを追加するように指示できます。

ADD . /rails_work
WORKDIR /rails_work
RUN bundle install

これにより、アプリケーションからファイルがコピーされ、アプリケーションの依存関係がインストールされます。 (ここでは、rails_workを置き換えます アプリの名前で。)

この時点で、コマンドを再実行してイメージを作成する必要があります。

docker image list

ここに問題が発生する可能性があります 特に、既存の本番アプリケーションに対してこれを行う場合。 Bundlerは、イメージが使用しようとしているBundlerのバージョンが、Gemfile.lockを作成したバージョンとは異なると文句を言う場合があります。 ファイル。これが発生した場合、2つの明確なオプションがあります:

  • 画像が使用しているバージョンを変更します。
  • Gemfile.lockを削除します 全体的に。 **これを行う場合は、ロックファイルが完全に再生成されるため、特定のバージョンで必要なGemsのバージョンを固定してください。

それでもバンドルのインストールが失敗する場合は、Dockerfileに追加のインストールが必要になる場合があります

RUN apt-get update && apt-get install -y shared-mime-info

それでも問題が発生する場合は、ベースとなる間違ったRubyイメージを選択した可能性があります 、そこで調査を開始する価値があります。

これは、環境変数を設定する良い機会です。 :

ENV RAILS_ENV production
ENV RAILS_SERVE_STATIC_FILES true

次に、Railsがデフォルトで実行されるポート3000を公開する行を追加します。

EXPOSE 3000

最後に、起動時にbashシェルを開くようにコンテナに指示します。

CMD ["bash"]

全体として、Dockerfileは次のようになります(rails_work名が置き換えられます):

FROM ruby:3.0.0

ADD . /rails_work
WORKDIR /rails_work
RUN bundle install

ENV RAILS_ENV production
ENV RAILS_SERVE_STATIC_FILES true

EXPOSE 3000
CMD ["bash"]
ドッカーコマンドの説明

最も一般的なDockerfileコマンドのいくつかを完全に理解しておくと確かに役立ちます。

  • FROM->これは、ベースとなる画像を定義します。
  • RUN->これは内部のコマンドを実行します コンテナ。
  • ENV->これは環境変数を定義します。
  • WORKDIR->これにより、コンテナが使用しているディレクトリが変更されます。
  • CMD->コンテナの起動時に実行するプログラムを指定します。
ドッカー作成

Dockerのドキュメントによると、「作成」は、複数のDockerコンテナーを使用してアプリケーションを作成(および起動)するためのツールです。アプリケーションに必要なコンテナーを起動するために必要なものはすべて、YAMLで概説されています。誰かがdocker-compose upを実行したとき 、コンテナが作成されます! Docker-composeを使用すると、コンテナー構成を宣言的に記述できます。

Docker Composeファイルを作成する前に、ビルドされるイメージからどのファイルを除外する必要があるかをDockerに示すことが重要です。 .dockerignoreというファイルを作成します 。 (ピリオドに注意してください!)このファイルに、以下を貼り付けます:

.git
.dockerignore
.env

Gemfileがビルドプロセスによって維持されている場合は、必ずGemfile.lockを追加してください。 上記の無視に。

次に、docker-compose.ymlというファイルを作成します 。ここで、コンテナの構成について説明します。ファイルの内容については、これから始めます:

version: '3.8'
services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    volumes:
      - postgres:/var/lib/postgresql/data
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/Rails-Docker
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  postgres:

このファイルは2つのサービスを作成します。1つはdbと呼ばれます もう1つはwebと呼ばれます 。 dbコンテナは、postgres用に作成されたイメージから構築されるため、POSTGRES_USERの関連する値を置き換える必要があります。 およびPOSTGRES_PASSWORD制作の秘密を入れないように注意する このファイルの内容-詳細については、以下の「秘密の管理」セクションを参照してください。

WebコンテナはDockerfileから構築され、IPアドレス0.0.0.0のポート3000でRailsサーバーを起動します。次に、内部ポート3000が実際のポート3000にマップされます。

そして最後に、データを永続化するためのPostgresボリュームがあります。

シークレットの管理

ビルド時の認証は、実稼働アプリケーションでは問題になる可能性があります。おそらく、アプリケーションがプライベートリポジトリからGemsを探しているか、データベースのクレデンシャルを保存する必要があるだけです。

Dockerfileに直接含まれる情報はすべて、コンテナイメージに永久に焼き付けられます。これは、一般的なセキュリティの落とし穴です。

Railsのクレデンシャルマネージャーを使用している場合、Docker(またはそのことについては任意のホスト)にアクセスを許可することは比較的簡単です。 Docker Composeファイルでは、RAILS_MASTER_KEYを指定するだけです。 環境変数。指定された作成ターゲットに対して、environmentの下でキーを指定します ヘッダー。まだ作成していない場合は作成する必要があります。上からのdocker-composeファイルは次のようになります:

version: '3.8'
services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    volumes:
      - postgres:/var/lib/postgresql/data
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/Rails-Docker
    ports:
      - "3000:3000"
    depends_on:
      - db
    environment:
      - RAILS_MASTER_KEY=this_would_be_the_key
volumes:
  postgres:

さて、これはあなたを岐路に立たせます。このファイルをソース管理にコミットすることをお勧めしますが、ソース管理によってマスターキーやデータベースパスワードを追跡することは絶対に望まない 、これは別の危険なセキュリティ問題になるためです。これまでの最善の解決策は、dotenv gemを利用して、プロキシでこれらのクレデンシャルにアクセスし、別のファイルに保存できるようにすることです。 ソース管理では追跡されません。

Dockerizedアプリケーションの実行

最後に、次のコマンドを使用してドッキングされたアプリケーションを実行できます。

docker compose up

信じられないかもしれませんが、それだけです。 Docker-composeを使用すると、特にコマンドライン引数に関して、コンテナーを簡単に起動できます。

実行中のコンテナのリストが必要な場合は、次を実行するだけです。

docker ps

Railsコンテナ名がwebの場合 、かなり簡単な方法でコマンドを実行できます。たとえば、Railsコンソールを実行する場合は、次を実行するだけです。

docker exec -it web rails console

コンテナ内にbashシェルが必要な場合は、代わりに次を実行します。

docker exec -it web bash
ここにリストされているようないくつかの落とし穴

本番環境でのドッキングされたRailsアプリケーションの一般的な問題の1つは、ログの処理です。それらは、コンテナシステムに長期間存在するべきではありません。 Dockerは、ログを単にSTDOUTにリダイレクトすることを提案しています。これは、config/application.rbで明示的に構成できます。 。

もう1つの一般的な問題は、メーラーの問題です。アプリケーションでメーラーを使用する場合は、接続設定を明示的に定義する必要があります 。 SMTPは完全に優れた配信方法であり、通常はデフォルトで適切に機能しますが、サーバーの場所やその他の設定をコンテナの構成と一致するように注意深く設定する必要があります。

sidekiqなどの労働者またはバックグラウンドの仕事がある場合 、次にそれを独自のコンテナで実行する必要があります。

結論

確かに見てきたように、本番Railsアプリケーションのコンテナー化には一連の課題が伴います。アプリケーションが成長するにつれて、このような移行を困難にする多くの依存関係が蓄積されている可能性があります。バックグラウンドワーカー、メーラー、シークレットのいずれであっても、ほとんどの落とし穴を処理するための確立されたパターンがあります。本番アプリケーションをDockerで動作させるための最初の作業が完了すると、将来の変更とデプロイが容易になるため、投資する価値があります。


  1. Rails5でのAngularの使用

    あなたは前にその話を聞いたことがあります。分散型で完全に機能するバックエンドAPIと、通常のツールセットで作成されたフロントエンドで実行されているアプリケーションがすでにあります。 次に、Angularに移動します。または、AngularをRailsプロジェクトと統合する方法を探しているだけかもしれません。これは、この方法を好むためです。私たちはあなたを責めません。 このようなアプローチを使用すると、両方の世界を活用して、たとえばRailsとAngularのどちらの機能を使用してフォーマットするかを決定できます。 構築するもの 心配する必要はありません。このチュートリアルは、この目的のた

  2. RailsアプリケーションでOmniAuth-Twitterを使用する方法

    このチュートリアルでは、アプリケーションのユーザーがTwitterアカウントを使用してログインできるようにする方法を学習します。これを行うには、OAuthなどのツールを使用すると簡単になります。 OmniAuthのTwitter戦略を含むOmniAuth-Twitterを利用します。 飛び込みましょう! はじめに Railsアプリケーションを生成することから始めます。ターミナルから、コマンドを実行して実行します。 rails new Tuts-Social -T Gemfileを開き、ブートストラップgemを追加します。 #Gemfile...gem bootstra