# Deployment Production runs as a Docker container named `konturai-parser-app`, deployed from `main` by **Gitea Actions** on a self-hosted runner. > The project was migrated from GitLab CI to Gitea in August 2026. The GitLab pipeline > and its runner scripts have been removed; the historical description is preserved in > [archive/setup-notes/DEPLOYMENT.md](archive/setup-notes/DEPLOYMENT.md). ## Pipeline [`.gitea/workflows/deploy.yml`](../.gitea/workflows/deploy.yml) triggers on every push to `main` and delegates to a host script: ```yaml on: push: branches: [main] jobs: deploy: runs-on: self-hosted steps: - name: Deploy run: /usr/local/bin/konturai-deploy.sh marketing-parser ``` `konturai-deploy.sh` lives on the deployment host, not in this repository. It is shared across KonturAI services and is responsible for syncing the checkout, building the image and recreating the container. Note that this workflow does **not** run the test suite — it deploys directly. Run `./mvnw clean verify` locally before pushing to `main`. ## Container [`Dockerfile`](../Dockerfile) is a two-stage build: 1. `maven:3.9.9-eclipse-temurin-21` resolves dependencies and runs `mvn clean install -DskipTests`. 2. `eclipse-temurin:21-jre-jammy` receives the jar and runs it as the non-root `appuser`, with `-XX:+HeapDumpOnOutOfMemoryError` writing to `/dumps`. Because stage 1 does `COPY . .`, anything required at build time must be present in the checkout on the host — including `src/main/resources/keys/google-key.json`, which is not in version control. See [configuration.md](configuration.md#the-google-service-account-key). ## Compose [`deployment/docker-compose.server.yml`](../deployment/docker-compose.server.yml) defines the production service: - Reads all configuration from `../.env.production` (**not** in version control). - Joins the pre-existing external Docker network `common_network` under the alias `parser-service`, so sibling KonturAI services can reach it by name. - `restart: unless-stopped`. - Maps `host.docker.internal` to the host gateway. No ports are published to the host — traffic arrives through the shared network. ## Server-side environment `.env.production` sits next to the checkout on the deployment host and supplies every variable listed in [`.env.example`](../.env.example). **The application will not start if a required variable is missing** — this is intentional, see [configuration.md](configuration.md#secret-handling). Manual operations on the host: ```bash cd /deployment docker compose ps # status docker compose logs -f parser-service # follow logs docker compose up -d --build # rebuild and recreate docker compose restart parser-service # pick up .env.production changes ``` ## Verifying a deploy ```bash docker compose ps # container is Up docker compose logs --tail=100 parser-service # no placeholder-resolution errors curl -fsS http://parser-service:8080/api/parser/health # from inside common_network ``` A failure to resolve a `${VAR}` placeholder appears immediately in the logs and names the missing variable. ## Rollback The deploy script builds from the synced checkout, so rolling back means checking out the previous commit on the host and rebuilding: ```bash cd git checkout cd deployment && docker compose up -d --build ```