# Docker CSS Compilation Fix ## Problem Description The frontend was completely broken in Docker/production environments - pages displayed as plain unstyled text without any CSS styling. ### Root Cause The `.dockerignore` file in `apps/frontend/` was excluding critical Tailwind CSS configuration files: - `postcss.config.js` - `tailwind.config.js` - `tailwind.config.ts` This prevented PostCSS and Tailwind CSS from compiling the CSS during Docker builds. The CSS file contained raw `@tailwind base;@tailwind components;@tailwind utilities;` directives instead of the compiled CSS. ### Why It Worked Locally Local development (`npm run dev` or `npm run build`) worked fine because: - Config files were present on the filesystem - Tailwind JIT compiler could process the directives - The compiled CSS output was ~60KB of actual CSS rules ### Why It Failed in Docker Docker builds failed because: - `.dockerignore` excluded the config files from the build context - Next.js build couldn't find `postcss.config.js` or `tailwind.config.ts` - CSS compilation was skipped entirely - The raw source CSS file was copied as-is (containing `@tailwind` directives) - Browsers couldn't interpret the `@tailwind` directives ## Solution ### 1. Frontend `.dockerignore` Fix **File**: `apps/frontend/.dockerignore` ```diff # Other .prettierrc .prettierignore .eslintrc.json .eslintignore -postcss.config.js -tailwind.config.js +# postcss.config.js # NEEDED for Tailwind CSS compilation +# tailwind.config.js # NEEDED for Tailwind CSS compilation +# tailwind.config.ts # NEEDED for Tailwind CSS compilation next-env.d.ts tsconfig.tsbuildinfo ``` **Impact**: This fix applies to: - ✅ Local Docker builds (`docker-compose.dev.yml`) - ✅ CI/CD builds (GitHub Actions `.github/workflows/ci.yml`) - ✅ Production deployments (Portainer pulls from CI/CD registry) ### 2. Additional Docker Fixes While fixing the CSS issue, we also resolved: #### Backend Docker Permissions - **Problem**: CSV file uploads failed with `EACCES: permission denied, mkdir '/app/apps'` - **Solution**: - Copy `src/` directory to production Docker image - Create `/app/src/infrastructure/storage/csv-storage/rates` with proper ownership - Add `getCsvUploadPath()` helper for Docker/dev path resolution #### Port Conflicts for Local Testing - **Problem**: Backend couldn't start because port 4000 was already in use - **Solution**: - Map to different ports in `docker-compose.dev.yml` - Backend: `4001:4000` instead of `4000:4000` - Frontend: `3001:3000` instead of `3000:3000` - Updated `CORS_ORIGIN` and `NEXT_PUBLIC_API_URL` accordingly ## How to Verify the Fix ### Local Docker Testing (Mac ARM64) ```bash # Build and start all services docker compose -f docker-compose.dev.yml up -d --build # Wait for frontend to be ready docker compose -f docker-compose.dev.yml ps # Check CSS is compiled (should show compiled CSS, not @tailwind directives) docker exec xpeditis-frontend-dev find .next/static/css -name "*.css" -exec head -c 200 {} \; # Expected output: # *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0... # (NOT: @tailwind base;@tailwind components;@tailwind utilities;) ``` **Access Points**: - Frontend: http://localhost:3001 (should show fully styled pages) - Backend API: http://localhost:4001 - MinIO Console: http://localhost:9001 (minioadmin/minioadmin) ### Production Deployment (Scaleway + Portainer) 1. **Push to preprod branch** (triggers CI/CD): ```bash git push origin preprod ``` 2. **Monitor GitHub Actions**: - Go to: https://github.com/YOUR_ORG/xpeditis/actions - Wait for "CI/CD Pipeline" to complete - Verify frontend build shows: `✓ Compiled successfully` 3. **Verify Docker Registry**: ```bash # Pull the newly built image docker pull rg.fr-par.scw.cloud/weworkstudio/xpeditis-frontend:preprod # Inspect the image docker run --rm --entrypoint sh rg.fr-par.scw.cloud/weworkstudio/xpeditis-frontend:preprod -c \ "find .next/static/css -name '*.css' -exec head -c 200 {} \;" ``` 4. **Deploy via Portainer**: - Go to Portainer: https://portainer.preprod.xpeditis.com - Stacks → xpeditis-preprod → Update the stack - Click "Pull and redeploy" - Wait for frontend container to restart 5. **Test Production Frontend**: - Visit: https://app.preprod.xpeditis.com - **Expected**: Fully styled landing page with: - Navy blue hero section - Turquoise accent colors - Proper typography (Manrope/Montserrat fonts) - Gradient backgrounds - Animations and hover effects - **NOT Expected**: Plain black text on white background ### CSS Verification Script ```bash #!/bin/bash # Test CSS compilation in Docker container CONTAINER_NAME="xpeditis-frontend-dev" echo "🔍 Checking CSS files in container..." CSS_CONTENT=$(docker exec $CONTAINER_NAME find .next/static/css -name "*.css" -exec head -c 100 {} \;) if echo "$CSS_CONTENT" | grep -q "@tailwind"; then echo "❌ FAIL: CSS contains uncompiled @tailwind directives" echo "CSS content: $CSS_CONTENT" exit 1 elif echo "$CSS_CONTENT" | grep -q "tw-border-spacing"; then echo "✅ PASS: CSS is properly compiled with Tailwind" echo "CSS preview: $CSS_CONTENT" exit 0 else echo "⚠️ UNKNOWN: Unexpected CSS content" echo "CSS content: $CSS_CONTENT" exit 2 fi ``` ## Technical Details ### Tailwind CSS Compilation Process 1. **Without config files** (broken): ``` Source: app/globals.css ↓ @tailwind base; @tailwind components; @tailwind utilities; ↓ [NO PROCESSING - config files missing] ↓ Output: Same raw directives (27KB) ↓ Browser: ❌ Cannot interpret @tailwind directives ``` 2. **With config files** (fixed): ``` Source: app/globals.css ↓ @tailwind base; @tailwind components; @tailwind utilities; ↓ PostCSS + Tailwind JIT Compiler (using tailwind.config.ts + postcss.config.js) ↓ Output: Compiled CSS (60KB+ of actual rules) ↓ Browser: ✅ Fully styled page ``` ### Docker Build Context When Docker builds an image: 1. It reads `.dockerignore` to determine which files to exclude 2. It copies the remaining files into the build context 3. Next.js build runs `npm run build` 4. Next.js looks for `postcss.config.js` and `tailwind.config.ts` 5. If found: Tailwind compiles CSS ✅ 6. If missing: Raw CSS copied as-is ❌ ## Related Files ### Configuration Files (MUST be in Docker build context) - ✅ `apps/frontend/postcss.config.js` - Tells Next.js to use Tailwind - ✅ `apps/frontend/tailwind.config.ts` - Tailwind configuration - ✅ `apps/frontend/app/globals.css` - Source CSS with @tailwind directives ### Build Files - `apps/frontend/Dockerfile` - Frontend Docker build - `apps/frontend/.dockerignore` - **CRITICAL: Must not exclude config files** - `.github/workflows/ci.yml` - CI/CD pipeline (uses apps/frontend context) - `docker/portainer-stack.yml` - Production deployment stack ### Testing Files - `docker-compose.dev.yml` - Local testing stack (Mac ARM64) ## Lessons Learned 1. **Never exclude build tool configs from Docker**: - PostCSS/Tailwind configs must be in build context - Same applies to `.babelrc`, `tsconfig.json`, etc. - Only exclude generated output, not source configs 2. **Always verify CSS compilation in Docker**: - Check actual CSS content, not just "build succeeded" - Compare file sizes (27KB raw vs 60KB compiled) - Test in a real browser, not just curl 3. **Docker build ≠ Local build**: - Local `node_modules/` has all files - Docker only has files not in `.dockerignore` - Always test Docker builds locally before deploying ## Commit Reference - **Commit**: `88f0cc9` - fix: enable Tailwind CSS compilation in Docker builds - **Branch**: `preprod` - **Date**: 2025-11-19 - **Files Changed**: - `apps/frontend/.dockerignore` - `apps/backend/Dockerfile` - `apps/backend/src/application/controllers/admin/csv-rates.controller.ts` - `docker-compose.dev.yml` ## Rollback Plan If this fix causes issues in production: ```bash # Revert the commit git revert 88f0cc9 # Or manually restore .dockerignore git show 2505a36:apps/frontend/.dockerignore > apps/frontend/.dockerignore # Push to trigger rebuild git push origin preprod ``` **Note**: This would restore the broken CSS, so only do this if the fix causes new issues. ## Future Improvements 1. **Add CSS compilation check to CI/CD**: ```yaml - name: Verify CSS compilation run: | docker run --rm $IMAGE_NAME sh -c \ "find .next/static/css -name '*.css' -exec grep -q '@tailwind' {} \; && exit 1 || exit 0" ``` 2. **Document required Docker build context files**: - Create `apps/frontend/DOCKER_REQUIRED_FILES.md` - List all files needed for successful builds 3. **Add frontend healthcheck that verifies CSS**: - Create `/api/health/css` endpoint - Check that CSS files are properly compiled - Fail container startup if CSS is broken