feat: add production deployment baseline

This commit is contained in:
2026-08-28 08:56:12 +03:00
parent b91bc98611
commit bf0b6ff070
11 changed files with 133 additions and 8 deletions

View File

@@ -0,0 +1,8 @@
# Absolute path on the production host containing minjust-normalized/.
DATA_ROOT=/volume1/docker/akyldash/data
BACKEND_PORT=8080
SEARCH_INDEX=akyldash-fragments-current
OPENSEARCH_MEM_LIMIT=4g
OPENSEARCH_JAVA_OPTS=-Xms2g -Xmx2g
# Generate with: openssl rand -hex 32
REVIEW_SECRET=replace-with-a-random-secret

View File

@@ -0,0 +1,11 @@
FROM python:3.12-slim
WORKDIR /app
COPY backend /app/backend
ENV PYTHONPATH=/app/backend
EXPOSE 8080
CMD ["python", "-m", "search.api", "--host", "0.0.0.0", "--port", "8080", "--url", "http://opensearch:9200", "--index", "akyldash-fragments-current", "--data", "/app/data/minjust-normalized", "--reviews-db", "/app/data/search-reviews.sqlite3"]
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/review', timeout=3)"]

View File

@@ -0,0 +1,3 @@
FROM opensearchproject/opensearch:3.7.0
RUN /usr/share/opensearch/bin/opensearch-plugin install --batch analysis-icu

View File

@@ -0,0 +1,37 @@
# Production deployment
This compose project runs the Search API and its private OpenSearch node. It
binds the API only to `127.0.0.1`; publish it through an authenticated reverse
proxy or VPN. OpenSearch is not published outside the compose network.
The current compose intentionally disables the OpenSearch security plugin to
match the existing API client. Keep both services on a private host/network
until authenticated OpenSearch support is implemented.
## First deployment
1. Copy this directory to the host with the repository source.
2. Copy `.env.example` to `.env`, set an absolute `DATA_ROOT`, and replace
`REVIEW_SECRET` with a random value. Do not commit `.env`.
3. Put the normalized dataset under `$DATA_ROOT/minjust-normalized/`.
4. Check the rendered configuration:
```bash
docker compose --env-file .env -f compose.yaml config
```
5. Start the services:
```bash
docker compose --env-file .env -f compose.yaml up -d --build
docker compose --env-file .env -f compose.yaml ps
curl -fsS http://127.0.0.1:${BACKEND_PORT:-8080}/review >/dev/null
```
6. Load the versioned index and switch its alias only after the import and
validation succeed. Back up `DATA_ROOT` and the `opensearch-data` volume
before the first import.
This is a deployment baseline, not a public internet exposure recipe. TLS,
authentication, backups, monitoring, and a production OpenSearch security
configuration must be provided by the host reverse proxy/operations setup.

View File

@@ -0,0 +1,64 @@
services:
opensearch:
build:
context: ../..
dockerfile: deploy/production/Dockerfile.opensearch
restart: unless-stopped
environment:
discovery.type: single-node
bootstrap.memory_lock: "true"
DISABLE_SECURITY_PLUGIN: "true"
OPENSEARCH_JAVA_OPTS: ${OPENSEARCH_JAVA_OPTS:--Xms2g -Xmx2g}
mem_limit: ${OPENSEARCH_MEM_LIMIT:-4g}
expose:
- "9200"
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- opensearch-data:/usr/share/opensearch/data
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:9200/_cluster/health || exit 1"]
interval: 30s
timeout: 10s
retries: 10
backend:
build:
context: ../..
dockerfile: deploy/production/Dockerfile.backend
restart: unless-stopped
environment:
REVIEW_SECRET: ${REVIEW_SECRET:?set REVIEW_SECRET in .env}
command:
- python
- -m
- search.api
- --host
- 0.0.0.0
- --port
- "8080"
- --url
- http://opensearch:9200
- --index
- ${SEARCH_INDEX:-akyldash-fragments-current}
- --data
- /app/data/minjust-normalized
- --reviews-db
- /app/data/search-reviews.sqlite3
- --review-secret
- ${REVIEW_SECRET}
ports:
- "127.0.0.1:${BACKEND_PORT:-8080}:8080"
depends_on:
opensearch:
condition: service_healthy
volumes:
- ${DATA_ROOT:?set DATA_ROOT in .env}:/app/data
volumes:
opensearch-data: