# Multi-stage Dockerfile for Bitip GeoIP Service # Stage 1: Build application FROM node:24.9-alpine3.21 AS builder WORKDIR /app # Copy workspace configuration COPY .npmrc .npmrc COPY package*.json ./ # Copy workspace package files COPY src/backend/package*.json ./src/backend/ COPY src/frontend/package*.json ./src/frontend/ # Install all dependencies (including devDependencies for build) RUN npm ci RUN rm -f .npmrc # Copy source code COPY src/ ./src/ # Copy content files needed for build COPY content ./content # Build both frontend and backend ARG APP_SUBFOLDER="" ENV VITE_BASE_PATH=${APP_SUBFOLDER} RUN npm run build # Stage 2: Production image FROM node:24.9-alpine3.21 # Build arguments for versioning ARG CREATED_AT=unknown ARG APP_VERSION=1.0.0 ARG GIT_REVISION=unknown # OCI Image labels LABEL org.opencontainers.image.authors="Tudor Stanciu " \ org.opencontainers.image.vendor="Toodle HomeLab" \ org.opencontainers.image.url="https://github.com/your-username/bitip" \ org.opencontainers.image.source="https://github.com/your-username/bitip" \ org.opencontainers.image.documentation="https://github.com/your-username/bitip/blob/main/README.md" \ org.opencontainers.image.licenses="Proprietary" \ org.opencontainers.image.title="Bitip GeoIP Service" \ org.opencontainers.image.description="Modern GeoIP lookup service with REST API and interactive web interface" \ org.opencontainers.image.created="${CREATED_AT}" \ org.opencontainers.image.version="${APP_VERSION}" \ org.opencontainers.image.revision="${GIT_REVISION}" # Set version environment variables (accessible at runtime) ENV APP_VERSION=${APP_VERSION} \ CREATED_AT=${CREATED_AT} \ GIT_REVISION=${GIT_REVISION} \ NODE_ENV=production # Install dumb-init for proper signal handling and wget for healthcheck RUN apk add --no-cache dumb-init wget # Create app directory WORKDIR /app # Create non-root user RUN addgroup -g 1001 -S nodejs && \ adduser -S bitip -u 1001 # Copy workspace configuration COPY package*.json ./ # Copy backend workspace package files COPY src/backend/package*.json ./src/backend/ # Install production dependencies only (for backend) RUN npm ci --only=production --workspace=bitip-backend && \ npm cache clean --force # Copy built artifacts from builder COPY --from=builder /app/dist ./dist # Copy content files needed at runtime COPY --from=builder /app/content ./content # Create directory for MaxMind databases RUN mkdir -p /usr/share/maxmind && \ chown -R bitip:nodejs /usr/share/maxmind # Change ownership of app directory RUN chown -R bitip:nodejs /app # Switch to non-root user USER bitip # Expose port EXPOSE 5172 # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:5172/api/health || exit 1 # Start the application ENTRYPOINT ["dumb-init", "--"] CMD ["node", "dist/backend/server.js"]