# ── Stage 1: Build frontend ─────────────────────────────────────────────────── FROM node:20-alpine AS frontend-build WORKDIR /app/frontend COPY frontend/package*.json ./ RUN npm ci COPY frontend/ ./ RUN npm run build # ── Stage 2: Build backend ──────────────────────────────────────────────────── FROM gradle:8-jdk21-alpine AS backend-build WORKDIR /app/backend COPY backend/build.gradle.kts backend/settings.gradle.kts ./ COPY backend/gradle ./gradle RUN gradle dependencies --no-daemon --quiet || true COPY backend/src ./src RUN gradle bootJar --no-daemon -x test # ── Stage 3: Final all-in-one image ─────────────────────────────────────────── FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y \ nginx \ postgresql \ supervisor \ openjdk-21-jre-headless \ && rm -rf /var/lib/apt/lists/* # PostgreSQL data directory RUN mkdir -p /var/lib/postgresql/data && chown -R postgres:postgres /var/lib/postgresql # Copy frontend static files COPY --from=frontend-build /app/frontend/dist /usr/share/nginx/html # Copy backend JAR RUN mkdir -p /app COPY --from=backend-build /app/backend/build/libs/*.jar /app/app.jar # Copy Nginx config (internal — backend is on localhost:8080) COPY nginx/nginx.allinone.conf /etc/nginx/nginx.conf # Copy Supervisor config COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf # Copy entrypoint COPY docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh EXPOSE 6969 ENTRYPOINT ["/entrypoint.sh"]