Ubuntu 16.04でMySQLを使用してElixir-Phoenixアプリケーションを展開する方法

_著者はhttps://www.brightfunds.org/organizations/code-org[Code.org]を選択して、https://do.co/w4do-cta [Write for DOnations]プログラムの一環として300ドルの寄付を受け取りました。 _

前書き

チュートリアルではhttps://www.digitalocean.com/community/tutorials/how-to-automate-elixir-phoenix-deployment-with-distillery-and-edeliver-on-ubuntu-16-04[Elixir Phoenixを自動化する方法Distilleryとedeliverを使用した展開]では、データベースなしでPhoenixアプリケーションを作成し、https://github.com/edeliver/edeliver [edeliver]を使用して運用サーバーに展開しました。 ほとんどの実際のアプリケーションでは、展開プロセスにいくつかの変更が必要なデータベースが必要です。

edeliverを使用して、アプリケーションとデータベースの変更を運用サーバーに同時にプッシュできるため、展開中にデータベースの変更を管理できます。

このガイドでは、https://github.com/phoenixframework/phoenix_ecto [Phoenix-Ecto]およびhttps://github.com/xerions/mariaex[Mariaex]を使用して、MySQLデータベースに接続するように既存のPhoenixアプリケーションを構成します。 。 Ectoは、Phoenixアプリケーションで広く使用されているデータベースラッパーです。 Mariaexは、Ectoと統合し、MySQLおよびMariaDBデータベースと通信するデータベースドライバーです。

また、データベースを使用する開発マシンで簡単なアドレス帳を作成し、edeliverを使用して運用サーバーに変更を展開します。 サイトのユーザーは、このアドレス帳のエントリを作成、読み取り、更新、および削除できます。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • チュートリアルhttps://www.digitalocean.com/community/tutorials/how-to-automate-elixir-phoenix-deployment-with-distillery-and-edeliver-on-ubuntu-16-04[How蒸留酒製造所とedeliverでElixir Phoenixの展開を自動化する]。 このアプリは、Let’s Encrypt証明書を使用してNginxの背後で実行され、edeliverで展開される必要があります。

  • Ubuntu 16.04にMySQLをインストールする方法に従ってサーバーにインストールされたMySQL。

  • 展開する前にデータベースをテストするために、ローカル開発マシンにインストールされたMySQL。

ステップ1-MariaexとEctoをアプリケーションに追加する

通常、Phoenixアプリケーションはデータベースへの接続を直接確立せず、SQLクエリを実行しません。 代わりに、_database driver_を使用して目的のデータベースに接続し、_database wrapper_を使用してデータベースを照会します。

データベースドライバーは、接続の確立、接続の終了、クエリの実行など、データベースを使用する日常的なタスクを処理するElixirアプリケーションです。 データベースラッパーは、ElixirプログラマーがElixirコードを使用してデータベースクエリを作成できるようにするデータベースドライバー上のレイヤーであり、クエリ構成(クエリのチェーン)などの追加機能を提供します。

この分離により、モジュラーアプリケーションが実現します。 データベースラッパー、したがってデータベースと対話するアプリケーションコードは、使用するデータベースに関係なくほぼ同じです。 データベースドライバーを変更するだけで、Phoenixアプリケーションは別のデータベースソフトウェアを使用できます。

https://www.digitalocean.com/community/tutorials/how-to-automate-elixir-phoenix-deployment-with-distillery-andでアプリケーションを作成するときに「+-no-ecto +」フラグを指定したため-edeliver-on-ubuntu-16-04 [前のチュートリアル]、アプリケーションにはEctoもMariaexもインストールされていません。 ここで、プロジェクトの依存関係としてEctoとMariaexを追加します。

まず、フェニックスプロジェクトを含むディレクトリに切り替えます。

cd ~/

次に、アプリケーションの依存関係のリストを含む `+ mix.exs +`ファイルを開きます。

nano mix.exs

次のコードブロックを見つけます。

〜/ myproject / mix.exs

 defp deps do
   [
     {:phoenix, "~> 1.3.0"},
     {:phoenix_pubsub, "~> 1.0"},
     {:phoenix_html, "~> 2.10"},
     {:phoenix_live_reload, "~> 1.0", only: :dev},
     {:gettext, "~> 0.11"},
     {:cowboy, "~> 1.0"},
     {:edeliver, "~> 1.4.3"},
     {:distillery, "~> 1.4"}
   ]
 end

MariaexとPhoenix-Ectoを依存関係として追加します。

〜/ myproject / mix.exs

 defp deps do
   [
     {:phoenix, "~> 1.3.0"},
     {:phoenix_pubsub, "~> 1.0"},
     {:phoenix_html, "~> 2.10"},
     {:phoenix_live_reload, "~> 1.0", only: :dev},
     {:gettext, "~> 0.11"},
     {:cowboy, "~> 1.0"},
     {:edeliver, "~> 1.4.3"},
     {:distillery, "~> 1.4"}


   ]
 end

`+ mix.exs +`を保存して閉じます。 次に、次のコマンドを実行して、プロジェクトに追加したばかりの依存関係をダウンロードします。

mix deps.get

依存関係がインストールされると、次の出力が表示されます。

OutputRunning dependency resolution...
...
* Getting phoenix_ecto (Hex package)
 Checking package (https://repo.hex.pm/tarballs/phoenix_ecto-3.3.0.tar)
 Fetched package
* Getting mariaex (Hex package)
 Checking package (https://repo.hex.pm/tarballs/mariaex-0.8.3.tar)
 Fetched package
...

出力は、Mixがパッケージ間の互換性をチェックし、Hexリポジトリからパッケージとその依存関係を取得したことを示しています。 このコマンドが失敗する場合は、Hexがインストールされており、 `+ mix.exs +`が正しく変更されていることを確認してください。

EctoとMariaexを配置すると、Ectoリポジトリをセットアップできます。

手順2-アプリケーションでのEctoリポジトリのセットアップ

Phoenixアプリケーションは、Ectoと呼ばれるデータベースラッパーを介してデータベースにアクセスします。 データベースラッパーは、プロジェクトのElixirモジュールの形式で実装されます。 データベースと対話し、モジュールが提供する機能を使用する必要があるときはいつでも、このモジュールをインポートできます。 ラップされたデータベースは、_repository_と呼ばれます。

このリポジトリモジュールには、Ectoで定義されたクエリ関数へのアクセスを許可するために、 `+ Ecto.Repo `マクロを含める必要があります。 また、 ` init +`という名前の関数でデータベースアダプターに渡されるオプションを初期化するコードを含める必要があります。

Phoenixプロジェクトの作成時に `+-no-ecto +`フラグを使用していなかった場合、Phoenixはこのモジュールを自動的に生成していました。 ただし、作成したので、自分で作成する必要があります。

`+ lib / `ディレクトリの ` repo.ex +`という名前のファイルにモジュールを作成しましょう。 最初にファイルを作成します。

nano lib//repo.ex

次のコードをファイルに追加して、リポジトリを定義します。

〜/ myproject / lib / myproject / repo.ex

defmodule .Repo do
 use Ecto.Repo, otp_app: :

 @doc """
 Dynamically loads the repository url from the
 DATABASE_URL environment variable.
 """
 def init(_, opts) do
   {:ok, Keyword.put(opts, :url, System.get_env("DATABASE_URL"))}
 end
end

デフォルトでは、Phoenixプロジェクトは、環境変数 `+ DATABASE_URL `が存在する場合、EctoがPhoenix構成ファイルの資格情報を使用する代わりに、環境変数の構成を使用してデータベースに接続するように、 ` init +`関数を定義します(このチュートリアルで後述するように)。

`+ repo.ex +`を保存して閉じます。

Phoenixプロジェクトは、同時実行性とフォールトトレランスのために軽量のElixirプロセスを使用します。 _Supervisors_は、クラッシュした場合にこれらのプロセスを管理して再起動します。 スーパーバイザーは他のスーパーバイザーを監督することもでき、この構造は「スーパービジョンツリー」と呼ばれます。

追加したばかりの `+ Myproject.Repo +`モジュールは、データベースに接続するプロセスを管理するスーパーバイザーを実装します。 このスーパーバイザーを開始するには、プロジェクトの監視ツリーに追加する必要があります。

`+ lib / `フォルダーの ` application.ex +`ファイルを開きます。

nano lib//application.ex

監視ツリーを定義する次のコードブロックを見つけます。

〜/ myproject / lib / myproject / application.ex

...
   children = [
     # Start the endpoint when the application starts
     supervisor(.Endpoint, []),
     ...
   ]
...

アプリケーションエンドポイントである `+ MyprojectWeb.Endpoint `がスーパーバイザーとして開始されていることがわかります。 このリストに ` Myproject.Repo +`を追加します。

〜/ myproject / lib / myproject / myproject.ex

   children = [


     # Start the endpoint when the application starts
     supervisor(MyprojectWeb.Endpoint, []),
     ...
   ]

この手順をスキップすると、Ectoはデータベースと対話するプロセスを作成せず、データベースと対話しようとするとアプリケーションがクラッシュします。

続行する前に、 `+ application.ex +`を保存して閉じます。

最後に、アプリケーション構成でEctoリポジトリを指定して、 `+ ecto.create `や ` ecto.migrate +`などのMixタスクを使用してデータベースを作成および管理できるようにします。

`+ config / config.exs +`で設定ファイルを開きます。

nano config/config.exs

ファイルの最後で次の行を見つけます。

〜/ myproject / config / config.exs

import_config "#{Mix.env}.exs"

この行により、 `+ prod.exs `や ` test.exs `などの環境固有の設定ファイルで、必要に応じて ` config.exs +`の設定を上書きできます。 その行の上に次のコードを追加して、Ectoリポジトリを構成します。

〜/ myproject / config / config.exs

...

config :,
 ecto_repos: [.Repo]
...

変更を保存してファイルを閉じます。

Ectoを構成したので、次にデータベース資格情報をアプリケーションに追加します。

手順3-MySQL資格情報を使用したアプリケーションの構成

アプリケーションがデータベースに接続する状況は、開発中、テスト中、本番中の3つです。

同様に、Phoenixは、アプリケーションが実行されている環境に関連する資格情報を含む3つの環境固有の構成ファイルを提供します。 これらのファイルは、プロジェクトのルートの「+ config +」ディレクトリにあります。 この手順では、これら3つのファイルを変更します。

まず、開発環境を設定しましょう。 `+ dev.exs +`を開きます。

nano config/dev.exs

MySQLを使用しているため、データベースアダプターを `+ Ecto.Adapters.MySQL +`に設定するには、次の行を追加します。

〜/ myproject / config / dev.exs

config :, .Repo,
 adapter:

次に、同じコードブロックでデータベースの目的の名前を指定します。

〜/ myproject / config / dev.exs

config :myproject, Myproject.Repo,
 adapter: Ecto.Adapters.MySQL

ここでは、開発データベース名を「+ _dev 」に定義します。 これは、Phoenixアプリがデータベースに使用する命名規則です。 この規則に従って、本番データベースは「 _prod 」、テストデータベースは「 _test +」と呼ばれます。 代わりに独自の命名スキームを使用できます。

次に、開発データベースサーバーのホスト名、ユーザー名、およびパスワードを指定します。

〜/ myproject / config / dev.exs

config :myproject, Myproject.Repo,
 adapter: Ecto.Adapters.MySQL,
 database: "myproject_dev"

最後に、プールサイズを適切な数値に設定します。 プールサイズは、アプリケーションが保持できるデータベースへの接続の最大数です。 これらの接続はリクエスト間で共有されます。 最適なサイズはハードウェアによって異なりますが、開始するには「10」を使用できます。

〜/ myproject / config / dev.exs

config :myproject, Myproject.Repo,
 adapter: Ecto.Adapters.MySQL,
 username: "root",
 password: "password",
 database: "myproject_dev",
 hostname: "localhost"

`+ dev.exs +`を保存して閉じます。

次に、テスト環境を構成します。 テスト環境設定ファイル `+ test.exs +`を開きます。

nano config/test.exs

このチュートリアルでは、開発用データベースと一緒にローカルデータベースサーバーでテストデータベースをホストします。 そのため、テストデータベースの構成はほぼ同じです。

ただし、プールサイズの代わりに、プール値に `+ Ecto.Adapters.SQL.Sandbox +`を指定します。 これにより、サンドボックスモードでテストが実行されます。 つまり、テスト中にテストデータベースで行われたトランザクションはすべてロールバックされます。 また、これは、各テスト後にデータベースが初期状態にリセットされるため、ユニットテストをランダムな順序で実行できることを意味します。

そして、データベース名として「+ myproject_test +」を使用します。

次の設定を `+ test.exs +`ファイルに追加します:

〜/ myproject / config / test.exs

config :, .Repo,
 adapter: Ecto.Adapters.MySQL,
 username: "",
 password: "",
 database: "",
 hostname: "",
 pool: Ecto.Adapters.SQL.Sandbox

`+ test.exs +`を保存して閉じます。

最後に、本番環境でアプリケーションの認証情報を設定するには、本番用の秘密ファイル `+ prod.secret.exs +`を開きます。

nano config/prod.secret.exs

このコードを `+ prod.secret.exs `ファイルに追加します。 ここでは、ユーザー名* myproject *とパスワード ` password +`を使用していることに注意してください。 。ここで指定したパスワードを使用して、本番データベースサーバー上でこのユーザーをすぐに作成します。 ここでは、より安全なパスワードを使用する必要があります。

〜/ myproject / config / prod.secret.exs

config :, .Repo,
 adapter: Ecto.Adapters.MySQL,
 username: "",
 password: "",
 database: "",
 hostname: "",
 pool_size: 10

変更を保存してファイルを閉じます。

このファイルはセキュリティ上の理由からGitによって追跡されないため、手動でサーバーに転送する必要があります。 このプロセスの詳細については、前提条件https://www.digitalocean.com/community/tutorials/how-to-automate-elixir-phoenix-deployment-with-distillery-and-edeliver-on-ubuntuのステップ3を参照してください。 -16-04 [Phoenixアプリケーションのデプロイに関するチュートリアル]。

scp ~/myproject/config/prod.secret.exs @:/home//app_config/prod.secret.exs

次に、 + ecto.create + Mixタスクを呼び出して、開発データベースを作成します。 テストを実行するときにPhoenixが自動的に行うので、テストデータベースを作成する必要はありません。

mix ecto.create

Ectoがデータベースを正常に作成したことを示す次の出力が表示されます。

Output...
The database for .Repo has been created

この出力が表示されない場合は、設定の詳細が正しいことと、MySQLが実行されていることを確認してください。 また、エラーのためにアプリケーションがコンパイルに失敗した場合、Ectoはデータベースの作成を拒否します。

データベースに接続するようにプロジェクトを設定し、開発マシンでEctoを使用してデータベースを作成したので、サーバー上のデータベースの変更に進むことができます。

ステップ4-本番データベースのセットアップ

+ ecto.create + Mixタスクを使用して、開発マシンに空のデータベースを作成しました。 これで、実稼働サーバーでも同じことができます。 残念ながら、これを実現するためのMixタスクやedeliverコマンドはありません。したがって、手動でサーバーにログインし、MySQLコンソールを使用してSQLコマンドで空のデータベースを作成します。

SSH経由でサーバーに接続します。

ssh @
  • root *ユーザーと設定したパスワードを使用してMySQLコンソールにアクセスします。

mysql -u  -p

ログインしたら、本番データベースを作成します。

CREATE DATABASE ;

次の出力が表示され、データベースが作成されたことがわかります。

OutputQuery OK, 1 row affected (0.00 sec)

次に、ユーザー名* myproject *と前の手順で指定したパスワードを使用して、アプリのユーザーを作成します。

CREATE USER ''@'localhost' IDENTIFIED BY '';

次に、作成したデータベースへの* myproject *ユーザーアクセスを許可します。

GRANT ALL PRIVILEGES ON .* to ''@'localhost';

最後に、許可の変更を適用します。

FLUSH PRIVILEGES;

「+ exit 」と入力して、MySQLコンソールを終了します。 もう一度「 exit +」と入力して、SSH接続を終了します。

これからは、ローカルマシンからのテーブルの作成や変更など、ほぼすべての操作を実行するため、本番データベースに触れる必要はほとんどありません。

本番データベースの準備ができたら、アプリケーションをサーバーに再デプロイできます。

手順5-サーバーへのプロジェクトの展開

この手順では、データベースに接続していない実行中のアプリケーションを、新しく構成したアプリケーションとその新しいEctoリポジトリに置き換えます。 この手順により、アプリケーションが正しく構成され、期待どおりに実行されることを確認できます。

`+ mix.exs +`を開き、アプリケーションのバージョンを増やします。 バージョン番号を使用すると、リリースを簡単に追跡し、必要に応じて以前のバージョンにロールバックできます。 また、edeliverがダウンタイムなしでアプリケーションをアップグレードするために使用します。

nano mix.exs

バージョンフィールドを適切な値に増やします。

〜/ myproject / mix.exs

 def project do
   [
     app: :myproject,
     version: "",
     elixir: "~> 1.4",
     elixirc_paths: elixirc_paths(Mix.env),
     compilers: [:phoenix, :gettext] ++ Mix.compilers,
     start_permanent: Mix.env == :prod,
     deps: deps()
   ]
 end

edeliverを使用してデータベースの移行を実行するには、edeliverがプロジェクト内で最後に起動するアプリケーションである必要があります。 次のコードブロックを見つけます。

〜/ myproject / mix.exs

 def application do
   [
     mod: {.Application, []},
     extra_applications: [:logger, :runtime_tools]
   ]
 end

`+ extra_applications `リストの最後に ` edeliver +`を追加します:

〜/ myproject / mix.exs

 def application do
   [
     mod: {.Application, []},
     extra_applications: [:logger, :runtime_tools]
   ]
 end

`+ mix.exs +`を保存して閉じます。

アプリケーションを起動して、すべてが機能し、コンパイルエラーがないことを確認します。

mix phx.server

http:// localhost:4000 [http:// localhost:4000 / addresses]にアクセスして、アプリが引き続き機能することを確認します。 開始しない場合、またはコンパイルエラーが表示される場合は、先に進む前にこのチュートリアルの手順を確認し、解決してください。

すべてが期待どおりに機能している場合は、ターミナルで「+ CTRL + C +」を2回押してサーバーを停止します。

次に、Gitで変更をコミットします。 edeliverはGitを使用してコードを最新のコミットからビルドサーバーにプッシュし、さらにアクションを実行するため、プロジェクトを変更するたびにこれを行う必要があります。

git add .
git commit -m "Configured application with database"

最後に、edeliverを使用して、運用サーバー上のアプリケーションを更新します。 次のコマンドは、ダウンタイムなしで運用マシンで実行されているアプリケーションをアップグレードする前に、プロジェクトの最新バージョンをビルドおよびデプロイします。

mix edeliver upgrade production

次の出力が表示されます。

OutputEDELIVER MYPROJECT WITH UPGRADE COMMAND

-----> Upgrading to revision 2512398 from branch master
-----> Detecting release versions on production hosts
-----> Deploying upgrades to 1 online hosts
-----> Checking whether installed version 0.0.2 is in release store
-----> Building the upgrade from version 0.0.2
-----> Authorizing hosts
-----> Validating * version 0.0.2 is in local release store
-----> Ensuring hosts are ready to accept git pushes
-----> Pushing new commits with git to: @
-----> Resetting remote hosts to 2512398838c2dcc43de3ccd869779dded4fd5b6b
-----> Cleaning generated files from last build
-----> Checking out 2512398838c2dcc43de3ccd869779dded4fd5b6b
-----> Fetching / Updating dependencies
-----> Compiling sources
-----> Checking version of new release
-----> Uploading archive of release 0.0.2 from local release store
-----> Extracting archive myproject_0.0.2.tar.gz
-----> Removing old releases which were included in upgrade package
-----> Generating release
-----> Removing built release 0.0.2 from remote release directory
-----> Copying release 0.0.3 to local release store
-----> Copying myproject.tar.gz to release store
-----> Upgrading production hosts to version 0.0.3
-----> Authorizing hosts
-----> Uploading archive of release 0.0.3 from local release store
-----> Upgrading release to 0.0.3

UPGRADE DONE!

アップグレードは正常に完了しましたが、アプリケーションを再起動するまでデータベース関連のedeliverタスクを実行できません。

mix edeliver restart production

次の出力が表示されます。

OutputEDELIVER  WITH RESTART COMMAND

-----> restarting production servers

production node:

 user    :
 host    :
 path    : /home//app_release
 response: ok

RESTART DONE!

edeliverは、運用サーバーを正常に再起動したことを示しています。

アプリケーションがアップグレードされたことを確認するには、次のedeliverコマンドを実行して、現在運用環境で実行されているアプリケーションのバージョンを取得します。

mix edeliver version production
OutputEDELIVER MYPROJECT WITH VERSION COMMAND

-----> getting release versions from production servers

production node:

 user    :
 host    :
 path    : /home//app_release
 response:

VERSION DONE!

出力は、実稼働サーバーがアプリケーションバージョン `++`を実行していることを示しています。

`+ https:// +`でアプリケーションにアクセスして、実行されていることを確認することもできます。 アプリケーションのコード自体には手を加えていないため、アプリケーションに目に見える変更はありません。

アップグレードは成功したが、アプリケーションの更新に失敗した場合は、コードをコミットし、アプリケーションのバージョンを上げたことを確認してください。 アップグレードコマンドが失敗した場合、edeliverは、エラーが発生したときにサーバーで実行していたbashコードとエラーメッセージ自体を出力します。 これらの手がかりを使用して問題を解決できます。

データベースサポートをアプリに追加し、運用環境に展開したので、MySQLを使用する機能を追加する準備が整いました。

ステップ6-アドレス帳の作成

データベースの変更を展開する方法を示すために、アプリケーションに簡単なアドレス帳を作成し、運用環境に展開してみましょう。

アドレス帳のコードを最初から記述する代わりに、https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Html.html [Phoenix generators]を使用してアドレス帳を作成します。 Phoenixジェネレーターは、単純なCRUD(作成、読み取り、更新、削除)機能のコードを生成するユーティリティです。 これは、構築する可能性のある多くのアプリケーション機能の適切な出発点となります。

アドレス帳には、エントリを保存するためのデータベース内のテーブルも必要です。 このテーブルをデータベースに追加するには、SQLクエリを作成して実行できますが、代わりにEctoの移行機能を使用してデータベースを変更します。 このアプローチにはいくつかの利点があります。 まず、データベースに依存しません。 PostgreSQL、MySQL、またはその他のデータベースを使用している場合でも、コマンドは同じです。 次に、移行ファイルは、データベーススキーマが時間とともにどのように変化したかを追跡する便利な方法を提供します。 最後に、必要に応じて、開発マシンで最新の移行をロールバックすることもできます。

ありがたいことに、Phoenixジェネレーターは、特に指定がない限り、移行ファイルを作成するため、移行ファイルを最初から作成する必要はありません。

ジェネレーターを使用するには、コンテキスト、エンティティの単数名、エンティティの複数名、および他のすべてのフィールドをそれぞれのタイプで指定します。

  • context *は、関連リソースの機能を含むモジュールです。 たとえば、サイトにサインアップしたユーザーのリストとユーザーのサインイン時にセッションのログを保持することを計画している場合、ユーザーとセッションを「アカウント」という名前の単一のコンテキストモジュールの下に置くことは理にかなっています。

慣例により、Phoenixはエンティティの複数名がそのリソースのデータベーステーブルの名前であると想定していることに注意してください。

ジェネレータでアドレス帳を作成しましょう。 アドレス帳をシンプルにするために、各レコードに名前、メール、郵便番号の3つのフィールドのみを含めます。 各エントリを「+ Address 」、複数のエントリを「 addresses 」、アドレス帳が存在するコンテキストを「 AddressBook +」と呼びます。

次のコマンドを実行して、アドレス帳を生成します。

mix phx.gen.html
Output* creating lib/myproject_web/controllers/.ex
...
* creating priv/repo/migrations/_create_address.exs

Add the resource to your browser scope in web/router.ex:

   resources "/",

Remember to update your repository by running migrations:

   $ mix ecto.migrate

Phoenixは、テンプレートファイル、テストファイル、モデル、コントローラー、移行ファイルを自動的に生成したことを教えてくれます。 また、ルーターファイルにリソースを追加し、リポジトリを更新するよう指示します。

出力に表示される指示に従うこともできますが、そうすることで、アプリケーションコードのアップグレードとデータベースの移行を単一のリリースにバンドルします。 これにより、アプリケーションが運用サーバーに展開されてから運用データベースが移行されるまで、アプリケーションの特定の部分が運用で失敗する可能性があります。 この間隔の間、アプリケーションコードは、データベース内に存在しないテーブルまたは列を参照している可能性があります。

ダウンタイムとエラーを防ぐには、次の2つの手順で変更を展開します。

  1. アプリケーションコードを変更せずに、データベースに必要な変更を加えたデータベース移行ファイルを追加します。 リリースを作成し、運用サーバーをアップグレードして、運用データベースを移行します。

  2. アプリケーションコードを変更してから、別のリリースを作成してデプロイします。

この方法を使用しない場合、アドレス帳のコードはまだ作成していないアドレステーブルを参照しようとし、アプリケーションがクラッシュします。

本番データベースを移行する前に、移行ファイルを見てみましょう。 ファイル名は作成日時に基づいて異なる日付スタンプを持ちますが、「+ priv / repo / migrations / _create_addresses.exs +」にあります。 エディターでファイルを開きます。

nano priv/repo/migrations/*_create_addresses.exs

Phoenixによって生成された移行ファイルは、「+ change +」と呼ばれる単一の機能を持つElixirモジュールです。 後で移行を実行すると、この関数が呼び出されます。

〜/ myproject / priv / repo / migrations / 20180501040548_create_addresses.exs

defmodule Myproject.Repo.Migrations.CreateAddresses do
 use Ecto.Migration

 def change do
   create table(:addresses) do
     add :name, :string
     add :email, :string
     add :zip_code, :integer

     timestamps()
   end

 end
end

この関数では、Phoenixジェネレーターが、指定したフィールドとともに `+ addresses `テーブルを作成するコードを記述しました。 さらに、ジェネレーターには、「 inserted_at 」と「 updated_at 」の2つのフィールドを追加する「 timestamps()+」関数も含まれています。 これらのフィールドに保存されている値は、データを挿入または更新すると自動的に更新されます。

変更を加えずにファイルを閉じます。必要なのは生成されたコードだけです。

アプリケーションコードを含めずに移行ファイルのみをデプロイするには、edeliverがGitを使用してプロジェクトをビルドサーバーに転送するという事実を利用します。 具体的には、生成された残りのファイルを追跡せずに、移行ファイルをステージングしてコミットします。

しかし、それを行う前に、 `+ mix.exs +`でアプリケーションのバージョンを増やしてください。 Edeliverは、ホットアップグレードの準備にバージョン番号を使用するため、更新ごとにバージョン番号を増やす必要があります。

`+ mix.exs +`を開きます。

nano mix.exs

アプリケーションのバージョンを適切な値に増やします。

〜/ myproject / mix.exs

 def project do
   [
     app: :myproject,
     version: "",
     ...

ファイルを保存して閉じます。

次に、Gitを使用して、 `+ mix.exs +`ファイルと移行ファイルの両方をステージングします。

git add mix.exs priv/repo/migrations/*_create_addresses.exs

次に、ステージングされたファイルをコミットします。

git commit -m "Adding addresses table to the database"

それで、edeliverを使用して運用アプリケーションをアップグレードします。

mix edeliver upgrade production

アップグレードが完了したら、次のedeliverコマンドを実行して、運用データベースを移行します。

mix edeliver migrate production

出力には、移行が正常に実行されたことが示され、移行ファイルのタイムスタンプが示されます。

OutputEDELIVER  WITH MIGRATE COMMAND

-----> migrateing production servers

production node:

 user    :
 host    :
 path    : /home//app_release
 response: []

MIGRATE DONE!

本番データベースには、 `+ addresses +`という名前の空のテーブルがあります。

移行が実行されなかった場合、「+ response 」フィールドには「 [] 」と表示されます。 この場合、再度アップグレードする前に、Gitを使用してコードをコミットしたことを確認してください。 問題が解決しない場合は、「 mix edeliver restart production +」と入力して本番アプリケーションを再起動し、データベース移行タスクを再度実行します。

`+ addresses +`テーブルを用意したら、アドレス帳を生成して新しいリリースを作成するときにPhoenixが発行した指示に従うことができます。

まず、ファイル `+ lib / myproject_web / router.ex +`ファイルを開きます:

nano lib/myproject_web/router.ex

次のコードブロックを見つけます。

〜/ myproject / lib / myproject_web / router.ex

 scope "/",  do
   pipe_through :browser

   get "/", PageController, :index
 end

`+ addresses +`リソースのルートを挿入します:

〜/ myproject / lib / myproject_web / router.ex

 scope "/",  do
   pipe_through :browser

   get "/", PageController, :index

 end

`+ router.ex +`を保存して閉じます。

次に、Ectoにローカルデータベースを変更するよう依頼します。

mix ecto.migrate

出力は、移行ファイル内の関数が呼び出され、テーブル `+ addresses +`が正常に作成されたことを示しています。

Output...
[info] == Running .Repo.Migrations.CreateAddresses.change/0 forward
[info] create table addresses
[info] == Migrated in 0.0s

次に、ローカル開発サーバーを起動して、新しい機能をテストします。

mix phx.server

ブラウザでhttp:// localhost:4000 / addressesにアクセスして、動作中の新しい機能を確認します。

物事がローカルで動作していることに満足したら、ターミナルに戻り、 `+ CTRL + C +`を2回押してサーバーを終了します。

作業が完了したので、変更を本番にデプロイできます。 アプリケーションのバージョンを更新するには、「+ mix.exs +」を開きます。

nano mix.exs

バージョンフィールドを適切な値に増やします。

〜/ myproject / mix.exs

 def project do
   [
     app: :myproject,
     version: "",
     elixir: "~> 1.4",
     elixirc_paths: elixirc_paths(Mix.env),
     compilers: [:phoenix, :gettext] ++ Mix.compilers,
     start_permanent: Mix.env == :prod,
     deps: deps()
   ]
 end

`+ mix.exs +`を保存して閉じます。

Gitで変更をコミットします。 今回は、すべてのファイルをステージングします。

git add .
git commit -m "Added application code for address book"

edeliverを使用して実稼働アプリケーションをアップグレードします。

mix edeliver upgrade production

更新が完了すると、「+ https:/// addresses +」で新しい機能にアクセスできます。

これで、本番アプリケーションとデータベースが正常にアップグレードされました。

結論

この記事では、MySQLデータベースを使用するようにPhoenixアプリケーションを構成し、edeliverとEctoの移行を使用して本番データベースに変更を加えました。 この方法を使用すると、本番データベースに触れる必要がなく、本番データベースに加えたい変更はすべてEcto移行ファイルを介して行われます。 これにより、時間の経過に伴うデータベースへの変更のロールバックと変更の追跡が容易になります。

Ectoの移行および複雑なデータベース操作の実行方法の詳細については、https://hexdocs.pm/ecto/Ecto.Migration.html [Ectoの公式移行ドキュメント]を参照してください。

Related