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?

CodePipeline・CodeBuildでLaravelのマイグレーションを自動化した話

0
Last updated at Posted at 2026-07-03

Laravelアプリケーションをリリースする際、データベースのマイグレーションは欠かせません。

以前は、アプリケーションをデプロイした後に踏み台サーバーへSSH接続し、手動でマイグレーションを実行していました。

作業自体は難しくありませんが、

  • 実行忘れ
  • 手順のばらつき
  • 誰が実行したか分かりづらい

といった課題がありました。

そこで、CodePipelineとCodeBuildを利用し、マイグレーションをリリースフローへ組み込みました。


導入前

以前は次のような流れでした。

踏み台サーバーへSSH

↓

php artisan migrate

↓

動作確認

この構成でも運用できますが、リリース手順が人に依存していました。


導入後

現在はCodePipeline上で実行しています。

GitHub

↓

CodeBuild
(migrate:status)

↓

Manual Approval

↓

CodeBuild
(migrate)

↓

CodeBuild
(migrate:status)

マイグレーション前に現在の状態を確認し、その内容を確認してから承認・実行する流れにしています。


migrate:statusを最初に実行

まずは現在の状態を取得します。

php artisan migrate:status

CodeBuildのログに、

  • 適用済みMigration
  • 未適用Migration

が表示されます。

これを確認してから承認することで、

「今回はどのMigrationが実行されるのか」

を事前に把握できます。


Manual Approval

migrate:statusの結果を確認後、

CodePipelineのManual Approvalステージで承認します。

migrate:status

↓

Manual Approval

↓

migrate

例えば、

  • 本番DBへ影響が大きい変更
  • カラム削除
  • インデックス追加

などの場合でも、一度内容を確認してから実行できます。

完全自動にはせず、人による最終確認を残しています。


マイグレーション実行

承認後に実行します。

php artisan migrate --force

CodeBuildでは対話モードが利用できないため、

--force

を付けています。


実行後も状態確認

実行後にも状態を確認しています。

php artisan migrate:status

これにより、

実際にMigrationが適用されたことをログから確認できます。


buildspec.yml

Migration用のCodeBuildでは次のような処理を実行しています。

version: 0.2

phases:
  build:
    commands:
      - php artisan migrate:status
      - php artisan migrate --force
      - php artisan migrate:status

マイグレーション前後の状態が残るため、後から監査しやすい構成です。


RDSはプライベートサブネット

RDSはインターネットへ公開せず、プライベートサブネットへ配置しています。

そのため、CodeBuildもVPCへ接続しています。

CodeBuild

↓

Private Subnet

↓

RDS

外部公開することなく、安全にマイグレーションを実行できます。


NAT Gateway

CodeBuildをVPCへ接続すると、

インターネットへ直接アクセスできなくなります。

Composerの取得やAWS APIへのアクセスが必要なため、

Private SubnetからはNAT Gateway経由で通信しています。

CodeBuild

↓

Private Subnet

↓

NAT Gateway

↓

Internet

Security Group

RDSでは、

CodeBuild用Security Groupのみ接続を許可しています。

RDS

↓

Inbound

↓

CodeBuild SG

CIDR指定ではなくSecurity Group同士で許可することで、

不要なアクセスを防いでいます。


Secrets Manager

データベース接続情報はSecrets Managerで管理しています。

CodeBuildでは環境変数として取得します。

env:
  secrets-manager:
    DB_PASSWORD: prod/database:password

認証情報をbuildspec.ymlへ記載する必要はありません。


CDKで構築

インフラはAWS CDKで管理しています。

例えばCodeBuildは次のように定義しています。

const project = new codebuild.Project(this, "MigrationProject", {
  vpc,
  subnetSelection: {
    subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
  },
  securityGroups: [migrationSecurityGroup],
  environment: {
    buildImage: codebuild.LinuxBuildImage.STANDARD_7_0,
  },
});

CodePipelineもCDKで定義しています。

pipeline.addStage({
  stageName: "MigrationStatus",
  actions: [migrationStatusAction],
});

pipeline.addStage({
  stageName: "Approval",
  actions: [
    new codepipeline_actions.ManualApprovalAction({
      actionName: "ApproveMigration",
    }),
  ],
});

pipeline.addStage({
  stageName: "Migration",
  actions: [migrationAction],
});

pipeline.addStage({
  stageName: "Deploy",
  actions: [deployAction],
});

インフラもコードとして管理できるため、

環境差分が発生しにくく、再現性の高い構成になっています。


導入して感じたこと

一番良かったのは、

マイグレーションの状態を確認してから実行できるようになったことです。

以前は踏み台サーバーへ接続し、

php artisan migrate

を実行するだけでした。

現在は、

  1. 現在のMigration状態を確認
  2. 人が承認
  3. Migration実行
  4. 実行後も状態確認
  5. アプリケーションをデプロイ

という流れになっています。

自動化しつつも、本番DBへの変更は人が最終確認するため、安心して運用できています。


まとめ

今回構築したパイプラインでは、

  • migrate:statusで実行予定を確認
  • Manual Approvalで最終判断
  • migrate --forceを実行
  • 実行後もmigrate:statusで確認
  • アプリケーションをデプロイ

という流れを採用しています。

インフラはCDKでコード化し、CodeBuildはVPC内からRDSへ接続する構成です。

手作業で踏み台サーバーへ接続していた頃と比べ、マイグレーションもCI/CDの一部として管理できるようになり、再現性の高いリリースフローを実現できました。

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?