個人開発でweb アプリの開発中に思い立って本番環境のデプロイを試してみたら大きな沼にはまってしまったので備忘録として。
中身は読まなくてもよいという方は最後にまとめてコードを載せていますので参考にしてください。
2024/05/05 追記
最終的に laravel forge にてデプロイすることにしました。
有料ですがlaravel公式がサポートしているため
サポートが充実していていました。
私の環境( とりあえず関係ありそうなのだけ列挙 )
php | 8.2 |
---|---|
laravel/framework | 10.10 |
laravel/jetstream | 4.0 |
@inertiajs/vue3 | 1.0.14 |
vue | 3.2.31 |
vite | 4.0.0 |
- ローカルではsailを使用して開発
- inertiaをssrモードにしている
Render 公式サイトのドキュメント
Deploy a PHP Web App with Laravel and Docker | Render Docs
renderのlaravel用公式ドキュメントがlaravel5.8(2024/02/12)へのドキュメントしかなく。このままでは動かない。
今回、乗り越えた問題
- render.comのsecretfilesに設定した.envが参照できない問題。
- ドメインのルートのみでしかpageが正しく表示されない
-
php artisan inertia:start-ssr
の実行場所について - Vite manifest not found と怒られる
- ssrモードでziggyのroute()関数が
ReferenceError: route is not defined
となる
render.comのsecretfilesに設定した.envが参照できない問題。
原因
+ Add Secret File
に.env
を置くと自動的にlaravel側でも読み込んでくれると思ってたが違った。
解決方法
dockerfileでファイルをアプリケーションのルートフォルダにコピーする。
# syntax = docker/dockerfile:1.2
### 省略 ###
RUN --mount=type=secret,id=_env,dst=/etc/secrets/.env cp /etc/secrets/.env .
ドメインのルートのみでしかpageが表示されない
下記のようにルート以外はpage not foundとなってしまう。
原因
inertiaをssrモードにしていたのにサーバーを実行していなかったため。
https://inertiajs.com/server-side-rendering
解決方法
php artisan inertia:start-ssr
を実行する。
Vite manifest not found と怒られる
原因
public/build/manifest.json
が見つからずエラーとなっていた。
build途中でメモリ不足となりkillされていたため最後まで走り切ってなかった。
解決方法
有料版のメモリ1Gに切り替えてbuildを実行した
25$/月かかるためどうするか迷っている。。。
ssrモードの起動の実行場所について
inrtiaをssrモードで使用する場合にphp artisan inertia:start-ssr
を実行する必要がある。
今回使用したdockerimageは richarvey/nginx-php-fpm:3.1.6
こちらはドキュメントを見てもらえばわかる通りscriptsを記述することができるため
/scripts/01-front-build.shの中で起動していた。
#!/usr/bin/env bash
# パッケージのインストール
npm install
# ビルド
npm run build
# ssrサーバー起動
php artisan inertia:start-ssr
そうしたらすべてのルートで下記の画面が出てくるようになってしまった。
解決方法
Infrastructure as Code (IaC)のrender.yaml
にてstartCommandで実行してあげないといけなかった。
5. ssrモードでziggyのroute()関数が ReferenceError: route is not defined
となる
下記は両方ともSSRでなければ動くのだが
SSRモードにした際はパターン2で記述する必要がある。
template内でroute()を呼び出せないみたい
パターン1
<script setup>
const pages = {
return{
hoge : route('hoge.index'),
fuga : route('fuga.index'),
piyo : route('piyo.index'),
}
}
</script>
<template>
<div>
<a v-for="(page, name) in pages" :key="name" :href="page">{{ name }}</a>
</div>
</template>
パターン2
<script setup>
const pages = () => {
hoge : route('hoge.index'),
fuga : route('fuga.index'),
piyo : route('piyo.index'),
}
</script>
<template>
<div>
<a v-for="(page, name) in pages" :key="name" :href="page">{{ name }}</a>
</div>
</template>
(20240605追記)
ssr.jsに下記を+したらTemplate内でもrouteを参照できるようになりました。
import { createSSRApp, h } from 'vue'
import { renderToString } from '@vue/server-renderer'
import { createInertiaApp } from '@inertiajs/vue3'
import createServer from '@inertiajs/vue3/server'
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'
import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.m'
+ import { route } from 'ziggy-js'
const appName = import.meta.env.VITE_APP_NAME || 'Laravel'
createServer((page) =>
createInertiaApp({
page,
render: renderToString,
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
setup({ App, props, plugin }) {
+ const Ziggy = {
+ // Pull the Ziggy config off of the props.
+ ...props.initialPage.props.ziggy,
+ // Build the location, since there is
+ // no window.location in Node.
+ location: new URL(props.initialPage.props.ziggy.url)
+ }
+ globalThis.route = (name, params, absolute, config = Ziggy) =>
+ route(name, params, absolute, config)
return createSSRApp({ render: () => h(App, props) })
.use(plugin)
.use(ZiggyVue, {
...page.props.ziggy,
location: new URL(page.props.ziggy.location),
})
},
})
)
最後にどなたかの参考になれば
Deploy Laravel and Memcache on Render.com: The Complete Guide - MemCachier Blogの記事を参考にセットアップしております。
- Dockerfile
# syntax = docker/dockerfile:1.2 # Dockerfile # Use base image for container FROM richarvey/nginx-php-fpm:3.1.6 # Copy all application code into your Docker container COPY . . RUN --mount=type=secret,id=_env,dst=/etc/secrets/.env cp /etc/secrets/.env . RUN apk update # Install the `npm` package RUN apk add --no-cache npm CMD ["/start.sh"]
- render.yml
databases: - name: app-db plan: free databaseName: v_shelf_db user: webapp services: - type: web plan: standard name: app runtime: docker startCommand: 'php artisan inertia:start-ssr' envVars: - fromGroup: app-secrets - fromGroup: app-share-secrets # Database - key: DATABASE_URL fromDatabase: name: app-db property: connectionString - key: DB_CONNECTION value: pgsql # Laravel - key: APP_URL value: https://app.onrender.com - key: APP_KEY sync: false - key: APP_ENV value: production - key: APP_DEBUG value: false - key: LOG_CHANNEL value: stderr - key: MEILISEARCH_HOST value: app-meilisearch # Image-specific vars (richarvey/nginx-php-fpm) - key: WEBROOT value: /var/www/html/public - key: RUN_SCRIPTS value: 1 - key: REAL_IP_HEADER value: 1 - key: SKIP_COMPOSER value: 1 - type: web name: app-meilisearch env: docker repo: https://github.com/ShakeSpheres/meilisearch-jp-docker-to-render.git plan: starter disk: name: meili-data mountPath: /meili-data sizeGB: 5 envVars: - fromGroup: app-share-secrets - key: MEILI_HTTP_ADDR value: 0.0.0.0:80 - key: MEILI_DB_PATH value: /meili-data - key: MEILI_ENV value: development envVarGroups: - name: app-share-secrets envVars: - key: MEILI_MASTER_KEY generateValue: true
- .dockerignore
# .dockerignore .DS_Store .dockerignore .editorconfig .env .env.backup .env.example .env.production .git .gitattributes /.fleet /.idea /.phpunit.cache /.vscode Homestead.json Homestead.yaml Dockerfile README.md /auth.json /node_modules /npm-debug.log /phpunit.result.cache /public/build /public/hot /public/storage /phpunit.xml storage/app/* storage/framework/cache/* storage/framework/sessions/* storage/framework/views/* storage/logs/* tests /vendor yarn-error.log
- scripts/00-laravel-setup.sh
#!/usr/bin/env bash echo "Running composer" composer install --no-dev --working-dir=/var/www/html echo "Caching config..." php artisan config:cache echo "Caching routes..." php artisan route:cache echo "Running migrations..." php artisan migrate --force
- scripts/01-front-build.sh
#!/usr/bin/env bash # パッケージのインストール npm install # ビルド npm run build
- conf/nginx/nginx-site.conf
server { # Render provisions and terminates SSL listen 80; # Make site accessible from http://localhost/ server_name _; root /var/www/html/public; index index.html index.htm index.php; # Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html sendfile off; # Add stdout logging error_log /dev/stdout info; access_log /dev/stdout; # block access to sensitive information about git location /.git { deny all; return 403; } add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~* \.(jpg|jpeg|gif|png|css|js|ico|webp|tiff|ttf|svg)$ { expires 5d; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; include fastcgi_params; } # deny access to . files location ~ /\. { log_not_found off; deny all; } location ~ /\.(?!well-known).* { deny all; } }