# Docker Compose Deployment Guide

This guide provides step-by-step instructions for deploying TaskFlow using Docker Compose.

## Prerequisites

- Docker Engine 20.10 or later
- Docker Compose 2.0 or later
- At least 1GB free disk space

## Quick Start

### 1. Create Environment File

Copy the example environment file and customize it:

```bash
cp .env.example .env
```

### 2. Configure Environment Variables

Edit the `.env` file with your settings:

```env
# Required: Set a secure database password
POSTGRES_PASSWORD=your_secure_password_here

# Optional: Customize these if needed
NODE_ENV=production
PORT=5000
POSTGRES_USER=taskflow
POSTGRES_DB=taskflow
```

### 3. Start the Application

```bash
docker-compose up -d
```

### 4. Verify Deployment

Check that both services are running:

```bash
docker-compose ps
```

You should see both `taskflow-app` and `taskflow-db` with status "Up".

### 5. Access the Application

Open your browser and navigate to:
```
http://localhost:5000
```

Or if deployed on a server:
```
http://your-server-ip:5000
```

## Environment Variables Reference

### Required Variables

| Variable | Description | Example |
|----------|-------------|---------|
| `POSTGRES_PASSWORD` | Database password (MUST be changed from default) | `MySecurePass123!` |

### Optional Variables

| Variable | Description | Default | Notes |
|----------|-------------|---------|-------|
| `NODE_ENV` | Application environment | `production` | Use `production` for deployment |
| `PORT` | Application port | `5000` | Change if port 5000 is already in use |
| `POSTGRES_USER` | Database username | `taskflow` | Can be customized |
| `POSTGRES_DB` | Database name | `taskflow` | Can be customized |
| `POSTGRES_PORT` | Internal database port | `5432` | Usually no need to change |

### Auto-Generated Variables

These are automatically set by docker-compose and don't need configuration:

- `DATABASE_URL` - Full PostgreSQL connection string
- `PGHOST` - Database hostname
- `PGUSER` - Database username (from POSTGRES_USER)
- `PGPASSWORD` - Database password (from POSTGRES_PASSWORD)
- `PGDATABASE` - Database name (from POSTGRES_DB)
- `PGPORT` - Database port (from POSTGRES_PORT)

## Changing the Port

If port 5000 is already in use, you have two options:

### Option 1: Change Application Port (Recommended)

Edit `.env`:
```env
PORT=8080
```

Edit `docker-compose.yml`:
```yaml
services:
  app:
    ports:
      - "8080:8080"  # Change both ports
```

### Option 2: Map to Different External Port

Edit `docker-compose.yml` only:
```yaml
services:
  app:
    ports:
      - "8080:5000"  # External:Internal
```

Then access at `http://localhost:8080`

## Security Best Practices

### 1. Strong Database Password

**Never use the default password in production!**

Generate a strong password:
```bash
# On Linux/Mac
openssl rand -base64 32

# Or use a password manager
```

### 2. Restrict Network Access

If running on a server, use a firewall to restrict access:

```bash
# Example: Allow only from specific IP
sudo ufw allow from 192.168.1.0/24 to any port 5000
```

### 3. Use HTTPS in Production

For production deployments, place TaskFlow behind a reverse proxy with SSL:

- Nginx
- Traefik
- Caddy

Example Nginx configuration:
```nginx
server {
    listen 443 ssl;
    server_name taskflow.yourdomain.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
```

## Common Operations

### View Logs

```bash
# All services
docker-compose logs -f

# App only
docker-compose logs -f app

# Database only
docker-compose logs -f db
```

### Restart Services

```bash
# Restart all
docker-compose restart

# Restart app only
docker-compose restart app
```

### Stop Services

```bash
# Stop but keep data
docker-compose stop

# Stop and remove containers (data persists)
docker-compose down

# Stop and remove everything including data
docker-compose down -v
```

### Update Application

```bash
# Pull latest changes
git pull

# Rebuild and restart
docker-compose up -d --build
```

### Check Service Health

```bash
# Check container status
docker-compose ps

# Check app health endpoint
curl http://localhost:5000/api/health

# Should return: {"status":"ok"}
```

## Database Management

### Backup Database

```bash
docker-compose exec db pg_dump -U taskflow taskflow > backup.sql
```

### Restore Database

```bash
docker-compose exec -T db psql -U taskflow taskflow < backup.sql
```

### Access Database Console

```bash
docker-compose exec db psql -U taskflow taskflow
```

### View Database Data

```bash
# Connect to database
docker-compose exec db psql -U taskflow taskflow

# List tables
\dt

# Query tasks
SELECT * FROM tasks;

# Query labels
SELECT * FROM labels;

# Exit
\q
```

## Troubleshooting

### Vite Module Error

If you see an error like:
```
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite'
```

**Solution**: This has been fixed in the latest version. Make sure you're using the updated Dockerfile that compiles server files separately. See [DOCKER-FIX.md](./DOCKER-FIX.md) for technical details.

**Quick fix**:
1. Rebuild your Docker image with the latest Dockerfile
2. Redeploy with `docker-compose up -d --build`

### Container Won't Start

**Check logs:**
```bash
docker-compose logs app
```

**Common issues:**
- Port already in use: Change PORT in `.env`
- Database not ready: Wait 10-20 seconds and check again
- Permission issues: Check file permissions on project directory

### Database Connection Failed

**Check database is running:**
```bash
docker-compose ps db
```

**Verify DATABASE_URL:**
```bash
docker-compose exec app env | grep DATABASE_URL
```

**Test database connection:**
```bash
docker-compose exec db pg_isready -U taskflow
```

### Application Shows Errors

**Check environment variables:**
```bash
docker-compose config
```

**Restart with fresh build:**
```bash
docker-compose down
docker-compose up -d --build
```

### Data Not Persisting

Make sure the database volume exists:
```bash
docker volume ls | grep taskflow
```

If missing, recreate:
```bash
docker-compose down
docker-compose up -d
```

### Port Already in Use

**Find what's using the port:**
```bash
# Linux/Mac
sudo lsof -i :5000

# Or
sudo netstat -tulpn | grep 5000
```

**Options:**
1. Stop the other service
2. Change TaskFlow port (see "Changing the Port" section)

## Production Deployment Checklist

- [ ] Change `POSTGRES_PASSWORD` to a strong, unique password
- [ ] Set `NODE_ENV=production` in `.env`
- [ ] Configure firewall rules
- [ ] Set up SSL/HTTPS reverse proxy
- [ ] Configure automated backups
- [ ] Set up monitoring/logging
- [ ] Test database backup and restore procedures
- [ ] Document your configuration
- [ ] Set up automatic updates (optional)

## Advanced Configuration

### Custom Database Configuration

Edit `docker-compose.yml` to add PostgreSQL configuration:

```yaml
services:
  db:
    environment:
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_INITDB_ARGS=-E UTF8 --locale=en_US.UTF-8
```

### Resource Limits

Limit container resources in `docker-compose.yml`:

```yaml
services:
  app:
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M
```

### External Database

To use an external PostgreSQL database instead of the container:

1. Remove the `db` service from `docker-compose.yml`
2. Set `DATABASE_URL` in `.env`:
   ```env
   DATABASE_URL=postgresql://user:password@external-host:5432/taskflow
   ```

## Deployment via CI/CD (Drone CI)

If you're using Drone CI to build and deploy your Docker images:

### Using Pre-built Images

If your CI system (like Drone) builds the image for you:

1. **Pull the image from your registry:**
   ```bash
   docker pull registry.local.nothaft.cloud/taskflow:latest
   ```

2. **Create docker-compose.yml for pre-built image:**
   ```yaml
   version: '3.8'
   
   services:
     db:
       image: postgres:16-alpine
       environment:
         - POSTGRES_USER=${POSTGRES_USER:-taskflow}
         - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
         - POSTGRES_DB=${POSTGRES_DB:-taskflow}
       volumes:
         - postgres_data:/var/lib/postgresql/data
       healthcheck:
         test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-taskflow}"]
         interval: 5s
         timeout: 5s
         retries: 5
   
     app:
       image: registry.local.nothaft.cloud/taskflow:latest  # Use pre-built image
       ports:
         - "${PORT:-5000}:5000"
       environment:
         - NODE_ENV=production
         - DATABASE_URL=postgresql://${POSTGRES_USER:-taskflow}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB:-taskflow}
         - PORT=5000
       depends_on:
         db:
           condition: service_healthy
       restart: unless-stopped
   
   volumes:
     postgres_data:
   ```

3. **Start services:**
   ```bash
   docker-compose up -d
   ```

### .drone.yml Configuration

Your `.drone.yml` file should build and push to your registry:

```yaml
kind: pipeline
type: docker
name: default

steps:
  - name: build taskflow
    image: plugins/docker
    settings:
      repo: registry.local.nothaft.cloud/taskflow
      tags: latest
      dockerfile: Dockerfile
      context: .
      registry: registry.local.nothaft.cloud
```

## Support

For issues and questions:
- Check the main [README.md](./README.md)
- Review [DEPLOYMENT.md](./DEPLOYMENT.md) for detailed deployment options
- Open an issue on the repository

## Next Steps

Once deployed:
1. Create your first tasks and labels
2. Explore calendar and kanban views
3. Try the time tracking feature
4. Set up automated backups
5. Configure HTTPS for secure access

Happy task managing! 🚀
