Caution: You are browsing the legacy symfony 1.x part of this website.
Cover of the book Symfony 5: The Fast Track

Symfony 5: The Fast Track is the best book to learn modern Symfony development, from zero to production. +300 pages showcasing Symfony with Docker, APIs, queues & async tasks, Webpack, SPAs, etc.

23日目: デプロイ

1.2 / Propel

昨日のキャッシュシステムのコンフィギュレーションによって、JobeetのWebサイトは運用サーバーにデプロイされる準備ができています。

22日間、開発マシンでJobeetを開発してきました。 ほとんどの方がローカルマシンで作業したでしょう; 運用サーバーで直接開発するのは、もちろん非常にわるいアイディアです。 では、Webサイトを運用サーバーに移行しましょう。

今日は、運用環境に移行する前に必要なもの、とることができるデプロイ戦略の種類、継続的なデプロイに必要なツールも見ることにします。

運用サーバーを用意する

プロジェクトを運用サーバーにデプロイする前に、運用サーバーを正しく設定する必要があります。 1日目を読み返すと、Webサーバーの設定方法が説明されています。

このセクションでは、Webサーバー、データベースサーバーとPHP 5.2.4以降をインストールしたことを前提とします。

note

WebサーバーにSSHでアクセスできない場合、コマンドラインにアクセスする必要のあるセクションは読み飛ばしてください。

サーバーのコンフィギュレーション

最初に、PHPが必要なエクステンションと一緒にインストールされ正しく設定されていることを確認する必要があります。 1日目に関して、symfonyによって提供されるcheck_configuration.phpスクリプトを使います。 symfonyを運用サーバーにインストールしないので、symfony公式サイトからファイルを直接ダウンロードします:

http://trac.symfony-project.org/browser/branches/1.2/data/bin/check_configuration.php?format=raw

Webのルートディレクトリにファイルをコピーしてブラウザーコマンドラインから実行します:

$ php check_configuration.php

スクリプトが見つける致命的なエラーを修正し両方の環境ですべてがよい状態で動作するまで作業を繰り返します。

PHPアクセラレーター

運用サーバーに関して、可能な限りベストなパフォーマンスを得ることを望んでいらっしゃるでしょう。 PHPアクセラレーターをインストールすれば最高のお金の節約になります。

note

Wikipediaより: PHPアクセラレーターはリクエストごとのソースの解析とコンパイルのオーバーヘッドを回避するためにPHPスクリプトのコンパイルされたバイトコードをキャッシュすることで動作します。

APCは最も人気のあるアクセラレーターで、インストール作業がシンプルです:

$ pecl install APC

OSによっては、OSネイティブのパッケージマネージャーでインストールすることもできます。

note

APCの設定方法を学ぶための時間をとってください。

symfonyのライブラリ

symfonyを埋め込む

symfonyの強みの1つはプロジェクトが自己完結していることです。 プロジェクトを動作させるために必要なすべてのファイルはメインのrootディレクトリの元にあります。 symfonyは相対パスのみを使用するのでプロジェクトで何も変更せずにプロジェクトを別のディレクトリに移動できることを意味します。 運用サーバーのディレクトリは開発マシンと同じである必要はないことを意味します。

唯一の絶対パスはconfig/ProjectConfiguration.class.phpファイルで見つかります; しかし1日目を読み返して、symfonyコアのオートローダーへの相対パスが含まれていることを確認します:

// config/ProjectConfiguration.class.php
require_once dirname(__FILE__).'/../lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php';

symfonyをアップグレードする

すべての内容が単独のディレクトリに収まる場合、symfonyを新しいリリースにアップグレードする作業はものすごく簡単です。

バグとセキュリティ問題の修正は定期的に行われるので、ときどきsymfonyを最新のマイナーリリースにアップグレードすることを望むでしょう。 よい知らせはすべてのsymfonyのバージョンは少なくとも1年間は維持されメンテナンス期間の間、新しい機能は小さくても追加されません。 ですので、1つのマイナーリリースから別のマイナーリリースへのアップグレードは常に速く、安全でセキュアです。

symfonyのアップグレード作業はlib/vendor/symfony/ディレクトリの内容を変更するだけなのでシンプルです。 アーカイブでsymfonyをインストールする場合、現在のファイルを削除して最新のものに置き換えます。

プロジェクトでSubversionを使う場合、プロジェクトを最新のsymfony1.2のタグにリンクすることもできます:

$ svn propedit svn:externals lib/vendor/
  # symfony http://svn.symfony-project.com/tags/RELEASE_1_2_1/

symfonyのアップグレード作業はタグを最新バージョンに変更するだけなのでシンプルです。

リアルタイムで修正される1.2系のブランチも利用できます:

$ svn propedit svn:externals lib/vendor/
  # symfony http://svn.symfony-project.com/branches/1.2/

svn upを実行するたびに、最新のsymfony 1.2が手に入ります。

新しいバージョンにアップグレードするとき、とりわけ運用環境では、常にキャッシュをクリアすることをお勧めします:

$ php symfony cc

tip

運用サーバーのFTPアクセス権限もある場合、cache/ディレクトリの元にあるすべてのファイルとディレクトリを削除することでsymfony ccをシミュレートできます。

symfonyの既存のバージョンを置き換えずに新しいバージョンをテストすることもできます。 新しいリリースをテストしたいだけで、簡単にロールバックできるようにしたい場合、別のディレクトリ(たとえばlib/vendor/symfony_test)にsymfonyをインストールしProjectConfigurationクラスのパスを変更し、キャッシュをクリアします。 ロールバックはディレクトリを削除してProjectConfigurationのパスを元に戻すだけです。

コンフィギュレーションを調整する

データベースのコンフィギュレーション

ほとんどの場合、運用のデータベースはローカルと異なるクレデンシャルを持ちます。 symfonyの環境システムのおかげで、運用データベースの異なるコンフィギュレーションを用意するのはたやすいことです:

$ php symfony configure:database "mysql:host=localhost;dbname=prod_dbname" prod_user prod_pass

databases.yml設定ファイルを直接編集することもできます。

アセット

Jobeetはアセットを埋め込むプラグインを使うのでsymfonyはweb/ディレクトリに相対的なシンボリックリンクを作成しました。 plugin:installタスクなしでプラグインをインストールする場合plugin:publish-assetsタスクはこれらを再生成もしくは作成します:

$ php symfony plugin:publish-assets

エラーページをカスタマイズする

運用に移行する前に、404エラーページ、もしくはデフォルトの例外ページのようなsymfonyのデフォルトページをカスタマイズするのはよいことです。

16日目、config/error/ディレクトリでerror.yaml.phpexception.yaml.phpファイルを作ることでYAMLフォーマット用のエラーページを設定しました。 prod環境のときはerror.yaml.phpファイルが、dev環境ではexception.yaml.phpが使われます。

ですので、HTMLフォーマット用にデフォルトの例外ページをカスタマイズするには、2つのファイル: config/error/error.html.phpconfig/error/exception.html.phpを作ります。

404ページ(page not found)はerror_404_moduleerror_404_action設定を変更することでカスタマイズできます:

# apps/frontend/config/settings.yml
all:
  .actions:
    error_404_module: default
    error_404_action: error404

ディレクトリ構造をカスタマイズする

コードの構造化と標準化のために、symfonyにはあらかじめ定義される名前を持つデフォルトのディレクトリ構造があります。 しかしときには、何らかの外部の制約から構造を変更せざるをえないことがあります。

config/ProjectConfiguration.class.phpクラスでディレクトリの名前を設定できます。

Webサイトのルートディレクトリ

Webホスティングの状況によって、Webサイトのルートディレクトリの名前を変更できないことがあります。 名前がweb/ではなくpublic_html/である場合を考えてみましょう:

// config/ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    $this->setWebDir($this->getRootDir().'/public_html');
  }
}

setWebDir()メソッドはWeb公開のルートディレクトリの絶対パスを受け取ります。 このディレクトリもどこかに移動させる場合、ProjectConfigurationファイルへのパスがまだ有効であることを確認するためにコントローラースクリプトを編集することを忘れないでください:

require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');

キャッシュとログディレクトリ

symfonyフレームワークは2つのディレクトリ: cache/log/のみに書き込みます。 セキュリティの理由から、Webホスティング会社の中にはメインディレクトリに書き込みパーミッションを設定しないところがあります。 これに該当する場合、これらのディレクトリを他のファイルシステムに移動させることができます:

// config/ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    $this->setCacheDir('/tmp/symfony_cache');
    $this->setLogDir('/tmp/symfony_logs');
  }
}

setWebDir()メソッドに関して、setCacheDir()setLogDir()はそれぞれcache/log/ディレクトリへの絶対パスを受け取ります。

ファクトリ

Jobeetチュートリアルの間、sfUsersfRequestsfResponsesfI18NsfRoutingなどのコアオブジェクトの話をしました。 これらのオブジェクトはsymfonyフレームワークによって自動的に作成され、設定され管理されます。 これらはsfContextオブジェクトから常にアクセス可能で、フレームワークの多くのものと同じように、これらは設定ファイル: factories.ymlで設定できます。このファイルは環境によって設定できます。

sfContextがコアファクトリを初期化するとき、コンストラクターに渡すクラスの名前(class)とパラメーター(param)のためにfactories.ymlファイルを読み込まれます:

response:
  class: sfWebResponse
  param:
    send_http_headers: false

上記のスニペットにおいて、レスポンスファクトリを作るために、symfonyはsfWebResponseオブジェクトをインスタンス化してパラメーターとしてsend_http_headersオプションを渡します。

ファクトリをカスタマイズできることはsymfonyのコアオブジェクトに対してデフォルトの代わりにカスタムのクラスを利用できることを意味します。 これらのクラスに送るパラメーターを変更することでこれらのふるまいを変更することもできます。

おそらくお望みの古典的なカスタマイズ方法を見てみましょう。

Cookieの名前

ユーザーセッションを扱うために、symfonyはCookieを使います。 このCookieはデフォルトの名前としてsymfonyを持ちます。 これはfactories.ymlで変更できます。 allキーの下で、Cookieの名前をjobeetに変更するために次のコンフィギュレーションを追加します:

# apps/frontend/config/factories.yml
storage:
  class: sfSessionStorage
  param:
    session_name: jobeet

セッションストレージ

デフォルトのセッションストレージクラスはsfSessionStorageです。 このクラスはセッション情報を保存するためにファイルシステムを使います。 複数のWebサーバーがある場合、データベーステーブルのような中心位置で複数のセッションを保存するとよいでしょう:

# apps/frontend/config/factories.yml
storage:
  class: sfPDOSessionStorage
  param:
    session_name: jobeet
    db_table:     session
    database:     propel
    db_id_col:    id
    db_data_col:  data
    db_time_col:  time

セッションのタイムアウト

デフォルトでは、ユーザーセッションのタイムアウトは1800秒です。 これはuserエントリーを編集することで変更できます:

# apps/frontend/config/factories.yml
user:
  class: myUser
  param:
    timeout: 1800

ロギング

デフォルトでは、prod環境ではロギングは行われません。 ロガークラスの名前がsfNoLoggerだからです:

# apps/frontend/config/factories.yml
prod:
  logger:
    class:   sfNoLogger
    param:
      level:   err
      loggers: ~

たとえばロガークラスの名前をsfFileLoggerに変更することでファイルシステムでのロギングを有効にできます:

# apps/frontend/config/factories.yml
logger:
  class: sfFileLogger
  param:
    level: error
    file:  %SF_LOG_DIR%/%SF_APP%_%SF_ENVIRONMENT%.log

note

factories.yml設定ファイルにおいて、文字列の%XXX%sfConfigオブジェクトからの対応する値に置き換えられます。 ですので、設定ファイルの%SF_APP%はPHPコードのsfConfig::get('sf_app')と同等です。 この表記はapp.yml設定ファイルでも利用できます。 パス(SF_ROOT_DIRSF_WEB_DIR、・・・)を決め打ちせずに設定ファイルでパスを参照する必要があるときにとても便利です。

デプロイする

デプロイとは?

JobeetのWebサイトを運用サーバーにデプロイするとき、 不要なファイルをアップロードしないもしくは企業のロゴのように、ユーザーによってアップロードされたファイルを上書きしないように注意する必要があります。

symfonyプロジェクトにおいて、転送から除外されるディレクトリは3つ: cache/log/web/uploads/あります。 そのほかはすべてそのまま転送できます。

セキュリティ上の理由から、frontend_dev.phpbackend_dev.phpfrontend_cache.phpスクリプトのような"運用環境ではない"フロントコントローラーも転送したくないでしょう。

デプロイ戦略

このセクションでは、運用サーバーを完全にコントロールできることを前提とします。 サーバーへのアクセス権限がFTPアカウントの場合は、唯一可能なデプロイの解決策はデプロイするたびにすべてのファイルを転送することです。

Webサイトをデプロイするもっともシンプルな方法は組み込みのproject:deployタスクを使うことです。 これは接続して1つのコンピュータから別のコンピュータにファイルを転送するためにSSHrsyncを使います。

project:deployタスク用のサーバーはconfig/properties.ini設定ファイルで設定できます:

# config/properties.ini
[production]
  host=www.jobeet.org
  port=22
  user=jobeet
  dir=/var/www/jobeet/
  type=rsync
  pass=

新しく設定したproductionサーバーにデプロイするには、project:deployタスクを使います:

$ php symfony project:deploy production

note

初めてproject:deployタスクを実行する前に、キーを既知のホストファイルに追加するために手動でサーバーに接続する必要があります。

このコマンドを実行すると、symfonyは転送のシミュレーションのみを行います。 実際にWebサイトをデプロイするには、--goオプションを追加します:

$ php symfony project:deploy production --go

note

properties.iniファイルでSSHパスワードを提供できる場合でも、パスワードなしの接続ができるようにSSHキーでサーバーを設定するほうがベターです。

デフォルトでは、symfonyは以前のセクションで話したディレクトリを転送しませんし、devのフロントコントローラースクリプトも転送しません。 これはproject:deployタスクがconfig/rsync_exclude.txtファイルで設定されたファイルとディレクトリを除外するからです:

# config/rsync_exclude.txt
.svn
/web/uploads/*
/cache/*
/log/*
/web/*_dev.php

Jobeetに対して、frontend_cache.phpファイルを追加する必要があります:

# config/rsync_exclude.txt
.svn
/web/uploads/*
/cache/*
/log/*
/web/*_dev.php
/web/frontend_cache.php

tip

ファイルとディレクトリの転送を強制するためにconfig/rsync_include.txtファイルを作ることもできます。

project:deployタスクがとても柔軟であるとしても、さらにカスタマイズできます。 デプロイはサーバーとコンフィギュレーションとネットワークトポロジーによって大きく異なる可能性があるので、デフォルトのタスクを拡張することをためらわないでください。

Webサイトを運用サーバーにデプロイするたびに、少なくとも運用サーバーの設定キャッシュをクリアすることをお忘れなく:

$ php symfony cc --type=config

ルートを変更したら、ルーティングのキャッシュもクリアする必要があります:

$ php symfony cc --type=routing

note

キャッシュを選別してクリアすることで、テンプレートキャッシュのようなキャッシュの一部を維持できます。

また明日

プロジェクトのデプロイはsymfony開発のライフサイクルの一番最後のステップです。 これはすべてが終わったことを意味しません。全くの逆です。 Webサイトの人生の始まりです。 おそらくバグを修正しなければならず時間が経過したら新しい機能も追加したくなります。 しかしsymfonyの構造と自由に使えるツールのおかげで、Webサイトのアップグレード作業はシンプルで、速く、安全です。

明日はJobeetチュートリアルの最後の日です。 Jobeetの23日間に学んだことを振り返ります。