FROM node:20-alpine AS base FROM base as dev_dep RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app WORKDIR /home/node/app # --- dependencies --- COPY --chown=node:node package*.json ./ COPY --chown=node:node backend/package*.json ./backend/ COPY --chown=node:node frontend/package*.json ./frontend/ USER node RUN npm install --include=dev FROM base as dep RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app WORKDIR /home/node/app # --- dependencies --- COPY --chown=node:node package*.json ./ COPY --chown=node:node backend/package*.json ./backend/ COPY --chown=node:node frontend/package*.json ./frontend/ USER node RUN npm install --omit=dev # # === BUILDER === # FROM base as build RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app WORKDIR /home/node/app COPY --from=dev_dep /home/node/app/ ./ COPY --chown=node:node . . # --- build frontend --- RUN npm -w frontend run build # --- build backend --- RUN npx -w backend prisma generate RUN npm -w backend run build # # === RUNNER === # FROM base as run WORKDIR /home/node/app COPY --from=dep /home/node/app/ ./ COPY package*.json docker-start.sh ./ # --- prepare frontend --- RUN mkdir -p frontend COPY --from=build /home/node/app/frontend/dist ./frontend/ # --- prepare server --- RUN mkdir -p backend COPY --from=build /home/node/app/backend/package.json ./backend/ COPY --from=build /home/node/app/backend/prisma ./backend/prisma COPY --from=build /home/node/app/backend/dist ./backend/dist # --- finalize --- RUN npx -w backend prisma generate # set runtime env variables ENV PORT 3000 ENV NODE_ENV production ENV SERVE_FRONTEND /home/node/app/frontend EXPOSE 3000 ENTRYPOINT [ "/bin/sh" ] CMD [ "./docker-start.sh" ]