Corporate proxy (Zscaler) causes npm to fail inside Docker builds with 'Exit handler never called' error. This approach builds frontend on host where npm works, then copies pre-built dist/ into Docker image. New files: - Dockerfile.prebuilt: Single-stage build, copies frontend/dist - docker-compose.prebuilt.yml: Uses Dockerfile.prebuilt - .dockerignore.prebuilt: Allows frontend/dist to be included - start-docker-quick.sh: Quick restart without rebuild - DOCKER-PREBUILT-APPROACH.md: Documents workaround and comparison Benefits: - Builds in 2-3 minutes (not 15+) - Works behind corporate proxy - Simpler to debug - Faster iteration Trade-off: Requires npm on host, two-step build process For production: CI/CD builds frontend + image, pushes to registry
2.6 KiB
2.6 KiB
Docker Pre-Built Frontend Approach
Problem: Zscaler corporate proxy causes npm to fail inside Docker builds with "Exit handler never called" error.
Solution: Build frontend on host (where npm works), copy pre-built dist/ into Docker image.
Quick Start
# 1. Build frontend on host
cd frontend
npm ci
npm run build
# 2. Build Docker image (uses pre-built dist/)
cd ..
docker compose -f docker-compose.prebuilt.yml build
# 3. Start services
docker compose -f docker-compose.prebuilt.yml up -d
# 4. Initialize (first time only)
docker compose -f docker-compose.prebuilt.yml exec api flask db upgrade
docker compose -f docker-compose.prebuilt.yml exec api bash /app/scripts/bootstrap-plugins.sh
# 5. Access
https://localhost:5001
Files
Dockerfile.prebuilt- Simplified Dockerfile without npm builddocker-compose.prebuilt.yml- Uses Dockerfile.prebuilt.dockerignore.prebuilt- Allows frontend/dist to be copied
Why This Works
Normal Dockerfile:
- Multi-stage build
- Stage 1: Node 20 runs
npm ciandnpm run build - Stage 2: Copies built frontend from stage 1
- PROBLEM: npm fails inside Docker with Zscaler proxy
Pre-Built Approach:
- Build frontend on Windows host (npm works here)
- Single-stage Dockerfile copies pre-built
frontend/dist/ - Only installs Python dependencies
- FASTER: 2-3 minutes vs 15+ minutes
Trade-offs
Pros:
- Avoids corporate proxy issues
- Much faster builds (no npm in container)
- Frontend build errors visible immediately
- Can iterate on frontend without rebuilding container
Cons:
- Requires npm on host machine
- Two-step build process
- frontend/dist must be in version control OR built before deployment
For Production (CI/CD)
# GitHub Actions / Jenkins example
- name: Build frontend
run: |
cd frontend
npm ci
npm run build
- name: Build Docker image
run: |
docker build -f Dockerfile.prebuilt -t shopdb:${{ github.sha }} .
- name: Push to registry
run: |
docker push shopdb:${{ github.sha }}
Comparison
| Approach | Build Time | Corporate Proxy | Complexity | Production Ready |
|---|---|---|---|---|
| Multi-stage Dockerfile | 15+ min | ❌ Fails | High | ❌ No |
| Pre-built frontend | 2-3 min | ✅ Works | Medium | ⚠️ Yes (with CI/CD) |
| Pre-built images from registry | 30 sec | ✅ Works | Low | ✅ Yes |
Next Steps
For true production deployment:
- Set up CI/CD to build frontend + Docker image
- Push to container registry
- Sites pull pre-built images
- No build step at deployment site