Ubuntu16.04でMySQLを使用してElixir-Phoenixアプリケーションをデプロイする方法
著者はCode.orgを選択して、 Write forDOnationsプログラムの一環として300ドルの寄付を受け取りました。
序章
チュートリアル蒸留所とedeliverを使用してElixirPhoenixのデプロイを自動化する方法では、データベースなしでPhoenixアプリケーションを作成し、edeliverを使用して本番サーバーにデプロイしました。 ほとんどの実際のアプリケーションでは、データベースを必要とし、展開プロセスにいくつかの変更を加える必要があります。
edeliverを使用して、アプリケーションとデータベースの変更を本番サーバーに同時にプッシュできるため、デプロイメント中にデータベースの変更を管理できます。
このガイドでは、Phoenix-EctoおよびMariaexを使用してMySQLデータベースに接続するように既存のPhoenixアプリケーションを構成します。 Ectoは、Phoenixアプリケーションで広く使用されているデータベースラッパーです。 Mariaexは、Ectoと統合し、MySQLおよびMariaDBデータベースと通信するデータベースドライバーです。
また、データベースを利用する簡単なアドレスブックを開発マシン上に作成し、edeliverを使用して変更を本番サーバーにデプロイします。 サイトのユーザーは、このアドレスブックのエントリを作成、読み取り、更新、および削除できます。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- チュートリアル蒸留所とedeliverを使用してElixirPhoenixの展開を自動化する方法から完成したPhoenixアプリケーション。 このアプリは、Let's Encrypt証明書を使用してNginxの背後で実行され、edeliverでデプロイされる必要があります。
- Ubuntu 16.04にMySQLをインストールする方法に従って、サーバーにMySQLをインストールします。
- デプロイする前にデータベースをテストするために、ローカル開発マシンにMySQLがインストールされています。
ステップ1—アプリケーションにMariaexとEctoを追加する
通常、Phoenixアプリケーションは、データベースへの接続を直接確立したり、SQLクエリを実行したりすることはありません。 代わりに、データベースドライバーを使用して目的のデータベースに接続し、データベースラッパーを使用してデータベースにクエリを実行します。
データベースドライバーは、接続の確立、接続の終了、クエリの実行など、データベースを使用する日常的なタスクを処理するElixirアプリケーションです。 データベースラッパーは、データベースドライバーの上にあるレイヤーであり、ElixirプログラマーがElixirコードを使用してデータベースクエリを作成できるようにし、クエリ構成(クエリの連鎖)などの追加機能を提供します。
この分離により、モジュラーアプリケーションが実現します。 データベースラッパー、つまりデータベースと対話するためのアプリケーションコードは、使用するデータベースに関係なくほぼ同じです。 データベースドライバを変更するだけで、Phoenixアプリケーションは別のデータベースソフトウェアを使用できます。
前のチュートリアルでアプリケーションを作成するときに--no-ecto
フラグを指定したため、アプリケーションにはEctoもMariaexもインストールされていません。 ここで、プロジェクトの依存関係としてEctoとMariaexを追加します。
注:PhoenixアプリケーションはデフォルトでPostgreSQLを使用します。 MySQLデータベースを使用して新しいアプリケーションを生成するには、コマンドmix phx.new --database mysql myproject
を使用します。
まず、Phoenixプロジェクトを含むディレクトリに切り替えます。
cd ~/myproject
次に、アプリケーションの依存関係のリストが含まれている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"}, {:phoenix_ecto, "~> 3.2"}, {:mariaex, "~> 0.8.2"} ] end
警告:潜在的な構成の問題を回避するために、新しいphoenix_ecto
エントリの前の行の最後にコンマ(、)が追加されていることを再確認してください。
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モジュールの形式で実装されます。 データベースと対話し、モジュールが提供する機能を使用する必要があるときはいつでも、このモジュールをインポートできます。 ラップされたデータベースは、リポジトリと呼ばれます。
このリポジトリモジュールには、Ectoで定義されたクエリ関数にアクセスできるようにするために、Ecto.Repo
マクロが含まれている必要があります。 さらに、init
という名前の関数でデータベースアダプタに渡されるオプションを初期化するためのコードが含まれている必要があります。
フェニックスプロジェクトの作成時に--no-ecto
フラグを使用していなかった場合、フェニックスはこのモジュールを自動的に生成します。 しかし、あなたがやったので、あなたはそれを自分で作成しなければならないでしょう。
lib/myproject
ディレクトリのrepo.ex
という名前のファイルにモジュールを作成しましょう。 最初にファイルを作成します。
nano lib/myproject/repo.ex
次のコードをファイルに追加して、リポジトリを定義します。
〜/ myproject / lib / myproject / repo.ex
defmodule Myproject.Repo do use Ecto.Repo, otp_app: :myproject @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プロジェクトはinit
関数を定義し、環境変数DATABASE_URL
が存在する場合、Ectoは環境変数の構成を使用して、データベースの資格情報を使用する代わりにデータベースに接続します。フェニックス構成ファイル(このチュートリアルで後で行うように)。
repo.ex
を保存して閉じます。
フェニックスプロジェクトは、並行性とフォールトトレランスのために軽量のElixirプロセスを使用しています。 スーパーバイザーは、これらのプロセスを管理し、クラッシュした場合に再起動します。 スーパーバイザーは他のスーパーバイザーを監視することもでき、この構造は監視ツリーと呼ばれます。
追加したMyproject.Repo
モジュールは、データベースに接続するプロセスを管理するスーパーバイザーを実装します。 このスーパーバイザーを開始するには、このスーパーバイザーをプロジェクトの監視ツリーに追加する必要があります。
lib/myproject
フォルダにあるapplication.ex
ファイルを開きます。
nano lib/myproject/application.ex
監視ツリーを定義する次のコードブロックを見つけます。
〜/ myproject / lib / myproject / application.ex
... children = [ # Start the endpoint when the application starts supervisor(MyprojectWeb.Endpoint, []), ... ] ...
アプリケーションエンドポイントMyprojectWeb.Endpoint
がスーパーバイザーとして開始されていることがわかります。 このリストにMyproject.Repo
を追加します。
〜/ myproject / lib / myproject / myproject.ex
children = [ # Start the Ecto repository supervisor(Myproject.Repo, []), # 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 :myproject, ecto_repos: [Myproject.Repo] ...
変更を保存してファイルを閉じます。
Ectoを構成したので、データベース資格情報をアプリケーションに追加することに進みます。
ステップ3—MySQLクレデンシャルを使用してアプリケーションを構成する
アプリケーションがデータベースに接続する状況は、開発中、テスト中、本番中の3つです。
これに対応して、Phoenixは、アプリケーションが実行されている環境に関連する資格情報を含む3つの環境固有の構成ファイルを提供します。 これらのファイルは、プロジェクトのルートのconfig
ディレクトリにあります。 このステップでは、これら3つのファイルを変更します。
まず、開発環境を設定しましょう。 dev.exs
を開きます。
nano config/dev.exs
MySQLを使用しているため、次の行を追加して、データベースアダプタをEcto.Adapters.MySQL
に設定します。
〜/ myproject / config / dev.exs
config :myproject, Myproject.Repo, adapter: Ecto.Adapters.MySQL
次に、同じコードブロックでデータベースの目的の名前を指定します。
〜/ myproject / config / dev.exs
config :myproject, Myproject.Repo, adapter: Ecto.Adapters.MySQL, database: "myproject_dev"
ここでは、開発データベース名をmyproject_dev
と定義します。 これは、Phoenixアプリがデータベースに使用する命名規則です。 この規則に従って、本番データベースはmyproject_prod
と呼ばれ、テストデータベースはmyproject_test
と呼ばれます。 代わりに、独自の命名スキームを使用できます。
次に、開発データベースサーバーのホスト名、ユーザー名、およびパスワードを指定します。
〜/ myproject / config / dev.exs
config :myproject, Myproject.Repo, adapter: Ecto.Adapters.MySQL, database: "myproject_dev", username: "root", password: "password", hostname: "localhost"
最後に、プールサイズを適切な数に設定します。 プールサイズは、アプリケーションが持つことができるデータベースへの接続の最大数です。 これらの接続は、リクエスト間で共有されます。 最適なサイズはハードウェアによって異なりますが、10
を使用して開始できます。
〜/ myproject / config / dev.exs
config :myproject, Myproject.Repo, adapter: Ecto.Adapters.MySQL, username: "root", password: "password", database: "myproject_dev", hostname: "localhost", pool_size: 10
dev.exs
を保存して閉じます。
次に、テスト環境を構成します。 テスト環境構成ファイルtest.exs
を開きます。
nano config/test.exs
このチュートリアルでは、開発データベースと一緒にローカルデータベースサーバーでテストデータベースをホストします。 そのため、テストデータベースの構成はほとんど同じです。
ただし、プールサイズの代わりに、プール値にEcto.Adapters.SQL.Sandbox
を指定します。 これにより、サンドボックスモードでテストが実行されます。 つまり、テスト中にテストデータベースで行われたトランザクションはすべてロールバックされます。 これは、各テスト後にデータベースが初期状態にリセットされるため、単体テストをランダムな順序で実行できることを意味します。
また、データベース名としてmyproject_test
を使用します。
次の構成をtest.exs
ファイルに追加します。
〜/ myproject / config / test.exs
config :myproject, Myproject.Repo, adapter: Ecto.Adapters.MySQL, username: "root", password: "password", database: "myproject_test", hostname: "localhost", 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 :myproject, Myproject.Repo, adapter: Ecto.Adapters.MySQL, username: "myapp", password: "password", database: "myproject_prod", hostname: "localhost", pool_size: 10
変更を保存してファイルを閉じます。
このファイルはセキュリティ上の理由からGitによって追跡されないため、手動でサーバーに転送する必要があります。 このプロセスの詳細については、Phoenixアプリケーションの展開に関する前提条件チュートリアルのステップ3を参照してください。
scp ~/myproject/config/prod.secret.exs sammy@your_server_ip:/home/sammy/app_config/prod.secret.exs
次に、ecto.create
Mixタスクを呼び出して、開発データベースを作成します。 テストを実行するときにPhoenixが作成するため、テストデータベースを作成する必要がないことに注意してください。
mix ecto.create
Ectoがデータベースを正常に作成したことを示す次の出力が表示されます。
Output... The database for Myproject.Repo has been created
この出力が表示されない場合は、構成の詳細が正しく、MySQLが実行されていることを確認してください。 エラーが原因でアプリケーションのコンパイルに失敗した場合も、Ectoはデータベースの作成を拒否します。
データベースに接続するようにプロジェクトを設定し、Ectoを使用して開発マシンにデータベースを作成したので、サーバー上のデータベースの変更に進むことができます。
ステップ4—本番データベースのセットアップ
ecto.create
Mixタスクを使用して、開発マシン上に空のデータベースを作成しました。 ここで、本番サーバーでも同じことを行います。 残念ながら、これを実現するのに役立つMixタスクやedeliverコマンドはありません。そのため、サーバーに手動でログインし、MySQLコンソールを使用してSQLコマンドで空のデータベースを作成します。
SSH経由でサーバーに接続します。
ssh sammy@your_server_ip
次に、rootユーザーと構成したパスワードを使用してMySQLコンソールにアクセスします。
mysql -u root -p
ログインしたら、本番データベースを作成します。
CREATE DATABASE myproject_prod;
次の出力が表示され、データベースが作成されたことがわかります。
OutputQuery OK, 1 row affected (0.00 sec)
次に、ユーザー名 myproject と前の手順で指定したパスワードを使用して、アプリのユーザーを作成します。
CREATE USER 'myproject'@'localhost' IDENTIFIED BY 'password';
次に、myprojectユーザーに作成したデータベースへのアクセスを許可します。
GRANT ALL PRIVILEGES ON myproject_prod.* to 'myproject'@'localhost';
最後に、権限の変更を適用します。
FLUSH PRIVILEGES;
exit
と入力して、MySQLコンソールを終了します。 もう一度exit
と入力して、SSH接続を終了します。
今後は、ローカルマシンからのテーブルの作成や変更など、ほとんどすべての操作を実行するため、本番データベースにアクセスする必要はほとんどありません。
本番データベースの準備ができたら、アプリケーションをサーバーに再デプロイできます。
ステップ5—プロジェクトをサーバーにデプロイする
このステップでは、データベースに接続していない実行中のアプリケーションを、新しく構成したアプリケーションとその新しいEctoリポジトリに置き換えます。 この手順により、アプリケーションが正しく構成され、期待どおりに実行されることを確認できます。
mix.exs
を開き、アプリケーションのバージョンを増やします。 バージョン番号を使用すると、リリースを追跡し、必要に応じて以前のバージョンにロールバックすることが容易になります。 また、ダウンタイムなしでアプリケーションをアップグレードするためにedeliverによって使用されます。
nano mix.exs
バージョンフィールドを適切な値にインクリメントします。
〜/ myproject / mix.exs
def project do [ app: :myproject, version: "0.0.3", 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: {Myproject.Application, []}, extra_applications: [:logger, :runtime_tools] ] end
edeliver
をextra_applications
リストの最後に追加します。
〜/ myproject / mix.exs
def application do [ mod: {Myproject.Application, []}, extra_applications: [:logger, :runtime_tools, :edeliver] ] end
mix.exs
を保存して閉じます。
アプリケーションを起動して、すべてが機能し、コンパイルエラーがないことを確認します。
mix phx.server
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: [email protected] -----> 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 MYPROJECT WITH RESTART COMMAND -----> restarting production servers production node: user : sammy host : example.com path : /home/sammy/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 : sammy host : example.com path : /home/sammy/app_release response: 0.0.3 VERSION DONE!
出力は、本番サーバーがアプリケーションバージョン0.0.3
を実行していることを示しています。
https://example.com
でアプリケーションにアクセスして、アプリケーションが実行されていることを確認することもできます。 アプリケーションコード自体には触れていないため、アプリケーションに目に見える変更はないはずです。
アップグレードは成功したがアプリケーションの更新に失敗した場合は、コードをコミットし、アプリケーションのバージョンを上げたことを確認してください。 アップグレードコマンドが失敗した場合、edeliverは、エラーが発生したときにサーバーで実行していたbashコードとエラーメッセージ自体を出力します。 これらの手がかりを使用して、問題を解決できます。
アプリにデータベースサポートを追加し、本番環境にデプロイしたので、MySQLを利用するいくつかの機能を追加する準備が整いました。
ステップ6—アドレス帳を作成する
データベースの変更をデプロイする方法を示すために、アプリケーションに簡単なアドレスブックを作成して、本番環境にデプロイしてみましょう。
警告:この名簿は一般公開され、誰でもアクセスして編集できるようになります。 このチュートリアルの完了後に機能を停止するか、Guardianなどの認証システムを追加してアクセスを制限してください。
アドレス帳のコードを最初から作成する代わりに、フェニックスジェネレーターを使用してアドレス帳を作成します。 フェニックスジェネレーターは、単純なCRUD(作成、読み取り、更新、削除)機能のコードを生成するユーティリティです。 これは、構築する可能性のある多くのアプリケーション機能の開始点として適しています。
名簿には、エントリを保存するためのデータベース内のテーブルも必要です。 このテーブルをデータベースに追加するには、SQLクエリを作成して実行できますが、代わりにEctoの移行機能を使用してデータベースを変更します。 このアプローチにはいくつかの利点があります。 まず、データベースに依存しません。 コマンドは、PostgreSQL、MySQL、またはその他のデータベースを使用している場合でも同じです。 次に、移行ファイルは、データベーススキーマが時間の経過とともにどのように変化したかを追跡するための便利な方法を提供します。 最後に、必要に応じて、開発マシンで最新の移行をロールバックすることもできます。
ありがたいことに、特に指定がない限り、Phoenixジェネレーターが移行ファイルを作成するため、移行ファイルを最初から作成する必要はありません。
ジェネレーターを使用するには、コンテキスト、エンティティの単数形の名前、エンティティの複数形の名前、およびその他すべてのフィールドをそれぞれのタイプで指定します。
context は、関連するリソースの関数を含むモジュールです。 たとえば、サイトにサインアップしたユーザーのリストと、ユーザーがサインインしたときのセッションのログを維持することを計画している場合、ユーザーとセッションを「アカウント」という名前の単一のコンテキストモジュールの下に置くことは理にかなっています。
慣例により、Phoenixはエンティティの複数形をそのリソースのデータベーステーブルの名前と見なしていることに注意してください。
ジェネレーターで名簿を作成しましょう。 名簿を単純にするために、レコードごとに名前、電子メール、郵便番号の3つのフィールドのみを含めます。 各エントリをAddress
と呼び、複数のエントリをaddresses
と呼び、アドレス帳が存在するコンテキストをAddressBook
と呼びます。
次のコマンドを実行して、アドレス帳を生成します。
mix phx.gen.html AddressBook Address addresses name:string email:string zip_code:integer
Output* creating lib/myproject_web/controllers/address_controller.ex ... * creating priv/repo/migrations/20180318032834_create_address.exs Add the resource to your browser scope in web/router.ex: resources "/addresses", AddressController Remember to update your repository by running migrations: $ mix ecto.migrate
フェニックスは、テンプレートファイル、テストファイル、モデル、コントローラー、および移行ファイルを自動的に生成したと語っています。 また、ルーターファイルにリソースを追加してリポジトリを更新するように指示します。
出力に表示される指示に従うこともできますが、そうすることで、アプリケーションコードのアップグレードとデータベースの移行を単一のリリースにバンドルすることができます。 これにより、アプリケーションが本番サーバーにデプロイされてから本番データベースが移行されるまで、アプリケーションの特定の部分が本番環境で失敗する可能性があります。 この間、アプリケーションコードはデータベース内に存在しないテーブルまたは列を参照している可能性があります。
ダウンタイムとエラーを防ぐには、次の2つの手順で変更を展開します。
- アプリケーションコードを変更せずに、データベースに必要な変更を加えたデータベース移行ファイルを追加します。 リリースを作成し、本番サーバーをアップグレードして、本番データベースを移行します。
- アプリケーションコードに変更を加えてから、別のリリースを作成してデプロイします。
このアプローチを採用しない場合、アドレスブックのコードは、まだ作成していないアドレステーブルを参照しようとし、アプリケーションがクラッシュします。
本番データベースを移行する前に、移行ファイルを見てみましょう。 これはpriv/repo/migrations/20180501040548_create_addresses.exs
にありますが、ファイル名は作成した日時に基づいて異なる日付スタンプが付けられます。 エディターでファイルを開きます。
nano priv/repo/migrations/*_create_addresses.exs
フェニックスによって生成された移行ファイルは、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: "0.0.4", ...
ファイルを保存して閉じます。
次に、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 MYPROJECT WITH MIGRATE COMMAND -----> migrateing production servers production node: user : sammy host : example.com path : /home/sammy/app_release response: [20180501040548] 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 "/", MyprojectWeb do pipe_through :browser get "/", PageController, :index end
addresses
リソースのルートを挿入します。
〜/ myproject / lib / myproject_web / router.ex
scope "/", MyprojectWeb do pipe_through :browser get "/", PageController, :index resources "/addresses", AddressController end
router.ex
を保存して閉じます。
次に、Ectoにローカルデータベースに変更を加えるように依頼します。
mix ecto.migrate
出力は、移行ファイル内の関数が呼び出され、テーブルaddresses
が正常に作成されたことを示しています。
Output... [info] == Running Myproject.Repo.Migrations.CreateAddresses.change/0 forward [info] create table addresses [info] == Migrated in 0.0s
次に、ローカル開発サーバーを起動して、新しい機能をテストします。
mix phx.server
ブラウザでhttp:// localhost:4000 / jobs にアクセスして、新機能の動作を確認してください。
ローカルで動作していることを確認したら、端末に戻り、CTRL+C
を2回押してサーバーを終了します。
これで問題が解決したので、変更を本番環境にデプロイできます。 mix.exs
を開いて、アプリケーションのバージョンを更新します。
nano mix.exs
バージョンフィールドを適切な値にインクリメントします。
〜/ myproject / mix.exs
def project do [ app: :myproject, version: "0.0.5", 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://example.com/addresses
で新機能にアクセスできます。
これで、本番アプリケーションとデータベースのアップグレードに成功しました。
結論
この記事では、MySQLデータベースを使用するようにPhoenixアプリケーションを構成し、edeliverとEctoの移行を使用して本番データベースに変更を加えました。 この方法では、本番データベースに触れる必要はなく、本番データベースに加えたい変更は、Ecto移行ファイルを介して行われます。 これにより、変更をロールバックし、データベースへの変更を経時的に追跡することが容易になります。
Ecto移行の詳細と、複雑なデータベース操作の実行方法については、公式のEcto移行ドキュメントを参照してください。