# 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 -p ``` 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 :/app/public/content/permits ./permits_backup docker cp :/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/. :/app/public/content/permits docker cp ./uploads_backup/. :/app/public/content/uploads ``` ## Troubleshooting ### Docker Logs View container logs: ```bash docker logs ``` ### 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