feat: Add timezone configuration for Docker to ensure correct time handling in production and development environments
This commit is contained in:
156
DOCKER_TIMEZONE_FIX.md
Normal file
156
DOCKER_TIMEZONE_FIX.md
Normal 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)
|
||||
Reference in New Issue
Block a user