Fly.io の「Laravel on Fly.io」のページに従ってデプロイの練習をやってみた

### 前提

- [Fly.io](https://fly.io/)のページについては、2024年8月7日時点の構成で説明しています。
- 検証環境
    - MacBook Pro(Intel)
        - macOS Sonoma 14.5

---

[Fly.io](https://fly.io/)のページにアクセスし、画面上部メニューのから「[Docs](https://fly.io/docs/)」をクリックします。

![スクリーンショット 2024-08-07 9.16.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23093/36ed6739-5556-5ef5-5623-1df4fba37262.png)

---

検索フォームから「Laravel」と入力します。

![スクリーンショット 2024-08-07 9.17.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23093/d6e8072f-567d-2a30-f6dc-f6ac6bf3b7da.png)

「Laravel on Fly.io」がヒットするのでクリックします。

![スクリーンショット 2024-08-07 9.18.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23093/dd74c479-1513-8f84-8aa4-e975ac1bc7cd.png)

「[Laravel on Fly.io](https://fly.io/docs/laravel/)」のページに従って作業を進めていきます。

---

事前準備として以下の説明が記載されています。

![スクリーンショット 2024-08-07 9.33.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23093/5a503647-87a4-924f-30e2-5c4ab9498cfb.png)

PHP8以上と　`composer`　コマンドを実行できる環境が必要なので、今回はDockerを使って「`php:8.3.10`」を利用することとします。

以下のコマンドを実行してコンテナを起動し、コンテナ内に入ります。

- デプロイ練習が終わったら不要な環境となるため `--rm` を付与しています。
- コンテナ実行環境の8000番ポートを利用するので `127.0.0.1:8000:8000` を付与しています。

```
% docker container run --rm -p 127.0.0.1:8000:8000 -it php:8.3.10 bash
```


コンテナのOSを確認すると `Debian GNU/Linux 12 (bookworm)` であることがわかります。

```
# grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
```

PHPのバージョンは「`php:8.3.10`」と指定していたので、当然「`8.3.10`」と表示されます。

```
# php -v
PHP 8.3.10 (cli) (built: Aug  1 2024 19:23:45) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.10, Copyright (c) Zend Technologies
```

`composer` コマンドはインストールされていません。

```
# composer --version
bash: composer: command not found
```

[Download Composer](https://getcomposer.org/download/)のページに従って、`composer` コマンドをインストールします。

```
# php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
# php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
# php composer-setup.php
# php -r "unlink('composer-setup.php');"
# mv composer.phar /usr/local/bin/composer
```

Composerのバージョンは2024年8月7日時点では「`2.7.7`」がインストールされるようです。

```
# composer --version
Composer version 2.7.7 2024-06-10 22:11:12
PHP version 8.3.10 (/usr/local/bin/php)
Run the "diagnose" command to get more detailed diagnostics output.
```

Laravelのインストールの過程で必要なパッケージ群をインストールします。

```
# apt update
# apt install -y git zip unzip
```

---

準備が整いましたので、コンテナ内でLaravelの環境を構築します。

- コンテナ内の8000番ポートをコンテナ実行環境にマッピングするため `--host=0.0.0.0 --port=8000` を付与します。

```
# composer create-project laravel/laravel fly-laravel
# cd fly-laravel
# php artisan serve --host=0.0.0.0 --port=8000
```

コンテナ実行環境のブラウザで http://127.0.0.1:8000/ にアクセスして、動作していることを確認します。

![スクリーンショット 2024-08-07 9.54.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23093/7158aa3f-1b60-5180-7c01-1abcde81df9f.png)

---

Fly.ioにデプロイするために `flyctl(fly)` コマンドをインストールします。
※インストール方法については「[Fly.io の「Hands-on」ページに従ってデプロイの練習をやってみた](https://qiita.com/akase244/items/ef9267f6e7c68ccb0f6a)」で紹介しています。

```
# curl -L https://fly.io/install.sh | sh
・
・
flyctl was installed successfully to /root/.fly/bin/flyctl
Manually add the directory to your $HOME/.bash_profile (or similar)
  export FLYCTL_INSTALL="/root/.fly"
  export PATH="$FLYCTL_INSTALL/bin:$PATH"
Run '/root/.fly/bin/flyctl --help' to get started

# apt install -y vim
# vim $HOME/.bash_profile
# tail -2 $HOME/.bash_profile
export FLYCTL_INSTALL="/root/.fly"
export PATH="$FLYCTL_INSTALL/bin:$PATH"
# . $HOME/.bash_profile
```

`flyctl(fly)` コマンドのバージョンを確認します。

```
# flyctl version
flyctl v0.2.107 linux/amd64 Commit: 87aa565a15aa220c2e846453279417724658a598 BuildDate: 2024-08-06T18:32:57Z
```

```
# fly version  
flyctl v0.2.107 linux/amd64 Commit: 87aa565a15aa220c2e846453279417724658a598 BuildDate: 2024-08-06T18:32:57Z
```

`fly` コマンドは `flyctl` コマンドへのシンボリックリンクになっています。

```
# which flyctl
/root/.fly/bin/flyctl

# which fly
/root/.fly/bin/fly

# ls -l /root/.fly/bin/fly
lrwxrwxrwx 1 root root 21 Aug  7 00:58 /root/.fly/bin/fly -> /root/.fly/bin/flyctl
```

なお、 `flyctl` コマンドは「[Command Lines, Flyctl and Fly](https://fly.io/blog/command-lines-flyctl-and-fly/)」の記事によると、Go製のようです。

`flyctl` コマンドと `fly` コマンドが共存している状態ですが、コミュニティページの「[What’s the difference between Fly and Flyctl?](https://community.fly.io/t/whats-the-difference-between-fly-and-flyctl/1377)」によると、いずれ `fly` コマンドに統合される？のかもしれません。
これを踏まえ、以降は `fly` コマンドにて説明を続けます。

---

Laravelのアプリケーションをインストールしたディレクトリで Fly.io へのデプロイ作業を行っていきます。

```
# pwd
/fly-laravel
```

`fly launch` コマンドを実行すると、 Fly.io へのサインインが求められるので「y」と入力します。

```
# fly launch
? You must be logged in to do this. Would you like to sign in? (y/N) y
```

以下のように表示が切り替わり、本来であればここでブラウザが起動するのですが、コンテナ内で実行しているためブラウザが起動しません。
なので、表示されているURLをコピーし、ブラウザのURL欄に貼り付けて直接アクセスします。

```
? You must be logged in to do this. Would you like to sign in? Yes
failed opening browser. Copy the url (https://fly.io/app/auth/cli/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX) into a browser and continue
Opening https://fly.io/app/auth/cli/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ...

Waiting for session...⣷
```

ブラウザでアクセスすると以下のように表示されるので、「Continue as メールアドレス」の部分をクリックします。

![スクリーンショット_2024-08-07_10_11_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23093/92cb31ca-1c91-3b18-76e5-d21affc4f1c6.png)

「Waiting for session...」の表示が「Done」に切り替わり、以下のように表示されます。
ここでは、どのOrganizationを利用するかだったり、マシンスペックなどが表示されています。
何も変更する必要がなければ「N」と入力します。「y」と入力すると（本来であれば）ブラウザが起動し、Fly.ioの画面上で設定を調整することが可能です。
今回はデプロイ練習なのでサッと試すために「N」と入力します。

```
Waiting for session... Done
successfully logged in as メールアドレス
Scanning source code
Detected a Laravel app
Creating app in /fly-laravel
We're about to launch your Laravel app on Fly.io. Here's what you're getting:

Organization: XXXXXXXX                                                   (fly launch defaults to the personal org)
Name:         fly-laravel-XXXXXXXXX-XXXX-XXXX                            (generated)
Region:       Tokyo, Japan                                               (this is the fastest region for you)
App Machines: shared-cpu-1x, 1GB RAM                                     (most apps need about 1GB of RAM)
Postgres:     <none>                                                     (not requested)
Redis:        Pay-as-you-go Plan: 10 GB Max Data Size, eviction disabled (determined from app source)
Tigris:       <none>                                                     (not requested)

? Do you want to tweak these settings before proceeding? (y/N) N
```

以下のように表示が切り替わり、Laravelのインストールやデプロイの経過が確認できます。

```
? Do you want to tweak these settings before proceeding? No
Created app 'fly-laravel-XXXXXXXXX-XXXX-XXXX' in organization 'personal'
Admin URL: https://fly.io/apps/fly-laravel-XXXXXXXXX-XXXX-XXXX
Hostname: fly-laravel-XXXXXXXXX-XXXX-XXXX.fly.dev
Set secrets on fly-laravel-XXXXXXXXX-XXXX-XXXX: APP_KEY

Your database fly-laravel-XXXXXXXXX-XXXX-XXXX-redis is ready. Apps in the personal org can connect to Redis at redis://default:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX@fly-fly-laravel-XXXXXXXXX-XXXX-XXXX-redis.upstash.io:6379

If you have redis-cli installed, use fly redis connect to get a Redis console.

Your database is billed at $0.20 per 100K commands. If you're using Sidekiq or BullMQ, which poll Redis frequently, consider switching to a fixed-price plan. See https://fly.io/docs/reference/redis/#pricing

Redis database fly-laravel-XXXXXXXXX-XXXX-XXXX-redis is set on fly-laravel-XXXXXXXXX-XXXX-XXXX as the REDIS_URL environment variable
installing: composer require --dev fly-apps/dockerfile-laravel
./composer.json has been updated
Running composer update fly-apps/dockerfile-laravel
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking fly-apps/dockerfile-laravel (1.0.6)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Downloading fly-apps/dockerfile-laravel (1.0.6)
  - Installing fly-apps/dockerfile-laravel (1.0.6): Extracting archive
Generating optimized autoload files
Warning: Ambiguous class resolution, "App\Providers\AppServiceProvider" was found in both "/fly-laravel/app/Providers/AppServiceProvider.php" and "/fly-laravel/vendor/fly-apps/dockerfile-laravel/app/Providers/AppServiceProvider.php", the first will be used.
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi

   INFO  Discovering packages.  

  laravel/sail ....................................................................................................... DONE
  laravel/tinker ..................................................................................................... DONE
  nesbot/carbon ...................................................................................................... DONE
  nunomaduro/collision ............................................................................................... DONE
  nunomaduro/termwind ................................................................................................ DONE

79 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan vendor:publish --tag=laravel-assets --ansi --force

   INFO  No publishable resources for tag [laravel-assets].  

No security vulnerability advisories found.
Using version ^1.0 for fly-apps/dockerfile-laravel
Running: vendor/bin/dockerfile-laravel generate
  create    Dockerfile
  create    .dockerignore
  create    .fly/entrypoint.sh
  create    .fly/start-nginx.sh
  create    .fly/scripts/caches.sh
  create    .fly/fpm/pool.d/www.conf
  create    .fly/nginx/conf.d/access-log.conf
  create    .fly/nginx/conf.d/websockets.conf
  create    .fly/nginx/sites-available/default-octane
  create    .fly/nginx/sites-available/default
  create    .fly/nginx/nginx.conf
  create    .fly/php/packages/7.4.txt
  create    .fly/php/packages/8.0.txt
  create    .fly/php/packages/8.1.txt
  create    .fly/php/packages/8.2.txt
  create    .fly/php/packages/8.3.txt
  create    .fly/php/ondrej_ubuntu_php.gpg
  create    .fly/supervisor/conf.d/fpm.conf
  create    .fly/supervisor/conf.d/nginx.conf
  create    .fly/supervisor/supervisord.conf
Wrote config file fly.toml
Validating /fly-laravel/fly.toml
✓ Configuration is valid
==> Building image
Remote builder fly-builder-rough-glitter-2586 ready
==> Building image with Docker
--> docker host: 24.0.7 linux x86_64
[+] Building 22.4s (34/34) FINISHED                                                                                          
 => [internal] load build definition from Dockerfile                                                                    0.1s
 => => transferring dockerfile: 4.52kB                                                                                  0.1s
 => [internal] load .dockerignore                                                                                       0.1s
 => => transferring context: 476B                                                                                       0.1s
 => resolve image config for docker.io/docker/dockerfile:experimental                                                   1.4s
 => CACHED docker-image://docker.io/docker/dockerfile:experimental@sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  0.0s
 => [internal] load .dockerignore                                                                                       0.0s
 => [internal] load build definition from Dockerfile                                                                    0.0s
 => [internal] load metadata for docker.io/library/ubuntu:22.04                                                         0.4s
 => [internal] load metadata for docker.io/library/node:18                                                              0.6s
 => [internal] load build context                                                                                       0.5s
 => => transferring context: 419.16kB                                                                                   0.5s
 => FROM docker.io/library/composer:2                                                                                   0.4s
 => => resolve docker.io/library/composer:2                                                                             0.4s
 => [node_modules_go_brrr 1/7] FROM docker.io/library/node:18@sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  0.0s
 => [base  1/14] FROM docker.io/library/ubuntu:22.04@sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  0.0s
 => CACHED [node_modules_go_brrr 2/7] RUN mkdir /app                                                                    0.0s
 => CACHED [node_modules_go_brrr 4/7] WORKDIR /app                                                                      0.0s
 => CACHED [node_modules_go_brrr 3/7] RUN mkdir -p  /app                                                                0.0s
 => CACHED [base  8/14] COPY .fly/supervisor/ /etc/supervisor/                                                          0.0s
 => CACHED [base  6/14] COPY .fly/nginx/ /etc/nginx/                                                                    0.0s
 => CACHED [base  7/14] COPY .fly/fpm/ /etc/php/8.3/fpm/                                                                0.0s
 => CACHED [base  2/14] COPY --from=composer:2 /usr/bin/composer /usr/bin/composer                                      0.0s
 => CACHED [base  9/14] COPY .fly/entrypoint.sh /entrypoint                                                             0.0s
 => CACHED [base 10/14] COPY .fly/start-nginx.sh /usr/local/bin/start-nginx                                             0.0s
 => CACHED [base 11/14] RUN chmod 754 /usr/local/bin/start-nginx                                                        0.0s
 => CACHED [base  5/14] RUN apt-get update     && apt-get install -y --no-install-recommends gnupg2 ca-certificates gi  0.0s
 => CACHED [base  4/14] ADD .fly/php/packages/8.3.txt /tmp/php-packages.txt                                             0.0s
 => CACHED [base  3/14] COPY .fly/php/ondrej_ubuntu_php.gpg /etc/apt/trusted.gpg.d/ondrej_ubuntu_php.gpg                0.0s
 => [base 12/14] COPY . /var/www/html                                                                                   0.0s
 => [node_modules_go_brrr 5/7] COPY . .                                                                                 0.0s
 => [base 13/14] WORKDIR /var/www/html                                                                                  0.0s
 => [base 14/14] RUN composer install --optimize-autoloader --no-dev     && mkdir -p storage/logs     && php artisan o  8.2s
 => [node_modules_go_brrr 6/7] COPY --from=base /var/www/html/vendor /app/vendor                                        0.8s
 => [node_modules_go_brrr 7/7] RUN if [ -f "vite.config.js" ]; then         ASSET_CMD="build";     else         ASSET_  8.9s
 => [stage-2 1/2] COPY --from=node_modules_go_brrr /app/public /var/www/html/public-npm                                 0.0s
 => [stage-2 2/2] RUN rsync -ar /var/www/html/public-npm/ /var/www/html/public/     && rm -rf /var/www/html/public-npm  0.2s
 => exporting to image                                                                                                  0.6s
 => => exporting layers                                                                                                 0.6s
 => => writing image sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                            0.0s
 => => naming to registry.fly.io/fly-laravel-XXXXXXXXX-XXXX-XXXX:deployment-01J4N6MTJPTNHZ9N9M91WTX3CE                  0.0s
--> Building image done
==> Pushing image to fly
The push refers to repository [registry.fly.io/fly-laravel-XXXXXXXXX-XXXX-XXXX]
XXXXXXXXXXXX: Pushed 
・
・
XXXXXXXXXXXX: Pushed 
deployment-XXXXXXXXXXXXXXXXXXXXXXXXXX: digest: sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX size: 3653
--> Pushing image done
image: registry.fly.io/fly-laravel-XXXXXXXXX-XXXX-XXXX:deployment-01J4N6MTJPTNHZ9N9M91WTX3CE
image size: 357 MB

Watch your deployment at https://fly.io/apps/fly-laravel-XXXXXXXXX-XXXX-XXXX/monitoring

Provisioning ips for fly-laravel-XXXXXXXXX-XXXX-XXXX
  Dedicated ipv6: XXXX:XXXX:X::XX:XXXX:X
  Shared ipv4: XXX.XXX.XXX.XXX
  Add a dedicated ipv4 with: fly ips allocate-v4

This deployment will:
 * create 2 "app" machines

No machines in group app, launching a new machine

WARNING The app is not listening on the expected address and will not be reachable by fly-proxy.
You can fix this by configuring your app to listen on the following addresses:
  - 0.0.0.0:8080
Found these processes inside the machine with open listening sockets:
  PROCESS        | ADDRESSES                             
-----------------*---------------------------------------
  /.fly/hallpass | [XXXX:X:XXXX:XXX:XXX:XXXX:XXXX:X]:XX  

Creating a second machine to increase service availability
Finished launching new machines
-------
NOTE: The machines for [app] have services with 'auto_stop_machines = "stop"' that will be stopped when idling

-------
Checking DNS configuration for fly-laravel-XXXXXXXXX-XXXX-XXXX.fly.dev

Visit your newly deployed app at https://fly-laravel-XXXXXXXXX-XXXX-XXXX.fly.dev/
```

最後に「Visit your newly deployed app at https://fly-laravel-XXXXXXXXX-XXXX-XXXX.fly.dev/ 」のようにURLが表示されるので、ブラウザでアクセスすると、 Fly.io 上にデプロイされたLaravelのアプリケーションが確認できます。

![スクリーンショット_2024-08-07_10_28_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23093/4b94beff-d4eb-a7c5-760e-64ea46e9e7ca.png)


---

`fly launch` コマンド実行時に自動生成された `Dockerfile` と `fly.toml` の中身はこんな感じです。
Fly.io へのデプロイは `Dockerfile` と `fly.toml` によって制御されています。

```
# cat Dockerfile 
# syntax = docker/dockerfile:experimental

ARG PHP_VERSION=8.2
ARG NODE_VERSION=18
FROM ubuntu:22.04 as base
LABEL fly_launch_runtime="laravel"

# PHP_VERSION needs to be repeated here
# See https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
ARG PHP_VERSION
ENV DEBIAN_FRONTEND=noninteractive \
    COMPOSER_ALLOW_SUPERUSER=1 \
    COMPOSER_HOME=/composer \
    COMPOSER_MAX_PARALLEL_HTTP=24 \
    PHP_PM_MAX_CHILDREN=10 \
    PHP_PM_START_SERVERS=3 \
    PHP_MIN_SPARE_SERVERS=2 \
    PHP_MAX_SPARE_SERVERS=4 \
    PHP_DATE_TIMEZONE=UTC \
    PHP_DISPLAY_ERRORS=Off \
    PHP_ERROR_REPORTING=22527 \
    PHP_MEMORY_LIMIT=256M \
    PHP_MAX_EXECUTION_TIME=90 \
    PHP_POST_MAX_SIZE=100M \
    PHP_UPLOAD_MAX_FILE_SIZE=100M \
    PHP_ALLOW_URL_FOPEN=Off

# Prepare base container: 
# 1. Install PHP, Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
COPY .fly/php/ondrej_ubuntu_php.gpg /etc/apt/trusted.gpg.d/ondrej_ubuntu_php.gpg
ADD .fly/php/packages/${PHP_VERSION}.txt /tmp/php-packages.txt

RUN apt-get update \
    && apt-get install -y --no-install-recommends gnupg2 ca-certificates git-core curl zip unzip \
                                                  rsync vim-tiny htop sqlite3 nginx supervisor cron \
    && ln -sf /usr/bin/vim.tiny /etc/alternatives/vim \
    && ln -sf /etc/alternatives/vim /usr/bin/vim \
    && echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu jammy main" > /etc/apt/sources.list.d/ondrej-ubuntu-php-focal.list \
    && apt-get update \
    && apt-get -y --no-install-recommends install $(cat /tmp/php-packages.txt) \
    && ln -sf /usr/sbin/php-fpm${PHP_VERSION} /usr/sbin/php-fpm \
    && mkdir -p /var/www/html/public && echo "index" > /var/www/html/public/index.php \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*

# 2. Copy config files to proper locations
COPY .fly/nginx/ /etc/nginx/
COPY .fly/fpm/ /etc/php/${PHP_VERSION}/fpm/
COPY .fly/supervisor/ /etc/supervisor/
COPY .fly/entrypoint.sh /entrypoint
COPY .fly/start-nginx.sh /usr/local/bin/start-nginx
RUN chmod 754 /usr/local/bin/start-nginx
    
# 3. Copy application code, skipping files based on .dockerignore
COPY . /var/www/html
WORKDIR /var/www/html

# 4. Setup application dependencies 
RUN composer install --optimize-autoloader --no-dev \
    && mkdir -p storage/logs \
    && php artisan optimize:clear \
    && chown -R www-data:www-data /var/www/html \
    && echo "MAILTO=\"\"\n* * * * * www-data /usr/bin/php /var/www/html/artisan schedule:run" > /etc/cron.d/laravel \
    && sed -i='' '/->withMiddleware(function (Middleware \$middleware) {/a\
        \$middleware->trustProxies(at: "*");\
    ' bootstrap/app.php; \ 
    if [ -d .fly ]; then cp .fly/entrypoint.sh /entrypoint; chmod +x /entrypoint; fi;




# Multi-stage build: Build static assets
# This allows us to not include Node within the final container
FROM node:${NODE_VERSION} as node_modules_go_brrr

RUN mkdir /app

RUN mkdir -p  /app
WORKDIR /app
COPY . .
COPY --from=base /var/www/html/vendor /app/vendor

# Use yarn or npm depending on what type of
# lock file we might find. Defaults to
# NPM if no lock file is found.
# Note: We run "production" for Mix and "build" for Vite
RUN if [ -f "vite.config.js" ]; then \
        ASSET_CMD="build"; \
    else \
        ASSET_CMD="production"; \
    fi; \
    if [ -f "yarn.lock" ]; then \
        yarn install --frozen-lockfile; \
        yarn $ASSET_CMD; \
    elif [ -f "pnpm-lock.yaml" ]; then \
        corepack enable && corepack prepare pnpm@latest-8 --activate; \
        pnpm install --frozen-lockfile; \
        pnpm run $ASSET_CMD; \
    elif [ -f "package-lock.json" ]; then \
        npm ci --no-audit; \
        npm run $ASSET_CMD; \
    else \
        npm install; \
        npm run $ASSET_CMD; \
    fi;

# From our base container created above, we
# create our final image, adding in static
# assets that we generated above
FROM base

# Packages like Laravel Nova may have added assets to the public directory
# or maybe some custom assets were added manually! Either way, we merge
# in the assets we generated above rather than overwrite them
COPY --from=node_modules_go_brrr /app/public /var/www/html/public-npm
RUN rsync -ar /var/www/html/public-npm/ /var/www/html/public/ \
    && rm -rf /var/www/html/public-npm \
    && chown -R www-data:www-data /var/www/html/public

# 5. Setup Entrypoint
EXPOSE 8080

ENTRYPOINT ["/entrypoint"]
```

```
# cat fly.toml 
# fly.toml app configuration file generated for fly-laravel-thrumming-frog-1677 on 2024-08-07T01:18:15Z
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = 'fly-laravel-XXXXXXXXX-XXXX-XXXX'
primary_region = 'nrt'
console_command = 'php /var/www/html/artisan tinker'

[build]
  [build.args]
    NODE_VERSION = '18'
    PHP_VERSION = '8.3'

[env]
  APP_ENV = 'production'
  LOG_CHANNEL = 'stderr'
  LOG_LEVEL = 'info'
  LOG_STDERR_FORMATTER = 'Monolog\Formatter\JsonFormatter'
  SESSION_DRIVER = 'cookie'
  SESSION_SECURE_COOKIE = 'true'

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = 'stop'
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

[[vm]]
  memory = '1gb'
  cpu_kind = 'shared'
  cpus = 1
```