From 5011f80fc49a1aec73d86fdbc978c8d88eeeab7c Mon Sep 17 00:00:00 2001 From: RKWojs Date: Sat, 4 Oct 2025 20:52:39 +0200 Subject: [PATCH] feat: Add timezone configuration for Docker to ensure correct time handling in production and development environments --- DEPLOYMENT_TIMEZONE_FIX.md | 129 ++++++++++++++++++++++++++++++ DOCKER_TIMEZONE_FIX.md | 156 +++++++++++++++++++++++++++++++++++++ Dockerfile | 4 + Dockerfile.dev | 4 + docker-compose.prod.yml | 1 + docker-compose.yml | 1 + 6 files changed, 295 insertions(+) create mode 100644 DEPLOYMENT_TIMEZONE_FIX.md create mode 100644 DOCKER_TIMEZONE_FIX.md diff --git a/DEPLOYMENT_TIMEZONE_FIX.md b/DEPLOYMENT_TIMEZONE_FIX.md new file mode 100644 index 0000000..b2ab5ef --- /dev/null +++ b/DEPLOYMENT_TIMEZONE_FIX.md @@ -0,0 +1,129 @@ +# Quick Deployment Guide - Timezone Fix + +## For Production Server + +1. **SSH into your server** where Docker is running + +2. **Navigate to project directory** + ```bash + cd /path/to/panel + ``` + +3. **Pull latest code** (includes timezone fixes) + ```bash + git pull origin main + ``` + +4. **Stop running containers** + ```bash + docker-compose -f docker-compose.prod.yml down + ``` + +5. **Rebuild Docker images** (this is critical - it bakes in the timezone configuration) + ```bash + docker-compose -f docker-compose.prod.yml build --no-cache + ``` + +6. **Start containers** + ```bash + docker-compose -f docker-compose.prod.yml up -d + ``` + +7. **Verify timezone is correct** + ```bash + # Check container timezone + docker-compose -f docker-compose.prod.yml exec app date + # Should show Polish time with CEST/CET timezone + + # Example output: + # Sat Oct 4 19:45:00 CEST 2025 + ``` + +8. **Test the fix** + - Post a new note at a known time (e.g., 19:45) + - Verify it displays the same time (19:45) + - Test both project notes and task notes + +## What Changed + +### Code Changes +- ✅ Fixed `datetime('now', 'localtime')` in all database queries +- ✅ Updated display formatters to use Europe/Warsaw timezone +- ✅ Fixed note display in components + +### Docker Changes (Critical!) +- ✅ Set `ENV TZ=Europe/Warsaw` in Dockerfile +- ✅ Configured system timezone in containers +- ✅ Added TZ environment variable to docker-compose files + +## Why Rebuild is Necessary + +The timezone configuration is **baked into the Docker image** during build time: +- `ENV TZ=Europe/Warsaw` - Set during image build +- `RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime` - Executed during image build + +Just restarting containers (`docker-compose restart`) will **NOT** apply these changes! + +## Troubleshooting + +### If times are still wrong after deployment: + +1. **Verify you rebuilt the images** + ```bash + docker images | grep panel + # Check the "CREATED" timestamp - should be recent + ``` + +2. **Check if container has correct timezone** + ```bash + docker-compose -f docker-compose.prod.yml exec app date + ``` + Should show Polish time, not UTC! + +3. **Check SQLite is using correct time** + ```bash + docker-compose -f docker-compose.prod.yml exec app node -e "const db = require('better-sqlite3')('./data/database.sqlite'); console.log(db.prepare(\"SELECT datetime('now', 'localtime') as time\").get());" + ``` + Should show current Polish time + +4. **Force rebuild if needed** + ```bash + docker-compose -f docker-compose.prod.yml down + docker system prune -f + docker-compose -f docker-compose.prod.yml build --no-cache + docker-compose -f docker-compose.prod.yml up -d + ``` + +## Expected Behavior After Fix + +### Before Fix (Docker in UTC): +``` +User posts note at 10:30 Poland time +→ Docker sees 08:30 UTC as "local time" +→ SQLite stores: 08:30 +→ Display shows: 08:30 ❌ (2 hours off!) +``` + +### After Fix (Docker in Europe/Warsaw): +``` +User posts note at 10:30 Poland time +→ Docker sees 10:30 Poland time as "local time" +→ SQLite stores: 10:30 +→ Display shows: 10:30 ✅ (correct!) +``` + +## Important Notes + +1. **Old notes**: Notes created before this fix may still show incorrect times (they were stored in UTC) +2. **New notes**: All new notes after deployment will show correct times +3. **Audit logs**: Continue to work correctly (they always used ISO format) +4. **Zero downtime**: Can't achieve - need to stop/rebuild/start containers + +## Quick Check Command + +After deployment, run this one-liner to verify everything: +```bash +docker-compose -f docker-compose.prod.yml exec app sh -c 'date && node -e "console.log(new Date().toLocaleString(\"pl-PL\"))"' +``` + +Both outputs should show the same Polish time! diff --git a/DOCKER_TIMEZONE_FIX.md b/DOCKER_TIMEZONE_FIX.md new file mode 100644 index 0000000..a77d6d9 --- /dev/null +++ b/DOCKER_TIMEZONE_FIX.md @@ -0,0 +1,156 @@ +# Docker Timezone Configuration Fix + +## Problem +Even after fixing the SQLite `datetime('now', 'localtime')` calls, notes posted at 10:00 still showed as 08:00 when running in Docker. + +## Root Cause +**Docker containers run in UTC timezone by default!** + +When using `datetime('now', 'localtime')` in SQLite: +- On local Windows machine: Uses Windows timezone (Europe/Warsaw) → ✅ Correct +- In Docker container: Uses container timezone (UTC) → ❌ Wrong by 2 hours + +Example: +``` +User posts at 10:00 Poland time (UTC+2) +↓ +Docker container thinks local time is 08:00 UTC +↓ +SQLite datetime('now', 'localtime') stores: 08:00 +↓ +Display shows: 08:00 (wrong!) +``` + +## Solution +Set the Docker container timezone to Europe/Warsaw + +### 1. Updated Dockerfile (Production) + +```dockerfile +# Use Node.js 22.11.0 as the base image +FROM node:22.11.0 + +# Set timezone to Europe/Warsaw (Polish timezone) +ENV TZ=Europe/Warsaw +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# ... rest of Dockerfile +``` + +### 2. Updated Dockerfile.dev (Development) + +```dockerfile +# Use Node.js 22.11.0 as the base image +FROM node:22.11.0 + +# Set timezone to Europe/Warsaw (Polish timezone) +ENV TZ=Europe/Warsaw +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# ... rest of Dockerfile +``` + +### 3. Updated docker-compose.yml (Development) + +```yaml +environment: + - NODE_ENV=development + - TZ=Europe/Warsaw +``` + +### 4. Updated docker-compose.prod.yml (Production) + +```yaml +environment: + - NODE_ENV=production + - TZ=Europe/Warsaw + - NEXTAUTH_SECRET=... + - NEXTAUTH_URL=... +``` + +## How to Apply + +### Option 1: Rebuild Docker Images +```bash +# Stop containers +docker-compose down + +# Rebuild images +docker-compose build --no-cache + +# Start containers +docker-compose up -d +``` + +### Option 2: For Production Deployment +```bash +# Pull latest code with fixes +git pull + +# Rebuild production image +docker-compose -f docker-compose.prod.yml build --no-cache + +# Restart +docker-compose -f docker-compose.prod.yml up -d +``` + +## Verification + +After rebuilding and restarting, verify timezone inside container: + +```bash +# Check timezone +docker exec -it date +# Should show: Sat Oct 4 19:00:00 CEST 2025 + +# Check Node.js sees correct timezone +docker exec -it node -e "console.log(new Date().toLocaleString('pl-PL', {timeZone: 'Europe/Warsaw'}))" +# Should show current Polish time + +# Check SQLite sees correct timezone +docker exec -it node -e "const db = require('better-sqlite3')('./data/database.sqlite'); console.log(db.prepare(\"SELECT datetime('now', 'localtime')\").get());" +# Should show current Polish time +``` + +## Why This Works + +1. **TZ Environment Variable**: Tells all processes (including Node.js and SQLite) what timezone to use +2. **Symlink /etc/localtime**: Updates system timezone for the entire container +3. **echo TZ > /etc/timezone**: Ensures the timezone persists + +Now when SQLite uses `datetime('now', 'localtime')`: +- Container local time is 10:00 Poland time +- SQLite stores: 10:00 +- Display shows: 10:00 ✅ + +## Important Notes + +1. **Must rebuild images**: Just restarting containers is not enough - the timezone configuration is baked into the image +2. **All existing data**: Old notes will still show incorrect times (they were stored in UTC) +3. **New notes**: Will now display correctly +4. **DST handling**: Europe/Warsaw automatically handles Daylight Saving Time transitions + +## Alternative Approach (Not Recommended) + +Instead of changing container timezone, you could: +1. Store everything in UTC (like audit logs do with ISO format) +2. Always convert on display + +But this requires more code changes and the current approach is simpler and more maintainable. + +## Files Modified + +1. `Dockerfile` - Added TZ configuration +2. `Dockerfile.dev` - Added TZ configuration +3. `docker-compose.yml` - Added TZ environment variable +4. `docker-compose.prod.yml` - Added TZ environment variable + +## Testing Checklist + +After deployment: +- [ ] Container shows correct date/time with `docker exec date` +- [ ] Post a new note at known time (e.g., 10:30) +- [ ] Verify note displays the same time (10:30) +- [ ] Check both project notes and task notes +- [ ] Verify audit logs still work correctly +- [ ] Check task timestamps (date_started, date_completed) diff --git a/Dockerfile b/Dockerfile index 018dd1e..894d6a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,10 @@ # Use Node.js 22.11.0 as the base image FROM node:22.11.0 +# Set timezone to Europe/Warsaw (Polish timezone) +ENV TZ=Europe/Warsaw +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + # Install git RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* diff --git a/Dockerfile.dev b/Dockerfile.dev index 7a9e61b..74f11ef 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,6 +1,10 @@ # Use Node.js 22.11.0 as the base image FROM node:22.11.0 +# Set timezone to Europe/Warsaw (Polish timezone) +ENV TZ=Europe/Warsaw +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + # Install git for development RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index ed535cc..e7b6901 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -16,6 +16,7 @@ services: - ./uploads:/app/public/uploads environment: - NODE_ENV=production + - TZ=Europe/Warsaw - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:-your-secret-key-generate-a-strong-random-string-at-least-32-characters} - NEXTAUTH_URL=${NEXTAUTH_URL:-https://panel2.wastpol.pl} - AUTH_TRUST_HOST=true diff --git a/docker-compose.yml b/docker-compose.yml index fed2ecd..311ac50 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,3 +13,4 @@ services: - ./data:/app/data environment: - NODE_ENV=development + - TZ=Europe/Warsaw