0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Symfonyアプリケーションをrailwayにデプロイしたら詰まった話

Last updated at Posted at 2025-09-29

みなさん、お疲れ様です
AIForwardの末永です。

今日はSymfonyアプリケーションをデプロイする時に遭遇した、ちょっと厄介なエラーについて共有したいと思います。Railway環境にデプロイしようとしたら、キャッシュウォームアップでデータベース接続エラーが出ちゃって...結構ハマったんですよ。でも、インメモリSQLiteを使った解決策を見つけたので、同じ問題で困ってる人の助けになればと思って記事にしました

はじめに

最近管理するサーバーが増えてサーバー費とかパスワードとかの管理がめんどくさくなってきたので、諸々railwayに移行してたんですが、今回Symfonyアプリケーションをコンテナ環境(Railway、Docker等)にデプロイする際に、cache:warmupコマンドでデータベース接続エラーが発生しちゃいました。

特にDoctrine ORMを使ってる場合、この問題によく遭遇するんですよね。

環境情報

まず、僕が使ってた環境はこんな感じです:

  • Symfony: 6.4.*
  • PHP: 8.3
  • Doctrine ORM: 3.5.2
  • デプロイ環境: Railway (Nixpacks v1.38.0)
  • 本番DB: MySQL

問題の発生

エラー内容

デプロイ時にこんなエラーが出ました:

RUN cd backend && APP_ENV=prod APP_DEBUG=0 php bin/console cache:warmup --env=prod
.internal failed: Name or service not known
ERROR: failed to build: failed to solve: process did not complete successfully: exit code: 255

設定(問題が発生した状態)

# nixpacks.toml
[phases.build]
cmds = [
    "cd backend && touch .env",
    "cd backend && APP_ENV=prod APP_DEBUG=0 php bin/console cache:warmup --env=prod"
]

この設定でビルド時にキャッシュウォームアップを実行しようとしたら、データベース接続エラーが発生しちゃったんです。

問題の原因分析

Symfonyのキャッシュウォームアップって何してるの?

そもそもcache:warmupコマンドって何してるのか。このコマンドは本番環境でのパフォーマンス向上のために、以下の処理をしてくれるんですね:

  1. サービスコンテナのコンパイル
  2. ルーティングキャッシュの生成
  3. テンプレートキャッシュの作成
  4. Doctrineメタデータキャッシュの生成 ← ここでDB接続が必要!
  5. プロキシクラスの作成

4番目でDB接続が必要になるわけです。

なぜDoctrine ORMでDB接続が必要になるのか

Doctrineって、エンティティクラスの構造を検証したり、データベーススキーマとの整合性をチェックしたりするんですよ。例えばこんな感じのエンティティがあったとして:

class User
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private int $id;

    #[ORM\Column(type: 'string', length: 255)]
    private string $email;
    
    // Doctrineはこれらの定義を検証するためにDB接続を試行
}

Doctrineはこれらの定義が正しいかチェックするために、実際にデータベースに接続しようとするんです。

デプロイ環境での問題

ビルド時って:

  • まだデータベースサービスが利用不可
  • 環境変数のDATABASE_URLは設定されてるけど、実際の接続先が存在しない
  • mysql.railway.internal:3306への接続試行 → 失敗!

つまり、「データベースがまだ立ち上がってないのに接続しようとしてエラーになる」っていう状況です。

解決策:インメモリSQLiteの活用

ここで、ビルド時のキャッシュ生成では実際のデータは不要で、Doctrineがエンティティ構造を理解できれば十分なので、インメモリSQLiteを一時的なデータベースとして使うことにしました

実装

解決策はシンプルで

# nixpacks.toml
[phases.build]
cmds = [
    "cd backend && touch .env",
    "cd backend && DATABASE_URL=sqlite:///:memory: APP_ENV=prod APP_DEBUG=0 php bin/console cache:warmup --env=prod"
]

[start]
cmd = "cd backend && echo 'Starting PHP server on port '$PORT && php -S 0.0.0.0:$PORT -t public"

DATABASE_URL=sqlite:///:memory:を追加するだけで、インメモリSQLiteが使われます。

インメモリSQLiteの役割

ビルド時はインメモリSQLiteを使ってキャッシュを生成し、実行時は本物のMySQLを使うという仕組みになってます

他のアプローチとの比較

アプローチ1: ビルド時キャッシュ生成をスキップ

最初はこれも考えたのですが、問題点が:

  • 起動時間が長くなる(初回リクエスト時にキャッシュ生成)
  • スケーリング時に各コンテナで個別にキャッシュ生成が必要

これじゃあパフォーマンス的に良くないですよね。

アプローチ2: Doctrine機能を無効化

これも考えましたが:

  • Doctrineの機能が制限される
  • 本番環境でのパフォーマンスが低下

本末転倒です(笑)

アプローチ3: インメモリSQLite(推奨)

やっぱりこれが一番!

  • ビルド時にフルキャッシュ生成
  • 外部依存なし
  • 本番環境の機能はそのまま
  • 高速起動

トラブルシューティング

よくあるエラーと対処法

僕も遭遇したエラーをいくつか紹介しますね。

エラー1: SQLite拡張が無効

ERROR: PHP extension sqlite3 is required

これは簡単に解決できます:

RUN apt-get install -y sqlite3 php-sqlite3

エラー2: メモリ不足

キャッシュ生成でメモリが足りなくなることもあります。その場合は:

[phases.build]
cmds = [
    "cd backend && php -d memory_limit=512M bin/console cache:warmup --env=prod"
]

他のフレームワークとの比較

ちなみに、LaravelやDjangoではこの問題は起きないんですよ。

Laravelの場合:

php artisan config:cache
php artisan route:cache

DB接続不要です。

Symfonyだけこの問題が発生する理由は、Doctrine ORMとキャッシュシステムが密結合してるからなんですね。でも、その分高機能なので、トレードオフですね。

まとめ

SymfonyアプリケーションのDeployment時のDB接続エラー、インメモリSQLiteを使えば簡単に解決できます!

重要なのは、この一行:

DATABASE_URL=sqlite:///:memory: APP_ENV=prod php bin/console cache:warmup --env=prod

これでSymfonyの高機能とコンテナ環境の制約を両立できちゃいます。

同じ問題で困ってる方の参考になれば嬉しいです!質問があればコメント欄でお気軽にどうぞ。

それではまた次の記事でお会いしましょう!

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?