mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-03 04:40:09 +00:00
0d64b90fd0
Fix PUID/PGID collision issues by using gosu to run services with exact UID:GID. Changes include: - Added redis-start.sh and updated app-start.sh to load /etc/environment, determine PUID/PGID, and invoke gosu "$PUID:$PGID" to start Redis and the Next.js app (with verification and fallbacks). - Updated entrypoint.sh to persist PUID/PGID into /etc/environment, document the gosu approach, and adjust startup messaging. - Updated supervisord.conf to run the new startup wrappers as root (so they can use gosu) instead of running processes directly as specific users. - Dockerfile updated to install gosu and copy the redis-start.sh wrapper. - Documentation updated (deployment/unified.md) describing the PUID collision bug, the root cause, and the gosu-based fix. This resolves cases where PUID collides with existing system users (e.g., nobody) which previously caused processes to run with the wrong GID and produce EACCES errors.
125 lines
4.0 KiB
Plaintext
125 lines
4.0 KiB
Plaintext
# ReadMeABook - Unified Dockerfile
|
|
# Single container with PostgreSQL, Redis, and Next.js app
|
|
# Designed for easy deployment with minimal configuration
|
|
|
|
# Start from debian base with node preinstalled
|
|
FROM node:20-bookworm AS base
|
|
|
|
# Re-declare build arguments after FROM (ARGs before FROM are not available after)
|
|
ARG GIT_COMMIT=unknown
|
|
ARG BUILD_DATE=unknown
|
|
|
|
# Install PostgreSQL 16 repository key
|
|
RUN apt-get update && apt-get install -y curl gnupg && \
|
|
install -d /etc/apt/keyrings && \
|
|
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /etc/apt/keyrings/postgresql.gpg && \
|
|
echo "deb [signed-by=/etc/apt/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/postgresql.list
|
|
|
|
# Install PostgreSQL, Redis, supervisord, and gosu (for reliable user switching)
|
|
RUN apt-get update && apt-get install -y \
|
|
postgresql-16 \
|
|
postgresql-client-16 \
|
|
redis-server \
|
|
supervisor \
|
|
curl \
|
|
openssl \
|
|
ffmpeg \
|
|
locales \
|
|
gosu \
|
|
&& sed -i 's/^# \(en_US.UTF-8 UTF-8\)/\1/' /etc/locale.gen \
|
|
&& locale-gen en_US.UTF-8 \
|
|
&& update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
ENV LANG=en_US.UTF-8
|
|
ENV LC_ALL=en_US.UTF-8
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy package files
|
|
COPY package.json package-lock.json* ./
|
|
COPY prisma ./prisma/
|
|
|
|
# Install ALL dependencies (including dev dependencies needed for build)
|
|
RUN npm ci && npm cache clean --force
|
|
|
|
# Copy application code (before generating Prisma to avoid overwriting)
|
|
COPY . .
|
|
|
|
# Generate Prisma client AFTER copying code (prevents stale generated files from overwriting)
|
|
ENV DATABASE_URL="postgresql://dummy:dummy@localhost:5432/dummy?schema=public"
|
|
RUN npx prisma generate
|
|
|
|
# Set version environment variables for build and runtime
|
|
ENV NEXT_PUBLIC_GIT_COMMIT=${GIT_COMMIT}
|
|
ENV NEXT_PUBLIC_BUILD_DATE=${BUILD_DATE}
|
|
ENV APP_VERSION=${GIT_COMMIT}
|
|
ENV BUILD_DATE=${BUILD_DATE}
|
|
|
|
# Build Next.js application
|
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
ENV NODE_ENV=production
|
|
ENV TURBOPACK=0
|
|
RUN npm run build
|
|
|
|
# Reorganize for standalone output
|
|
# Next.js standalone mode creates .next/standalone/ with server.js
|
|
# We need to move files to root for supervisord to find server.js
|
|
RUN cp -r .next/standalone/* . && \
|
|
cp -r .next/static ./.next/static && \
|
|
cp -r public ./public 2>/dev/null || true
|
|
|
|
# Remove dev dependencies to reduce image size
|
|
RUN npm prune --production
|
|
|
|
# Create necessary directories
|
|
RUN mkdir -p \
|
|
/var/run/postgresql \
|
|
/var/lib/postgresql/data \
|
|
/var/lib/redis \
|
|
/app/config \
|
|
/app/cache \
|
|
/downloads \
|
|
/media \
|
|
/app/.next/cache \
|
|
/var/log/supervisor
|
|
|
|
# Setup PostgreSQL
|
|
RUN chown -R postgres:postgres /var/lib/postgresql /var/run/postgresql && \
|
|
chmod 2777 /var/run/postgresql
|
|
|
|
# Setup Redis data directory
|
|
RUN chown -R redis:redis /var/lib/redis
|
|
|
|
# Setup app directories (node user)
|
|
RUN chown -R node:node /app/config /app/cache /downloads /media /app/.next/cache
|
|
|
|
# Copy supervisord configuration
|
|
COPY --chown=root:root docker/unified/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
|
|
|
# Copy entrypoint script
|
|
COPY --chown=root:root docker/unified/entrypoint.sh /entrypoint.sh
|
|
# Convert line endings (Windows CRLF -> Unix LF) and make executable
|
|
RUN sed -i 's/\r$//' /entrypoint.sh && chmod +x /entrypoint.sh
|
|
|
|
# Copy app startup wrapper
|
|
COPY --chown=root:root docker/unified/app-start.sh /app/app-start.sh
|
|
# Convert line endings and make executable
|
|
RUN sed -i 's/\r$//' /app/app-start.sh && chmod +x /app/app-start.sh
|
|
|
|
# Copy redis startup wrapper
|
|
COPY --chown=root:root docker/unified/redis-start.sh /app/redis-start.sh
|
|
# Convert line endings and make executable
|
|
RUN sed -i 's/\r$//' /app/redis-start.sh && chmod +x /app/redis-start.sh
|
|
|
|
# Expose app port
|
|
EXPOSE 3030
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
|
CMD curl -f http://localhost:3030/api/health || exit 1
|
|
|
|
# Set entrypoint
|
|
ENTRYPOINT ["/entrypoint.sh"]
|
|
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
|