deployment error: Error: Cannot find module '/app/serve'. [fly api proxy] listening at /.fly/api

hello all,

Error: Cannot find module '/app/serve'

Preparing to run: `docker-entrypoint.sh serve -s dist -l 80` as root
[fly api proxy] listening at /.fly/api

so apparently npm serve package issue…

I’m encountering a deployment error when building images for my React-Express app using a GitHub Action CI-CD pipeline.

The images build successfully and pushed to Docker Hub, but when attempting to deploy (starting with the server image), an error occurs related to the client (the second image), which hasn’t started deployment yet.
I suspect the issue lies with the TOML file.
Additionally, the npm serve package has been installed globally and as the root user.
All files and locations have been validated through the build log.

This is the error:

Node.js v20.9.0
 INFO Main child exited normally with code: 1
 INFO Starting clean up.
 WARN could not unmount /rootfs: EINVAL: Invalid argument
[    1.783213] reboot: Restarting system
2024-10-30T13:41:51.854035368 [01JBETFRV3V83QRDVVN8ZE241T:main] Running Firecracker v1.7.0
 INFO Starting init (commit: 693c179a)...
 INFO Preparing to run: `docker-entrypoint.sh serve -s dist -l 80` as root
 INFO [fly api proxy] listening at /.fly/api
   Machine started in 1.012s
2024/10/30 13:41:52 INFO SSH listening listen_address=[fdaa:a:ac95:a7b:86:f79e:5bd1:2]:22 dns_server=[fdaa::3]:53
node:internal/modules/cjs/loader:1051
  throw err;
  ^
Error: Cannot find module '/app/serve'
    at Module._resolveFilename (node:internal/modules/cjs/loader:1048:15)
    at Module._load (node:internal/modules/cjs/loader:901:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12)
    at node:internal/main/run_main_module:23:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []

./fly.toml


app = "x-realestate"
primary_region = "fra"


[[vm]]
  memory = "256mb"
  cpu_kind = "shared"
  cpus = 1

[env]
  NODE_ENV = "production"


[processes]
  server = "node --trace-warnings dist/index.js"  # server start command
  client = "serve -s dist -l 80"  # run static server

[[services]]
  processes = ["server"]
  internal_port = 8000
  protocol = "tcp"
  image = "registry.fly.io/x-realestate:server-latest"

  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
  [[services.ports]]
    handlers = ["http"]
    port = 80

[[services]]
  processes = ["client"]
  internal_port = 80  # Keep NGINX on port 80 for ngnix
  protocol = "tcp"
  image = "registry.fly.io/x-realestate:client-latest"
  
  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
  [[services.ports]]
    handlers = ["http"]
    port = 80

the react.js ./client/Dockerfile


# Production Dockerfile for the client
FROM node:20.9.0 AS build_stage 

# Set the container runtime environment variables (used at build time)
ARG VITE_FIREBASE_API_KEY
ARG VITE_AUTH_DOMAIN
ARG VITE_PROJECT_ID
ARG VITE_STORAGE_BUCKET
ARG VITE_MESSAGING_SENDER_ID
ARG VITE_APP_ID
ARG VITE_NODE_ENV=production
ARG VITE_APP_API_ENDPOINT

ENV VITE_FIREBASE_API_KEY=${VITE_FIREBASE_API_KEY}
ENV VITE_AUTH_DOMAIN=${VITE_AUTH_DOMAIN}
ENV VITE_PROJECT_ID=${VITE_PROJECT_ID}
ENV VITE_STORAGE_BUCKET=${VITE_STORAGE_BUCKET}
ENV VITE_MESSAGING_SENDER_ID=${VITE_MESSAGING_SENDER_ID}
ENV VITE_APP_ID=${VITE_APP_ID}
ENV VITE_NODE_ENV=${VITE_NODE_ENV}
ENV VITE_APP_API_ENDPOINT=${VITE_APP_API_ENDPOINT}

WORKDIR /app

USER root


RUN npm cache clean --force && npm install -g serve --verbose




# Copy package.json and install production dependencies only
COPY ./package*.json ./
COPY ./tsconfig.json ./
COPY ./vite.config.ts ./
COPY . .

# Install dependencies, serve, and build
RUN npm install -g serve \
    && npm install --legacy-peer-deps \
    && npm run build --verbose \
    && echo "current location is: $(pwd)"


# -- END
# Runtime stage
FROM node:20.9.0 AS runtime_stage

WORKDIR /app
USER root

  
COPY ./package*.json ./
COPY ./tsconfig.json ./
COPY ./vite.config.ts ./

COPY --from=build_stage /app/dist /app/dist   
RUN ls /app/dist

# copy the build (dist) and install --only=production
RUN npm install --legacy-peer-deps --only=production \
    && npm install -g serve --verbose



# Expose the default port
EXPOSE 80


# Start the static server
# exec without sh
CMD ["serve", "-s", "dist", "-l", "80"]

./server/Dockerfile


FROM node:20.9.0 AS build

# Set build-time arguments (available during build)
ARG MONGO_CONN
ARG DB_NAME
ARG JWT_SECRET
ARG ORIGIN
ARG PORT
ARG NODE_ENV=production
ARG SERVER_DOMAIN

# Set the runtime environment variables
ENV MONGO_CONN=${MONGO_CONN}
ENV DB_NAME=${DB_NAME}
ENV JWT_SECRET=${JWT_SECRET}
ENV ORIGIN=${ORIGIN}
ENV PORT=${PORT}
ENV NODE_ENV=${NODE_ENV}
ENV SERVER_DOMAIN=${SERVER_DOMAIN}

# Set the working directory
WORKDIR /app

COPY ./package*.json ./
# Copy the rest of the project
COPY . .

RUN npm install --omit=dev \
    && npm run build --verbose \
    && ls -alh /app/dist


# Expose the port
EXPOSE 8000

# Start the application
CMD ["node", "--trace-warnings", "dist/index.js"]