Dockerfile 2.52 KB
# vibe_erp — single shipping image (architecture spec section 10).
#
# This produces ghcr.io/vibeerp/vibe-erp:<tag>: one Spring Boot fat-jar,
# one mounted volume at /opt/vibe-erp, one mandatory dependency
# (PostgreSQL). Customer extensions live OUTSIDE the image.

# ─── Stage 1: build ────────────────────────────────────────────────────
# NOTE: this stage assumes ./gradlew and gradle/wrapper/* exist at the
# repo root. They are generated by Gradle itself (not hand-written) and
# will be added before anyone tries to build this image.
FROM eclipse-temurin:21-jdk-alpine AS build

# Node + npm are required for the :web Gradle subproject's npm-based
# Vite build. The bootJar wires the SPA bundle into Spring Boot's
# classpath:/static/ via processResources, so a clean container build
# of `:distribution:bootJar` transitively runs `:web:npmInstall` and
# `:web:npmBuild` and needs npm on PATH. Apk's nodejs/npm packages
# track v22.x on Alpine 3.21, which Vite 5 + React 18 are happy with.
RUN apk add --no-cache nodejs npm

WORKDIR /workspace
COPY . .

RUN chmod +x ./gradlew \
 && ./gradlew :distribution:bootJar --no-daemon

# ─── Stage 2: runtime ──────────────────────────────────────────────────
FROM eclipse-temurin:21-jre-alpine AS runtime

# Non-root user — never run the JVM as root inside the container.
RUN addgroup -S vibeerp -g 10001 \
 && adduser -S -u 10001 -G vibeerp vibeerp

# Customer-mounted volume layout from architecture spec section 10.
RUN mkdir -p /opt/vibe-erp/config \
             /opt/vibe-erp/plugins \
             /opt/vibe-erp/i18n-overrides \
             /opt/vibe-erp/files \
             /opt/vibe-erp/logs \
 && chown -R vibeerp:vibeerp /opt/vibe-erp \
 && mkdir -p /app \
 && chown -R vibeerp:vibeerp /app

COPY --from=build --chown=vibeerp:vibeerp \
     /workspace/distribution/build/libs/vibe-erp.jar /app/vibe-erp.jar

WORKDIR /app

ENV VIBEERP_PLUGINS_DIR=/opt/vibe-erp/plugins \
    VIBEERP_FILES_DIR=/opt/vibe-erp/files

EXPOSE 8080
VOLUME ["/opt/vibe-erp"]

USER vibeerp

HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
  CMD wget -q -O /dev/null http://localhost:8080/actuator/health || exit 1

ENTRYPOINT ["java", \
            "-XX:+UseContainerSupport", \
            "-XX:MaxRAMPercentage=75", \
            "-Dfile.encoding=UTF-8", \
            "-jar", "/app/vibe-erp.jar"]