From 514c72a4fa41ff4d1bfef3aebb1fa77f2d3c7925 Mon Sep 17 00:00:00 2001 From: Joshua Ryder Date: Thu, 6 Nov 2025 08:16:41 -0500 Subject: [PATCH] fix: Resolve Docker volume permissions for SQLite database MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed SQLITE_READONLY errors by implementing proper volume permission handling in Docker container. The issue occurred because Docker volumes are mounted with root ownership, preventing the non-root nuxt user from writing to the database. Solution: - Added docker-entrypoint.sh script to handle permission fixes - Container starts as root to fix /app/data permissions - Uses su-exec to drop privileges to nuxt user after fixing permissions - Maintains security by running application as non-root user This allows the SQLite database to be properly created and modified while keeping the container secure with non-root execution. Fixes: - "attempt to write a readonly database" errors - Session cleanup failures - Rate limit cleanup failures - Password reset cleanup failures - Admin credential generation on first launch 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- Dockerfile | 16 ++++++++++------ docker-entrypoint.sh | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 docker-entrypoint.sh diff --git a/Dockerfile b/Dockerfile index e93fc7d..3253abf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,8 +54,8 @@ FROM node:20-alpine AS runtime WORKDIR /app -# Install dumb-init for proper signal handling -RUN apk add --no-cache dumb-init +# Install dumb-init and su-exec for proper signal handling and user switching +RUN apk add --no-cache dumb-init su-exec # Create non-root user for security RUN addgroup -g 1001 -S nodejs && \ @@ -66,11 +66,15 @@ COPY --from=builder --chown=nuxt:nodejs /app/.output ./.output COPY --from=builder --chown=nuxt:nodejs /app/node_modules ./node_modules COPY --from=builder --chown=nuxt:nodejs /app/package.json ./package.json +# Copy entrypoint script +COPY docker-entrypoint.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + # Create data directory for SQLite database with proper permissions RUN mkdir -p /app/data && chown -R nuxt:nodejs /app/data -# Switch to non-root user -USER nuxt +# Don't switch to non-root user yet - entrypoint will handle it +# This allows the entrypoint to fix volume permissions first # Expose port EXPOSE 3000 @@ -88,6 +92,6 @@ ENV NUXT_PORT=3000 HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \ CMD node -e "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" || exit 1 -# Use dumb-init to properly handle signals -ENTRYPOINT ["dumb-init", "--"] +# Use custom entrypoint to handle permissions and user switching +ENTRYPOINT ["dumb-init", "--", "docker-entrypoint.sh"] CMD ["node", ".output/server/index.mjs"] diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..5908967 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -e + +# Ensure data directory exists and has correct permissions +# This is needed because Docker volumes may be mounted with root ownership +if [ ! -d /app/data ]; then + mkdir -p /app/data +fi + +# If running as root, fix permissions and switch to nuxt user +if [ "$(id -u)" = "0" ]; then + chown -R nuxt:nodejs /app/data + exec su-exec nuxt "$@" +else + # Already running as nuxt user + exec "$@" +fi