# Deployment Guide for MWitnessing Application

This guide covers four deployment methods:
1. **Standard Docker Deployment** - Builds a complete Docker image with your code
2. **Runtime Git Clone Deployment** - Clones the repository at container startup (current method)
3. **Webhook-Based Deployment** - Automatically deploys when code is pushed to the repository
4. **Registry-Based Deployment** - Builds and pushes images to a private Docker registry

## Method 1: Standard Docker Deployment (Recommended)

This method builds a complete Docker image containing your application code, providing:
- Faster container startup
- No dependency on Git repository during runtime
- Better security (no Git credentials in environment variables)
- Standard Docker deployment workflow

### Prerequisites
- Docker and Docker Compose installed on the host machine
- Access to the application source code

### Deployment Steps

1. **Build and start the containers**:
   ```bash
   cd /path/to/project
   docker-compose -f _deploy/standard-docker-compose.yml up -d
   ```

2. **Access the application**:
   - Web application: http://localhost:3000
   - Database admin: http://localhost:8080

3. **Update the application**:
   ```bash
   # Pull the latest code
   git pull
   
   # Rebuild and restart
   docker-compose -f _deploy/standard-docker-compose.yml up -d --build
   ```

### Configuration

Edit the environment variables in `_deploy/standard-docker-compose.yml` before deployment:
- `DATABASE_URL`: Database connection string
- `NEXTAUTH_URL`: Public URL of your application
- `NEXTAUTH_SECRET`: Secret for NextAuth.js encryption

### Persistent Data

The following Docker volumes are used to persist data:
- `app_permits`: Stores permit files
- `app_uploads`: Stores uploaded files
- `app_logs`: Stores application logs
- `db_data`: Stores database data

## Method 2: Runtime Git Clone Deployment (Legacy)

This method clones the repository at container startup, which is the current deployment method.

### Prerequisites
- Docker and Docker Compose installed on the host machine
- Git repository access credentials

### Deployment Steps

1. **Configure environment variables**:
   Edit the Docker Compose file (e.g., `_deploy/deoloy.azure.production.yml`) to set:
   - `GIT_USERNAME`: Username for Git repository access
   - `GIT_PASSWORD`: Password for Git repository access
   - `GIT_BRANCH`: Branch to deploy (default: main)
   - `UPDATE_CODE_FROM_GIT`: Set to "true" to enable Git clone

2. **Start the containers**:
   ```bash
   docker-compose -f _deploy/deoloy.azure.production.yml up -d
   ```

3. **Update the application**:
   - Updates happen automatically when containers restart
   - Force an update by restarting the container:
     ```bash
     docker-compose -f _deploy/deoloy.azure.production.yml restart nextjs-app
     ```

### How It Works

The `entrypoint.sh` script:
1. Clones the repository at container startup
2. Backs up important directories like `permits` and `uploads`
3. Syncs new code from the repository
4. Restores or merges the backed-up directories
5. Rebuilds the application

## Method 3: Webhook-Based Deployment (Recommended for Production)

This method uses Gitea webhooks to automatically deploy changes when code is pushed to the repository, providing:
- Automated continuous deployment
- No manual intervention needed for updates
- Immediate deployment of changes
- Preservation of user-uploaded content

### Prerequisites
- Docker and Docker Compose installed on the host machine
- Gitea repository with webhook capabilities
- Server with port 9000 (or your configured port) accessible to Gitea

### Setup Steps

1. **Build and start the webhook service**:
   ```bash
   cd /path/to/project
   mkdir -p _deploy/webhook
   cp _deploy/webhook-receiver.js _deploy/webhook/
   cp _deploy/webhook-deploy.sh _deploy/webhook/
   docker-compose -f _deploy/webhook-docker-compose.yml up -d
   ```

2. **Configure Gitea webhook**:
   - Go to your repository settings in Gitea
   - Navigate to "Webhooks" > "Add Webhook" > "Gitea"
   - Set Target URL: `http://your-server-ip:9000/webhook`
   - Set Content Type: `application/json`
   - Set Secret: Same as `WEBHOOK_SECRET` in webhook-docker-compose.yml
   - Select "Just the push event"
   - Select "Active"
   - Click "Add Webhook"

3. **Test the webhook**:
   - Make a change to your repository and push it
   - The webhook service will receive the event and trigger a deployment
   - Check logs: `docker logs mwitnessing-webhook`

### Configuration

Edit the environment variables in `_deploy/webhook-docker-compose.yml` before deployment:
- `WEBHOOK_SECRET`: Secret for authenticating webhook requests (must match Gitea webhook secret)
- `ALLOWED_BRANCHES`: Comma-separated list of branches that trigger deployments
- `ALLOWED_REPOSITORIES`: Comma-separated list of repositories to monitor
- `GIT_USERNAME` and `GIT_PASSWORD`: Credentials for Git repository access

### How It Works

1. **Webhook Receiver**:
   - Listens for push events from Gitea
   - Validates the webhook signature using the shared secret
   - Triggers the deployment script when a valid push event is received

2. **Deployment Script**:
   - Clones the repository at the specified branch
   - Checks if dependencies have changed (package.json, Dockerfile, etc.)
   - Performs a full rebuild if necessary, or just updates code and restarts
   - Preserves user-uploaded content during deployment

3. **Intelligent Updates**:
   - Intelligently determines whether a full rebuild is needed
   - Only rebuilds Docker images when necessary (package.json changes, etc.)
   - Preserves data in volumes across deployments

### Monitoring and Maintenance

- **View logs**:
  ```bash
  docker logs mwitnessing-webhook
  ```

- **Manual trigger**:
  ```bash
  docker exec mwitnessing-webhook /app/webhook-deploy.sh main
  ```

- **Update webhook code**:
  ```bash
  # Edit webhook files, then:
  docker-compose -f _deploy/webhook-docker-compose.yml up -d --build
  ```

## Method 4: Registry-Based Deployment

This method involves building Docker images locally or in a CI/CD pipeline, pushing them to your private Docker registry (`docker.d-popov.com`), and then deploying using those pre-built images.

### Prerequisites
- Docker and Docker Compose installed on the build machine
- Access to your private Docker registry at `docker.d-popov.com`
- Authentication configured for the Docker registry

### Build and Push Process

1. **Log in to the Docker registry**:
   ```bash
   docker login docker.d-popov.com -u <username> -p <password>
   ```

2. **Build the Docker image**:
   ```bash
   # Navigate to the project root
   cd /path/to/project
   
   # Build the image with the jwpw tag
   docker build -t docker.d-popov.com/jwpw:latest -f _deploy/prod.Dockerfile .
   ```

3. **Push the image to the registry**:
   ```bash
   docker push docker.d-popov.com/jwpw:latest
   ```

4. **Tag with version (optional but recommended)**:
   ```bash
   # Tag with version number
   docker tag docker.d-popov.com/jwpw:latest docker.d-popov.com/jwpw:v1.0.0
   
   # Push the versioned tag
   docker push docker.d-popov.com/jwpw:v1.0.0
   ```

### Deployment Process

1. **On the server, create or update your deployment YAML file**:
   Create or edit a file like `_deploy/deploy.production.yml`:

   ```yaml
   version: "3"
   services:
     nextjs-app:
       hostname: jwpw-app-production
       image: docker.d-popov.com/jwpw:latest
       volumes:
         - /mnt/docker_volumes/pw-prod/app/public/content/uploads/:/app/public/content/uploads
         - /mnt/docker_volumes/pw-prod/app/logs:/app/logs
         - /mnt/docker_volumes/pw-prod/app/public/content/permits/:/app/public/content/permits
       environment:
         - APP_ENV=production
         - NODE_ENV=production
         - TZ=Europe/Sofia
         - DATABASE=mysql://username:password@db:3306/database_name
       restart: always
       networks:
         - infrastructure_default
         - default
     # Add database service if needed
   ```

2. **Deploy using Docker Compose**:
   ```bash
   docker-compose -f _deploy/deploy.production.yml up -d
   ```

3. **Update the deployment** (when a new image is available):
   ```bash
   # Pull the latest image
   docker pull docker.d-popov.com/jwpw:latest
   
   # Restart the service
   docker-compose -f _deploy/deploy.production.yml up -d
   ```

### Continuous Integration/Continuous Deployment (CI/CD)

This method is ideal for integration with CI/CD pipelines. For example, you could set up a GitHub Actions or GitLab CI pipeline that:

1. Builds the Docker image
2. Runs tests
3. Pushes the image to your private registry
4. Triggers a deployment on your server

### Advantages of Registry-Based Deployment

- **Consistent environments**: The exact same image is used in all environments
- **Faster deployments**: No building on the production server
- **Rollback capability**: Easy to roll back to a previous version by specifying an older tag
- **Better separation of concerns**: Build and deployment processes are separated
- **Audit trail**: Registry maintains a history of image versions

### Current Use

This method is currently used for your staging environment, as seen in `_deploy/deoloy.azure.staging.yml`, which references `docker.d-popov.com/jwpw:latest` as the image source.

### Using the Automated Build Script

For convenience, an automated build script is included that handles the building and pushing process:

1. **Make the script executable**:
   ```bash
   chmod +x _deploy/build-and-push.sh
   ```

2. **Run the script** (from the project root):
   ```bash
   # Build and push with 'latest' tag
   ./_deploy/build-and-push.sh
   
   # Build and push with specific version tag
   ./_deploy/build-and-push.sh v1.2.3
   ```

3. **What the script does**:
   - Builds the Docker image using `_deploy/prod.Dockerfile`
   - Tags the image with the specified version and 'latest'
   - Pushes both tags to your private Docker registry
   - Performs basic error checking (Docker installed, logged into registry)

This script simplifies the process of creating and publishing new versions of your application, making it easier to maintain consistent deployment practices.

## Migrating Between Methods

### From Git Clone to Standard Docker

1. Back up your data:
   ```bash
   docker cp <container_name>:/app/public/content/permits ./permits_backup
   docker cp <container_name>:/app/public/content/uploads ./uploads_backup
   ```

2. Stop the old containers:
   ```bash
   docker-compose -f _deploy/deoloy.azure.production.yml down
   ```

3. Deploy using the standard method:
   ```bash
   docker-compose -f _deploy/standard-docker-compose.yml up -d
   ```

4. Restore your data if needed:
   ```bash
   docker cp ./permits_backup/. <new_container_name>:/app/public/content/permits
   docker cp ./uploads_backup/. <new_container_name>:/app/public/content/uploads
   ```

## Troubleshooting

### Docker Logs
View container logs:
```bash
docker logs <container_name>
```

### Application Logs
Application logs are stored in:
- `/app/logs` inside the container
- The `app_logs` Docker volume

### Common Issues
- **Database connection error**: Check the `DATABASE_URL` environment variable
- **Missing files**: Check volume mappings and permissions
- **Container exits immediately**: Check the logs for startup errors 