From 0e72a1d2845a52b8ce78a72826f97218b11b72b0 Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Mon, 2 Mar 2026 14:00:54 +0300 Subject: [PATCH] Add production deployment: Dockerfile, docker-compose, deploy script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dockerfile: multi-stage build (golang:1.25-alpine → alpine:3.21), linux/amd64 - infra/mariadb: docker-compose + init SQL for reanimator DB/user - infra/reanimator: docker-compose for reanimator-api (Gitea registry) - deploy.sh: local build → push to git.mchus.pro → SSH deploy Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile | 23 +++++++++++ deploy.sh | 55 +++++++++++++++++++++++++ infra/mariadb/docker-compose.yml | 17 ++++++++ infra/mariadb/init/01_reanimator.sql | 9 ++++ infra/mariadb/mariadb.env.example | 9 ++++ infra/reanimator/docker-compose.yml | 16 +++++++ infra/reanimator/reanimator.env.example | 5 +++ 7 files changed, 134 insertions(+) create mode 100644 Dockerfile create mode 100755 deploy.sh create mode 100644 infra/mariadb/docker-compose.yml create mode 100644 infra/mariadb/init/01_reanimator.sql create mode 100644 infra/mariadb/mariadb.env.example create mode 100644 infra/reanimator/docker-compose.yml create mode 100644 infra/reanimator/reanimator.env.example diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bdecb80 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +FROM golang:1.25-alpine AS builder + +WORKDIR /build + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . +RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o reanimator-api ./cmd/reanimator-api + + +FROM alpine:3.21 + +RUN apk add --no-cache tzdata ca-certificates + +WORKDIR /app + +COPY --from=builder /build/reanimator-api ./reanimator-api +COPY --from=builder /build/migrations ./migrations + +EXPOSE 9999 + +ENTRYPOINT ["./reanimator-api"] diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..b17e5e8 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +set -euo pipefail + +IMAGE="git.mchus.pro/reanimator/core" +TAG="${1:-latest}" +DEPLOY_DIR="/appdata/reanimator" + +echo "Deploy target:" +echo " 1) local" +echo " 2) remote (SSH)" +read -rp "Choice [1/2]: " choice + +case "$choice" in + 1) + TARGET="local" + ;; + 2) + read -rp "SSH target (login@hostname): " SSH_TARGET + TARGET="ssh" + ;; + *) + echo "Invalid choice" >&2 + exit 1 + ;; +esac + +echo "==> Building and pushing $IMAGE:$TAG (linux/amd64)..." +docker buildx build --platform linux/amd64 -t "$IMAGE:$TAG" --push . + +if [ "$TARGET" = "local" ]; then + echo "==> Deploying locally..." + docker pull "$IMAGE:$TAG" + cd "$DEPLOY_DIR" + docker compose pull + docker compose up -d --remove-orphans + echo "-- Status:" + docker compose ps + echo "==> Done." +else + echo "==> Deploying on $SSH_TARGET..." + ssh "$SSH_TARGET" " + set -euo pipefail + echo '-- Pulling image...' + docker pull $IMAGE:$TAG + + echo '-- Restarting container...' + cd $DEPLOY_DIR + docker compose pull + docker compose up -d --remove-orphans + + echo '-- Status:' + docker compose ps + " + echo "==> Done." +fi diff --git a/infra/mariadb/docker-compose.yml b/infra/mariadb/docker-compose.yml new file mode 100644 index 0000000..b2bfb3a --- /dev/null +++ b/infra/mariadb/docker-compose.yml @@ -0,0 +1,17 @@ +services: + mariadb: + image: mariadb:11.4 + container_name: mariadb + restart: unless-stopped + env_file: /appdata/mariadb/mariadb.env + ports: + - "3306:3306" + volumes: + - /appdata/mariadb/data:/var/lib/mysql + - /appdata/mariadb/init:/docker-entrypoint-initdb.d:ro + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s diff --git a/infra/mariadb/init/01_reanimator.sql b/infra/mariadb/init/01_reanimator.sql new file mode 100644 index 0000000..e2ed162 --- /dev/null +++ b/infra/mariadb/init/01_reanimator.sql @@ -0,0 +1,9 @@ +CREATE DATABASE IF NOT EXISTS reanimator + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +CREATE USER IF NOT EXISTS 'reanimator'@'%' IDENTIFIED BY 'REANIMATOR_PASSWORD_PLACEHOLDER'; + +GRANT ALL PRIVILEGES ON reanimator.* TO 'reanimator'@'%'; + +FLUSH PRIVILEGES; diff --git a/infra/mariadb/mariadb.env.example b/infra/mariadb/mariadb.env.example new file mode 100644 index 0000000..55d6d1d --- /dev/null +++ b/infra/mariadb/mariadb.env.example @@ -0,0 +1,9 @@ +# Скопировать на сервер: /appdata/mariadb/mariadb.env +# Заменить все значения на реальные + +MARIADB_ROOT_PASSWORD=changeme_root + +# Пользователь для reanimator (должен совпадать с паролем в init/01_reanimator.sql) +MARIADB_USER=reanimator +MARIADB_PASSWORD=changeme_reanimator +MARIADB_DATABASE=reanimator diff --git a/infra/reanimator/docker-compose.yml b/infra/reanimator/docker-compose.yml new file mode 100644 index 0000000..d2a5b19 --- /dev/null +++ b/infra/reanimator/docker-compose.yml @@ -0,0 +1,16 @@ +services: + reanimator-api: + image: git.mchus.pro/reanimator/core:latest + container_name: reanimator-api + restart: unless-stopped + env_file: /appdata/reanimator/reanimator.env + ports: + - "9999:9999" + extra_hosts: + - "host.docker.internal:host-gateway" + healthcheck: + test: ["CMD-SHELL", "wget -qO- http://localhost:9999/health || exit 1"] + interval: 15s + timeout: 5s + retries: 3 + start_period: 20s diff --git a/infra/reanimator/reanimator.env.example b/infra/reanimator/reanimator.env.example new file mode 100644 index 0000000..154ab6b --- /dev/null +++ b/infra/reanimator/reanimator.env.example @@ -0,0 +1,5 @@ +# Скопировать на сервер: /appdata/reanimator/reanimator.env + +HTTP_ADDR=:9999 +DATABASE_DSN=reanimator:PASSWORD@tcp(host.docker.internal:3306)/reanimator?parseTime=true +MIGRATIONS_DIR=/app/migrations