Failed to 'fly launch' Laravel project

I’m new to fly.io, I was following this tutorial, but I didn’t make it too far until this error appear after running fly launch:

 ==> Building image
✓ compatible remote builder found
Waiting for remote builder fly-builder-red-moon-9042...
 🌍INFO Override builder host with: https://fly-builder-red-moon-9042.fly.dev (was tcp://[fdaa:9:493f:a7b:d6:633a:c2e0:2]:2375)
Remote builder fly-builder-red-moon-9042 ready
INFO Override builder host with: https://fly-builder-red-moon-9042.fly.dev (was tcp://[fdaa:9:493f:a7b:d6:633a:c2e0:2]:2375)

Remote builder fly-builder-red-moon-9042 ready
==> Building image with Docker
--> docker host: 24.0.7 linux x86_64
[+] Building 2.0s (19/21)
 => [internal] load .dockerignore                                                                            0.3s
 => => transferring context: 476B                                                                            0.3s
 => [internal] load build definition from Dockerfile                                                         0.3s
 => => transferring dockerfile: 2.54kB                                                                       0.3s
 => resolve image config for docker.io/docker/dockerfile:experimental                                        0.2s
 => CACHED docker-image://docker.io/docker/dockerfile:experimental@sha256:600e5c62eedff338b3f7a0850beb7c058  0.0s
 => [internal] load .dockerignore                                                                            0.0s
 => [internal] load build definition from Dockerfile                                                         0.0s
 => [internal] load metadata for docker.io/library/node:18                                                   0.2s
 => [internal] load metadata for docker.io/fideloper/fly-laravel:8.3                                         0.3s
 => [node_modules_go_brrr 1/7] FROM docker.io/library/node:18@sha256:b08b1356559e2e9945f47ded630c9eb9d4e3ca  0.0s
 => [base 1/3] FROM docker.io/fideloper/fly-laravel:8.3@sha256:e1f0257c517d645dfefe30f1aede7b0c9dfb7ce9e988  0.0s
 => [internal] load build context                                                                            0.2s
 => => transferring context: 7.76kB                                                                          0.2s
 => CACHED [node_modules_go_brrr 2/7] RUN mkdir /app                                                         0.0s
 => CACHED [node_modules_go_brrr 3/7] RUN mkdir -p  /app                                                     0.0s
 => CACHED [node_modules_go_brrr 4/7] WORKDIR /app                                                           0.0s
 => CACHED [node_modules_go_brrr 5/7] COPY . .                                                               0.0s
 => CACHED [base 2/3] COPY . /var/www/html                                                                   0.0s
 => CACHED [base 3/3] RUN composer install --optimize-autoloader --no-dev     && mkdir -p storage/logs       0.0s
 => CACHED [node_modules_go_brrr 6/7] COPY --from=base /var/www/html/vendor /app/vendor                      0.0s
 => ERROR [node_modules_go_brrr 7/7] RUN if [ -f "vite.config.js" ]; then         ASSET_CMD="build";     el  0.8s
------
 > [node_modules_go_brrr 7/7] 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;:
0.592 npm error code ENOENT
0.592 npm error syscall open
0.592 npm error path /app/package.json
0.592 npm error errno -2
0.593 npm error enoent Could not read package.json: Error: ENOENT: no such file or directory, open '/app/package.json'
0.594 npm error enoent This is related to npm not being able to find a file.
0.594 npm error enoent
0.594
0.594 npm error A complete log of this run can be found in: /root/.npm/_logs/2024-05-22T04_16_27_038Z-debug-0.log
0.738 npm error code ENOENT
0.738 npm error syscall open
0.738 npm error path /app/package.json
0.739 npm error errno -2
0.740 npm error enoent Could not read package.json: Error: ENOENT: no such file or directory, open '/app/package.json'
0.740 npm error enoent This is related to npm not being able to find a file.
0.740 npm error enoent
0.741
0.741 npm error A complete log of this run can be found in: /root/.npm/_logs/2024-05-22T04_16_27_505Z-debug-0.log
------
Error: failed to fetch an image or build from source: error building: failed to solve: process "/bin/sh -c 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;" did not complete successfully: exit code: 254

The error message mentioned that it couldn’t find a package.json file. My project doesn’t have one because it’s just a Laravel REST API.

Hi @cin4ed !

I’m with Fly.io and I’ll help you out. Here’s what’s happening and how to fix it:

The issue

When running fly launch in a Laravel app, a couple of files are automatically set up. One of those files is the Dockerfile, which is how we’ll build a container that we can deploy on Fly.io’s servers.

The original Dockerfile actually does a multi-stage build, in three steps:

  1. Set up an environment where PHP and Laravel can run
  2. Create a new environment where the node modules are installed, using yarn, pnpm or npm.
  3. Copy over the node modules to the environment created in step 1.
    The advantage of this is that the final container will have the correct node modules without needing to include node itself. This makes the final container smaller and keeps deployments snappy.

Since you have no package.json file npm install cannot run and will spit out errors, which is what you’re seeing).

The fix

The fix for this would be to eliminate steps 2 and 3 from the Dockerfile. If you comment out lines 28-74 (keep the expose 8080 line) it should work!
For reference, this is how a Dockerfile for this case could look:

# syntax = docker/dockerfile:experimental

ARG PHP_VERSION=8.2
ARG NODE_VERSION=18
FROM fideloper/fly-laravel:${PHP_VERSION} as base

# PHP_VERSION needs to be repeated here
# See https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
ARG PHP_VERSION

LABEL fly_launch_runtime="laravel"

# copy application code, skipping files based on .dockerignore
COPY . /var/www/html

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

EXPOSE 8080

The lines that are commented out can also be removed if you want.
Let me know if this helps!

2 Likes

Hey @Johannes-Fly, that solved my problem. Thank you!

It would be a good idea to handle this edge case in future Dockerfiles for Laravel projects, as it is common to use Laravel solely as an API.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.