diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..393d4c6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.sh text eol=lf +docker-entrypoint.sh text eol=lf diff --git a/Dockerfile b/Dockerfile index 850a570..4a0508b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,8 +35,8 @@ WORKDIR /app ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 -# Only install runtime deps (sqlite, curl for healthcheck) -RUN apk add --no-cache sqlite-libs curl && \ +# Only install runtime deps (sqlite, curl for healthcheck, su-exec for entrypoint) +RUN apk add --no-cache sqlite-libs curl su-exec && \ addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 nextjs @@ -54,11 +54,14 @@ COPY --from=builder /app/src/lib/schema_features.sql ./src/lib/schema_features.s # Data directory with proper permissions RUN mkdir -p /app/data && chown -R nextjs:nodejs /app/data +# Copy entrypoint +COPY docker-entrypoint.sh /app/docker-entrypoint.sh +RUN chmod +x /app/docker-entrypoint.sh + ENV DATA_DIR="/app/data" VOLUME ["/app/data"] -# Switch to non-root user -USER nextjs +# Run as root initially so entrypoint can fix volume permissions, then drops to nextjs EXPOSE 3000 ENV PORT=3000 @@ -67,4 +70,4 @@ ENV HOSTNAME="0.0.0.0" HEALTHCHECK --interval=30s --timeout=3s --start-period=15s --retries=3 \ CMD curl -f http://localhost:3000/api/health || exit 1 -CMD ["node", "server.js"] \ No newline at end of file +ENTRYPOINT ["/app/docker-entrypoint.sh"] \ No newline at end of file diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..458020c --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# Ensure data directory exists and is writable +mkdir -p /app/data + +# Fix ownership if running as root (e.g., when host volume is root-owned) +if [ "$(id -u)" = "0" ]; then + chown -R nextjs:nodejs /app/data + exec su-exec nextjs node server.js +else + exec node server.js +fi