はじめに
この記事では、開発環境で動いていた Laravel + React (Inertia.js) アプリを、EC2 上で Docker を使って本番運用できる構成にする手順を解説します。
対象読者は以下のような方です:
- 開発環境では Laravel Sail を使っている
- EC2 に本番環境を構築したい
- RDS + Nginx + Docker の構成で運用したい
- HTTPS(Let’s Encrypt)も有効化したい
1. EC2に接続する
EC2インスタンス作成後、EC2 インスタンスに SSH 接続します。
mkdir -p ~/.ssh
mv ~/Downloads/*****.pem ~/.ssh/
chmod 400 ~/.ssh/*****.pem
ssh -i ~/.ssh/Tripost.pem ec2-user@ec*******.ap-northeast-1.compute.amazonaws.com
2. Docker のインストールと設定(Amazon Linux 2023)
EC2 上で Docker を使って開発環境に近い構成をそのまま再現。
開発環境と差が少ないので「動いたのに本番で動かない」問題が減る。
Amazon Linux 2023 は dnf を使用します。
sudo dnf update -y
sudo dnf install -y docker
sudo systemctl enable --now docker
docker --version
非 root ユーザーで Docker を使えるようにする
sudo usermod -aG docker ec2-user
newgrp docker
これで sudo なしで docker ps が動きます。
3. Docker Compose をインストール
Amazon Linux 2023 ではパッケージが無いため、バイナリから直接入れます。
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
4. GitHub からプロジェクトをクローン
sudo dnf install -y git
cd /home/ec2-user
git clone https://github.com/your-username/your-repo.git <プロジェクト名>
cd <プロジェクト名>
sudo chown -R ec2-user:ec2-user .
5. RDS の設定と接続確認
RDS 未作成の場合は先に作成しておきましょう。
EC2 から接続テスト:
sudo dnf install -y mariadb105
mysql -h (RDSのエンドポイント) -u admin -p
👉 パスワード入力 → mysql> プロンプトが出たら成功。
接続後、DB作成:
CREATE DATABASE (DB名) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
もし RDS で作成済みの DB 名が既にあるなら、新規作成は不要です。
名前を変える場合は .env.production と RDS の DB 名を必ず一致させること。
文字セットは utf8mb4 + utf8mb4_unicode_ci にしておくと絵文字や特殊文字も対応できます。
6. 環境変数ファイル .env.production の作成
nano .env.production
APP_NAME=Tripost
APP_ENV=production
APP_KEY=base64:*****
APP_DEBUG=false
APP_URL=http://*****
APP_LOCALE=ja
APP_FALLBACK_LOCALE=ja
APP_FAKER_LOCALE=ja_JP
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
REDIS_CLIENT=phpredis
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379
DB_CONNECTION=mysql
DB_HOST=*****.rds.amazonaws.com
DB_PORT=3306
DB_DATABASE=*****-db
DB_USERNAME=admin
DB_PASSWORD=*****
# その他 APIキー / S3設定など
VITE_GOOGLE_MAPS_KEY=*****
.env.production は Git にコミットしないよう .gitignore に追記
echo ".env.production" >> .gitignore
chmod 600 .env.production
.env や設定ファイル: アプリ/デプロイプロセスがファイルを書き換える必要があるなら 600、読み取りだけなら 400 でも可。多くは 600 を使うのが無難。
7. Dockerfile と docker-compose.production.yml の準備
開発環境でLaravel Sailを使用している場合、本番環境では使用不可なのでNginx+PHP-FPMを構築する。
Dokerfile
FROM php:8.3-fpm
# 必要パッケージ & PHP拡張
RUN apt-get update && apt-get install -y \
git unzip curl libzip-dev libonig-dev libxml2-dev mariadb-client nodejs npm \
procps iproute2 net-tools \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath zip
# phpredis 拡張を追加
RUN pecl install redis \
&& docker-php-ext-enable redis
# Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# FPM listen を全インターフェースに変更
RUN sed -i 's/listen = .*/listen = 0.0.0.0:9000/' /usr/local/etc/php-fpm.d/www.conf
WORKDIR /var/www/html
# php-fpm をフォアグラウンドで起動
CMD ["php-fpm"]
docker-compose.production.yml
services:
laravel:
build:
context: .
dockerfile: Dockerfile
container_name: *****-laravel
env_file:
- .env.production
volumes:
- .:/var/www/html
ports:
- "9000:9000"
depends_on:
- redis
networks:
- *****
nginx:
image: nginx:1.25
container_name: *****-nginx
ports:
- "80:80"
volumes:
- .:/var/www/html
- ./nginx/conf.d:/etc/nginx/conf.d
depends_on:
- laravel
networks:
- *****
redis:
image: redis:7
container_name: *****-redis
ports:
- "6379:6379"
networks:
- *****
networks:
*****:
driver: bridge
8. コンテナビルド & 起動
コンテナビルド & 起動
docker compose -f docker-compose.production.yml --env-file .env.production up -d --build
docker compose ps // laravel コンテナが Up になっているか確認
本番用APP_KEY作成:
docker compose -f docker-compose.production.yml exec laravel php artisan key:generate --show
docker compose -f docker-compose.production.yml exec laravel php artisan config:cache
9. マイグレーション & シード
docker compose -f docker-compose.production.yml exec laravel php artisan migrate --force
docker compose -f docker-compose.production.yml exec laravel php artisan db:seed --force
10. Nginx 設定(EC2 フロント用)
sudo amazon-linux-extras install nginx1 -y
sudo systemctl enable nginx
sudo systemctl start nginx
//ディレクトリ作成(存在しない場合)
sudo mkdir -p /etc/nginx/conf.d
//EC2 上の Nginx を Laravel コンテナのフロントとして動かす設定
sudo nano /etc/nginx/conf.d/*****.conf
//設定テスト
sudo nginx -t
sudo systemctl restart nginx
11. React / Inertia.js のビルド設定
Inertia.js(React)で構築したフロントエンドを本番環境用にビルドします。
Vite を使用している場合、Laravel 側で JS / CSS を正しく読み込むための設定が必要です。
- ビルドコマンドの実行
docker compose -f docker-compose.production.yml exec laravel npm install
docker compose -f docker-compose.production.yml exec laravel npm run build
もしエラーで「manifest.jsonが見つからない」と出た場合:
docker exec -it tripost-laravel bash
cp public/build/.vite/manifest.json public/build/manifest.json
chown -R www-data:www-data public/build
chmod -R 755 public/build
php artisan config:clear && php artisan cache:clear
exit
- Laravel 側の設定確認
resources/views/app.blade.php や vite.config.js、config/vite.php の設定を正しく行っていない場合も
manifest 読み込みエラーが発生します。以下の設定を確認しましょう。
resources/views/app.blade.php
Laravel × Inertia.js のエントリーポイント。
Vite のビルド済み JS / CSS を読み込むよう指定します。
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title inertia>{{ config('app.name', 'Laravel') }}</title>
@routes
@viteReactRefresh
@vite([
'resources/js/app.jsx',
isset($page['component']) ? "resources/js/Pages/{$page['component']}.jsx" : null
])
@inertiaHead
</head>
<body class="font-sans antialiased">
@inertia
</body>
</html>
vite.config.js
開発環境(npm run dev)と本番環境(npm run build)を切り替える設定です。
ビルド後のファイルは /public/build に出力されます。
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
const isProduction = process.env.NODE_ENV === 'production';
export default defineConfig({
plugins: [
laravel({
input: 'resources/js/app.jsx',
refresh: !isProduction,
}),
react(),
],
base: isProduction ? '/build/' : '/',
build: {
outDir: 'public/build',
emptyOutDir: true,
manifest: true,
rollupOptions: {
input: 'resources/js/app.jsx',
},
assetsDir: 'assets',
},
});
config/vite.php
Laravel 側で Vite の manifest ファイルを参照できるようにします。
.vite/manifest.json ではなく build/manifest.json に変更しておくことが重要です。
<?php
return [
/*
|--------------------------------------------------------------------------
| Vite manifest path
|--------------------------------------------------------------------------
|
| Vite のビルド後 manifest.json のパス
|
*/
'manifest_path' => public_path('build/manifest.json'),
];
キャッシュクリア
docker compose -f docker-compose.production.yml exec laravel php artisan config:clear
docker compose -f docker-compose.production.yml exec laravel php artisan view:clear
12. HTTPS(Let’s Encrypt + Certbot)
//Certbotのインストール
sudo dnf install -y certbot python3-certbot-nginx
// Nginxコンテナを一時停止
docker stop tripost-nginx
// 証明書取得(your-domain.comを実際のドメインに置き換え)
sudo certbot certonly --standalone -d your-domain.com
// Nginxコンテナを再起動
docker start tripost-nginx
Nginx設定の更新。*****.conf に HTTPS 設定を追加:
# HTTP → HTTPS リダイレクト
server {
listen 80;
server_name your-domain.com www.your-domain.com;
return 301 https://$host$request_uri;
}
# HTTPS設定
server {
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com;
# SSL証明書の設定
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# SSL設定の最適化
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS設定(セキュリティ強化)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /var/www/html/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass laravel:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# HTTPS用パラメータ追加
fastcgi_param HTTPS on;
fastcgi_param SERVER_PORT 443;
}
location ~ /\.ht {
deny all;
}
# Let's Encrypt用のアクセス許可
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html/public;
}
docker-compose.production.yml に HTTPS ポートを追加:
ports:
- "80:80"
- "443:443"
volumes:
- /etc/letsencrypt:/etc/letsencrypt:ro
また、.env.productionファイルの該当部分をhttpsへ変更しておく。
13. 証明書の自動更新(cron)
echo "0 0 * * 0 root certbot renew --quiet && docker restart tripost-nginx" | sudo tee -a /etc/crontab
14. 動作確認
http://<EC2のパブリックIP>
https://your-domain.com
まとめ
項目 | 内容 |
---|---|
OS | Amazon Linux 2023 |
Web サーバ | Nginx (Docker) |
アプリ | Laravel + React (Inertia.js) |
DB | Amazon RDS (MySQL) |
キャッシュ | Redis |
HTTPS | Let’s Encrypt (Certbot) |
デプロイ方式 | Docker Compose + 手動更新 or CI/CD |
この構成により、開発環境(Sail)とほぼ同等の構成を EC2 上で再現でき、
「開発では動いたのに本番で動かない」問題を大幅に減らすことができます。