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
- Dockerfile - Simplified to use
npm installin all three stages - .dockerignore - Optimizes build context
- 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
- Copy package.json into build stage
- Run npm install - automatically resolves and installs all dependencies
- 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
- frontend-builder: Builds Svelte/Vite frontend with all dev dependencies
- backend-builder: Compiles TypeScript backend with all dev dependencies
- 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