From 2735a1c161fcc2612792babe11d9a44e45b4001c Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Mon, 28 Sep 2026 14:47:53 +0200 Subject: [PATCH] deploy(backend): add prod Dockerfiles, compose stack, nginx configs, deploy scripts Multi-stage Dockerfiles for accounts-service/configs-service/gateway, a docker-compose.prod.yml wiring fresh Postgres+MinIO+the three services on a private network, nginx site templates for visual.loki-code.dev (static SPA + /api proxy) and bekend.loki-code.dev (full gateway proxy for the mod), and idempotent setup.sh/deploy.sh scripts for the VDS. Claude-Session: https://claude.ai/code/session_01F1M1Jic1wTSn4igUENynmZ --- backend/accounts-service/Dockerfile | 19 +++ backend/configs-service/Dockerfile | 19 +++ backend/deploy/deploy.sh | 29 +++++ .../deploy/nginx-bekend.loki-code.dev.conf | 14 +++ .../deploy/nginx-visual.loki-code.dev.conf | 20 +++ backend/deploy/pg-init/01-create-databases.sh | 6 + backend/deploy/setup.sh | 22 ++++ backend/docker-compose.prod.yml | 115 ++++++++++++++++++ backend/gateway/Dockerfile | 19 +++ 9 files changed, 263 insertions(+) create mode 100644 backend/accounts-service/Dockerfile create mode 100644 backend/configs-service/Dockerfile create mode 100755 backend/deploy/deploy.sh create mode 100644 backend/deploy/nginx-bekend.loki-code.dev.conf create mode 100644 backend/deploy/nginx-visual.loki-code.dev.conf create mode 100755 backend/deploy/pg-init/01-create-databases.sh create mode 100755 backend/deploy/setup.sh create mode 100644 backend/docker-compose.prod.yml create mode 100644 backend/gateway/Dockerfile diff --git a/backend/accounts-service/Dockerfile b/backend/accounts-service/Dockerfile new file mode 100644 index 0000000..2df5da2 --- /dev/null +++ b/backend/accounts-service/Dockerfile @@ -0,0 +1,19 @@ +# Build context must be backend/ (the workspace root). +FROM rust:1-slim AS builder +RUN apt-get update && apt-get install -y --no-install-recommends \ + protobuf-compiler pkg-config libssl-dev ca-certificates \ + && rm -rf /var/lib/apt/lists/* +WORKDIR /build +COPY Cargo.toml Cargo.lock ./ +COPY common ./common +COPY accounts-service ./accounts-service +COPY gateway ./gateway +COPY configs-service ./configs-service +RUN cargo build --release -p accounts-service + +FROM debian:bookworm-slim +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates libssl3 \ + && rm -rf /var/lib/apt/lists/* +COPY --from=builder /build/target/release/accounts-service /usr/local/bin/accounts-service +ENTRYPOINT ["/usr/local/bin/accounts-service"] diff --git a/backend/configs-service/Dockerfile b/backend/configs-service/Dockerfile new file mode 100644 index 0000000..25d4a02 --- /dev/null +++ b/backend/configs-service/Dockerfile @@ -0,0 +1,19 @@ +# Build context must be backend/ (the workspace root). +FROM rust:1-slim AS builder +RUN apt-get update && apt-get install -y --no-install-recommends \ + protobuf-compiler pkg-config libssl-dev ca-certificates \ + && rm -rf /var/lib/apt/lists/* +WORKDIR /build +COPY Cargo.toml Cargo.lock ./ +COPY common ./common +COPY accounts-service ./accounts-service +COPY gateway ./gateway +COPY configs-service ./configs-service +RUN cargo build --release -p configs-service + +FROM debian:bookworm-slim +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates libssl3 \ + && rm -rf /var/lib/apt/lists/* +COPY --from=builder /build/target/release/configs-service /usr/local/bin/configs-service +ENTRYPOINT ["/usr/local/bin/configs-service"] diff --git a/backend/deploy/deploy.sh b/backend/deploy/deploy.sh new file mode 100755 index 0000000..cafe9d9 --- /dev/null +++ b/backend/deploy/deploy.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# Idempotent redeploy for LoVisual. Run as: /opt/lovisual/deploy.sh +set -euo pipefail + +REPO_DIR=/opt/lovisual +FRONTEND_ROOT=/var/www/visual.loki-code.dev/html + +cd "$REPO_DIR" +git pull --ff-only + +echo "==> Building & (re)starting backend services" +cd "$REPO_DIR/backend" +docker compose -f docker-compose.prod.yml up -d --build + +echo "==> Building frontend" +cd "$REPO_DIR/frontend" +npm ci +npm run build + +echo "==> Syncing frontend build to $FRONTEND_ROOT" +mkdir -p "$FRONTEND_ROOT" +rsync -a --delete dist/ "$FRONTEND_ROOT/" + +echo "==> Reloading nginx" +nginx -t +systemctl reload nginx + +echo "==> Done" +docker compose -f "$REPO_DIR/backend/docker-compose.prod.yml" ps diff --git a/backend/deploy/nginx-bekend.loki-code.dev.conf b/backend/deploy/nginx-bekend.loki-code.dev.conf new file mode 100644 index 0000000..099b09a --- /dev/null +++ b/backend/deploy/nginx-bekend.loki-code.dev.conf @@ -0,0 +1,14 @@ +server { + server_name bekend.loki-code.dev; + + location / { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + listen 80; +} diff --git a/backend/deploy/nginx-visual.loki-code.dev.conf b/backend/deploy/nginx-visual.loki-code.dev.conf new file mode 100644 index 0000000..c150fa3 --- /dev/null +++ b/backend/deploy/nginx-visual.loki-code.dev.conf @@ -0,0 +1,20 @@ +server { + server_name visual.loki-code.dev; + root /var/www/visual.loki-code.dev/html; + index index.html; + + location /api/ { + proxy_pass http://127.0.0.1:8080/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location / { + try_files $uri /index.html; + } + + listen 80; +} diff --git a/backend/deploy/pg-init/01-create-databases.sh b/backend/deploy/pg-init/01-create-databases.sh new file mode 100755 index 0000000..cc97be2 --- /dev/null +++ b/backend/deploy/pg-init/01-create-databases.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "postgres" <<-EOSQL + SELECT 'CREATE DATABASE accounts_db OWNER lovisual' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'accounts_db')\gexec + SELECT 'CREATE DATABASE configs_db OWNER lovisual' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'configs_db')\gexec +EOSQL diff --git a/backend/deploy/setup.sh b/backend/deploy/setup.sh new file mode 100755 index 0000000..9e09902 --- /dev/null +++ b/backend/deploy/setup.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# One-time first-install setup for LoVisual on this VDS. Safe to re-run. +# Assumes: repo already cloned to /opt/lovisual, backend/.env already created (chmod 600). +set -euo pipefail + +REPO_DIR=/opt/lovisual + +echo "==> nginx site configs" +cp "$REPO_DIR/backend/deploy/nginx-visual.loki-code.dev.conf" /etc/nginx/sites-available/visual.loki-code.dev +cp "$REPO_DIR/backend/deploy/nginx-bekend.loki-code.dev.conf" /etc/nginx/sites-available/bekend.loki-code.dev +ln -sf /etc/nginx/sites-available/visual.loki-code.dev /etc/nginx/sites-enabled/visual.loki-code.dev +ln -sf /etc/nginx/sites-available/bekend.loki-code.dev /etc/nginx/sites-enabled/bekend.loki-code.dev +mkdir -p /var/www/visual.loki-code.dev/html +nginx -t +systemctl reload nginx + +echo "==> certbot" +certbot --nginx -d visual.loki-code.dev --non-interactive --agree-tos -m mauhhhh7@gmail.com --redirect || true +certbot --nginx -d bekend.loki-code.dev --non-interactive --agree-tos -m mauhhhh7@gmail.com --redirect || true + +echo "==> First deploy" +"$REPO_DIR/backend/deploy/deploy.sh" diff --git a/backend/docker-compose.prod.yml b/backend/docker-compose.prod.yml new file mode 100644 index 0000000..87f8b2f --- /dev/null +++ b/backend/docker-compose.prod.yml @@ -0,0 +1,115 @@ +name: lovisual + +networks: + lovisual-internal: + driver: bridge + +volumes: + lovisual-pg-data: + lovisual-minio-data: + +services: + postgres: + image: postgres:16 + restart: unless-stopped + environment: + POSTGRES_USER: lovisual + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: postgres + volumes: + - lovisual-pg-data:/var/lib/postgresql/data + - ./deploy/pg-init:/docker-entrypoint-initdb.d:ro + networks: [lovisual-internal] + healthcheck: + test: ["CMD-SHELL", "pg_isready -U lovisual"] + interval: 5s + timeout: 5s + retries: 10 + + minio: + image: minio/minio + restart: unless-stopped + command: server /data + environment: + MINIO_ROOT_USER: ${S3_ACCESS_KEY} + MINIO_ROOT_PASSWORD: ${S3_SECRET_KEY} + volumes: + - lovisual-minio-data:/data + networks: [lovisual-internal] + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 5s + timeout: 5s + retries: 10 + + minio-init: + image: minio/mc + depends_on: + minio: + condition: service_healthy + networks: [lovisual-internal] + entrypoint: > + /bin/sh -c " + mc alias set local http://minio:9000 $${S3_ACCESS_KEY} $${S3_SECRET_KEY} && + (mc mb local/$${S3_BUCKET} || true) && + echo bucket-ready + " + environment: + S3_ACCESS_KEY: ${S3_ACCESS_KEY} + S3_SECRET_KEY: ${S3_SECRET_KEY} + S3_BUCKET: ${S3_BUCKET} + + accounts-service: + build: + context: . + dockerfile: accounts-service/Dockerfile + restart: unless-stopped + depends_on: + postgres: + condition: service_healthy + minio-init: + condition: service_completed_successfully + env_file: .env + environment: + DATABASE_URL: postgres://lovisual:${POSTGRES_PASSWORD}@postgres:5432/accounts_db + S3_ENDPOINT: http://minio:9000 + PORT: 8081 + GRPC_PORT: 50051 + networks: [lovisual-internal] + + configs-service: + build: + context: . + dockerfile: configs-service/Dockerfile + restart: unless-stopped + depends_on: + postgres: + condition: service_healthy + accounts-service: + condition: service_started + env_file: .env + environment: + CONFIGS_DATABASE_URL: postgres://lovisual:${POSTGRES_PASSWORD}@postgres:5432/configs_db + ACCOUNTS_GRPC_URL: http://accounts-service:50051 + CONFIGS_PORT: 8082 + networks: [lovisual-internal] + + gateway: + build: + context: . + dockerfile: gateway/Dockerfile + restart: unless-stopped + depends_on: + accounts-service: + condition: service_started + configs-service: + condition: service_started + env_file: .env + environment: + GATEWAY_PORT: 8080 + ACCOUNTS_HTTP_URL: http://accounts-service:8081 + ACCOUNTS_GRPC_URL: http://accounts-service:50051 + CONFIGS_HTTP_URL: http://configs-service:8082 + ports: + - "127.0.0.1:8080:8080" + networks: [lovisual-internal] diff --git a/backend/gateway/Dockerfile b/backend/gateway/Dockerfile new file mode 100644 index 0000000..67d2f15 --- /dev/null +++ b/backend/gateway/Dockerfile @@ -0,0 +1,19 @@ +# Build context must be backend/ (the workspace root). +FROM rust:1-slim AS builder +RUN apt-get update && apt-get install -y --no-install-recommends \ + protobuf-compiler pkg-config libssl-dev ca-certificates \ + && rm -rf /var/lib/apt/lists/* +WORKDIR /build +COPY Cargo.toml Cargo.lock ./ +COPY common ./common +COPY accounts-service ./accounts-service +COPY gateway ./gateway +COPY configs-service ./configs-service +RUN cargo build --release -p gateway + +FROM debian:bookworm-slim +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates libssl3 \ + && rm -rf /var/lib/apt/lists/* +COPY --from=builder /build/target/release/gateway /usr/local/bin/gateway +ENTRYPOINT ["/usr/local/bin/gateway"]