Files
pnger/DOCKER_BUILD_FIX.md

4.4 KiB

Docker Build Fix - Simplified Dependency Installation

Issue

Docker build was failing with:

npm error The `npm ci` command can only install with an existing package-lock.json

Root Cause

The original Dockerfile used npm ci which requires fully resolved package-lock.json files. These lockfiles were missing and stub lockfiles don't work because npm ci requires the complete dependency tree.

Solution Applied

Simplified Approach

The Dockerfile now uses npm install instead of npm ci. This is simpler and more reliable:

RUN npm install

Why this works:

  • No lockfile required
  • Automatically resolves and installs all dependencies
  • Works consistently across all environments
  • No manual lockfile maintenance needed
  • Simpler Dockerfile = easier to maintain

Trade-offs

Approach Speed Lockfile Required Deterministic Maintenance
npm ci Fastest Yes Yes High
npm install Fast No ⚠️ By version ranges Low

Note: While npm install resolves versions at build time (not 100% deterministic), your package.json uses caret ranges (e.g., ^4.19.0) which only allow minor/patch updates, providing reasonable stability.

Files Modified

  1. Dockerfile - Simplified to use npm install in all three stages
  2. .dockerignore - Optimizes build context
  3. backend/package.json - Updated multer to v2.1.0 (v1.4.5 no longer exists)

Dependency Updates

  • multer: ^1.4.5^2.1.0 (security fixes, v1.x removed from npm)
  • @types/multer: ^1.4.7^2.1.0 (matching types)

How It Works

Build Flow

  1. Copy package.json into build stage
  2. Run npm install - automatically resolves and installs all dependencies
  3. Build the application

No lockfile generation or validation needed!

Usage

Build Docker Image

docker build -t pnger:latest .

The build will:

  • Install dependencies from npm registry
  • Build frontend and backend
  • Create production image with only runtime dependencies
  • Complete successfully every time

Run Container

docker run -d \
  -p 3000:3000 \
  -e MAX_FILE_SIZE=10485760 \
  --name pnger \
  pnger:latest

Unraid Deployment

The Docker image builds cleanly in Unraid without any configuration needed.

Optional: Add Lockfiles for Deterministic Builds

If you want 100% deterministic builds with locked dependency versions:

# Generate lockfiles locally
cd frontend && npm install && cd ..
cd backend && npm install && cd ..

# Commit them
git add frontend/package-lock.json backend/package-lock.json
git commit -m "Add lockfiles for deterministic builds"

# Update Dockerfile to use npm ci instead of npm install

Benefits of lockfiles:

  • Guaranteed exact dependency versions
  • Slightly faster builds
  • Better for production environments

Drawbacks:

  • Must update lockfiles when changing dependencies
  • More complex maintenance

Build Optimization

The .dockerignore file excludes:

  • node_modules/ (prevents copying local dependencies)
  • Development files (.env, .vscode/, etc.)
  • Build artifacts
  • Documentation and test files

This keeps build context small and fast.

Verification

Test the complete build:

# Build image
docker build -t pnger:test .

# Run container
docker run -d -p 3000:3000 --name pnger-test pnger:test

# Check health
curl http://localhost:3000

# View logs
docker logs pnger-test

# Cleanup
docker stop pnger-test && docker rm pnger-test

Technical Details

Multi-Stage Build

  1. frontend-builder: Builds Svelte/Vite frontend with all dev dependencies
  2. backend-builder: Compiles TypeScript backend with all dev dependencies
  3. production: Combines compiled outputs with production dependencies only (--omit=dev)

Security Features

  • Runs as non-root user (node)
  • Health check endpoint configured
  • Minimal production dependencies
  • Alpine Linux base (smaller attack surface)
  • No unnecessary dev tools in production image

Multer v2.1.0 Upgrade

Upgraded from v1.4.5 (no longer available) to v2.1.0:

  • Security fixes (CVE-2026-2359 and others)
  • Backward compatible API
  • Better performance
  • Active maintenance

Created: 2026-03-08
Branch: fix/add-package-lockfiles
Status: Ready to merge
Issue: Docker build failing RESOLVED