feat: Add timezone configuration for Docker to ensure correct time handling in production and development environments

This commit is contained in:
2025-10-04 20:52:39 +02:00
parent 9357c2e0b9
commit 5011f80fc4
6 changed files with 295 additions and 0 deletions

129
DEPLOYMENT_TIMEZONE_FIX.md Normal file
View File

@@ -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!

156
DOCKER_TIMEZONE_FIX.md Normal file
View File

@@ -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 <container_name> date
# Should show: Sat Oct 4 19:00:00 CEST 2025
# Check Node.js sees correct timezone
docker exec -it <container_name> 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 <container_name> 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 <container> 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)

View File

@@ -1,6 +1,10 @@
# Use Node.js 22.11.0 as the base image # Use Node.js 22.11.0 as the base image
FROM node:22.11.0 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 # Install git
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*

View File

@@ -1,6 +1,10 @@
# Use Node.js 22.11.0 as the base image # Use Node.js 22.11.0 as the base image
FROM node:22.11.0 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 # Install git for development
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*

View File

@@ -16,6 +16,7 @@ services:
- ./uploads:/app/public/uploads - ./uploads:/app/public/uploads
environment: environment:
- NODE_ENV=production - NODE_ENV=production
- TZ=Europe/Warsaw
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET:-your-secret-key-generate-a-strong-random-string-at-least-32-characters} - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:-your-secret-key-generate-a-strong-random-string-at-least-32-characters}
- NEXTAUTH_URL=${NEXTAUTH_URL:-https://panel2.wastpol.pl} - NEXTAUTH_URL=${NEXTAUTH_URL:-https://panel2.wastpol.pl}
- AUTH_TRUST_HOST=true - AUTH_TRUST_HOST=true

View File

@@ -13,3 +13,4 @@ services:
- ./data:/app/data - ./data:/app/data
environment: environment:
- NODE_ENV=development - NODE_ENV=development
- TZ=Europe/Warsaw