# Multi-stage Dockerfile for Bitip GeoIP Service # Stage 1: Build frontend FROM node:18-alpine as frontend-builder WORKDIR /app/frontend # Copy frontend package files COPY src/frontend/package*.json ./ RUN npm ci --only=production # Copy frontend source COPY src/frontend/ ./ # Build frontend RUN npm run build # Stage 2: Build backend FROM node:18-alpine as backend-builder WORKDIR /app/backend # Copy backend package files COPY src/backend/package*.json ./ COPY src/backend/tsconfig.json ./ RUN npm ci # Copy backend source COPY src/backend/ ./ # Build backend RUN npm run build # Stage 3: Production image FROM node:18-alpine # 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 variable (accessible at runtime) ENV APP_VERSION=${APP_VERSION} \ CREATED_AT=${CREATED_AT} \ GIT_REVISION=${GIT_REVISION} # Install dumb-init for proper signal handling RUN apk add --no-cache dumb-init # Create app directory WORKDIR /app # Create non-root user RUN addgroup -g 1001 -S nodejs && \ adduser -S bitip -u 1001 # Copy backend production files COPY --from=backend-builder /app/backend/dist ./dist COPY --from=backend-builder /app/backend/package*.json ./ RUN npm ci --only=production && npm cache clean --force # Copy built frontend COPY --from=frontend-builder /app/frontend/dist ./dist/frontend # Create directory for GeoIP databases RUN mkdir -p /usr/share/GeoIP && \ chown -R bitip:nodejs /usr/share/GeoIP # Change ownership of app directory RUN chown -R bitip:nodejs /app # Switch to non-root user USER bitip # Expose port EXPOSE 3000 # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD node -e "require('http').get('http://localhost:3000/api/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) }).on('error', () => { process.exit(1) })" # Start the application ENTRYPOINT ["dumb-init", "--"] CMD ["node", "dist/index.js"]