Przejdź do treści
Q
QuoteNode

Installation

Aktualizacja QuoteNode

Jak sprawdzać nowe wersje, przejść na pakiet nowego wydania i bezpiecznie wycofać aktualizację.

Aktualizacja QuoteNode

QuoteNode automatycznie sprawdza dostępność nowych wydań. Gdy pojawi się nowsza wersja, panel administracyjny pokazuje powiadomienie z etykietą wydania i linkiem do informacji o zmianach.

Każde wydanie jest publikowane jako pakiet wdrożeniowy: docker-compose.yml (oraz docker-compose.coolify.yml) z obrazami wydania przypiętymi po digeście, env.example, release.json i narzędzia operator/. Aktualizacja polega na zastąpieniu pliku Compose plikiem z kolejnego pakietu. Bieżące wydanie to v0.9.8-alpha (pakiet).

Sposób aktualizacji zależy od sposobu instalacji. Lista kontrolna i polecenia poniżej dotyczą katalogu instalacji (serwer, LAN, laptop albo folder na NAS z docker-compose.yml i .env). Stos Portainer nie ma takiego katalogu: przejdź do sekcji Stos Portainer. Coolify: przejdź do sekcji Coolify.

Znany problem w v0.9.5-alpha: przykładowy zdalny cel kopii zapasowych

Plik env.example wydania v0.9.5-alpha zawiera aktywną przykładową linię BACKUP_RCLONE_REMOTE=s3:mybucket/backups. Ten zdalny cel nie jest skonfigurowany: gdy linia trafi do ustawień, każda kopia zapasowa kończy się błędem, a po nieudanym wysłaniu nie zostaje lokalne archiwum tej kopii. Ustawienia z tych przewodników nigdy jej nie zawierają; sprawdź instalację, jeśli plik .env powstał z env.example albo podczas aktualizacji dodano do niego ustawienia z tego pliku.

W katalogu instalacji zakomentuj dokładnie tę przykładową linię (prawdziwy zdalny cel pozostaje bez zmian) i odtwórz kontenery:

# Run in Bash (for example Linux, Git Bash or WSL); other shells can edit the exact placeholder manually.
(
  set -eu
  umask 077
  temporary_env="$(mktemp .env.backup-remote.XXXXXX)"
  trap 'rm -f "$temporary_env"' EXIT
  carriage_return="$(printf '\r')"
  # Match only the published placeholder, with either LF or Windows CRLF line endings.
  sample_pattern="^BACKUP_RCLONE_REMOTE=s3:mybucket/backups${carriage_return}\{0,1\}$"
  sed "s|${sample_pattern}|# &|" .env > "$temporary_env"
  if LC_ALL=C grep -Eq "^BACKUP_RCLONE_REMOTE=s3:mybucket/backups${carriage_return}?$" "$temporary_env"; then
    echo "Sample backup remote is still active; settings were not replaced." >&2
    exit 1
  else
    match_status=$?
    [ "$match_status" -eq 1 ] || exit "$match_status"
  fi
  # Keep real remote settings unchanged; publish a changed file atomically with private permissions.
  if ! cmp -s .env "$temporary_env"; then
    mv "$temporary_env" .env
  fi
  docker compose up -d
)

W Portainerze usuń zmienną stosu BACKUP_RCLONE_REMOTE, jeśli ma tę przykładową wartość, a następnie zaktualizuj stos. Definicja Coolify w v0.9.5-alpha nie przekazuje tej zmiennej do aplikacji; usuń przykładową wartość z zasobu przed aktualizacją do nowszego wydania.

Kopie zapasowe zostają wtedy w wolumenie kopii zapasowych. Uruchom kopię w panelu administratora (Admin → Security → Backup), sprawdź, czy zakończyła się powodzeniem, i zapewnij kopię poza serwerem: skonfigurowany zdalny cel rclone albo regularne kopiowanie archiwów na inną maszynę (Kopie zapasowe i odtwarzanie).

Przejście na PostgreSQL 18

Pliki Compose używają już postgres:18-alpine, więc nowe instalacje nie wymagają niczego. Jeśli wcześniejsza wersja alfa działała na PostgreSQL 16, raz przenieś dane — serwer PostgreSQL 18 nie uruchomi się na starszym katalogu danych, a aplikacja nigdy nie przepisuje go automatycznie. Skorzystaj z osobnej, bezpiecznej procedury: Migracja danych do PostgreSQL 18 (ścieżki z wiersza poleceń i tylko z interfejsu, dla każdej platformy).

Jak działa sprawdzanie wersji

Interfejs administracyjny pobiera https://quotenode.dev/releases/latest.json przy logowaniu administratora. To żądanie GET tylko do odczytu, bez uwierzytelnienia; żadne dane z Twojej instancji nie są wysyłane. Gdy manifest jest niedostępny, sprawdzenie po cichu się nie udaje, a panel działa normalnie.

Sprawdzanie i adres manifestu są częścią zbudowanego interfejsu WWW. Ustawienie VITE_RELEASE_CHECK_ENABLED lub VITE_RELEASE_MANIFEST_URL w .env albo w Coolify nie ma wpływu na wydanie; te wartości działają tylko wtedy, gdy samodzielnie budujesz obraz frontendu ze źródeł. Aby instalacja nie łączyła się z quotenode.dev, zablokuj ten adres w swojej sieci.

Lista kontrolna przed aktualizacją

Dotyczy katalogu instalacji; Portainer i Coolify mają własne sekcje poniżej.

  1. Zanotuj bieżące wydanie: release.json w katalogu instalacji albo Admin > Licencja.
  2. Skopiuj .env poza serwer — zawiera sekrety, których nie da się odtworzyć (zwłaszcza DB_ENCRYPTION_KEY).
  3. Pobierz nowy pakiet obok instalacji. Niczego, co działa, to nie zmienia:
mkdir -p ../next && cd ../next
curl -fsSLO https://quotenode.dev/releases/v0.9.8-alpha/quotenode-deploy-v0.9.8-alpha.tar.gz
tar -xzf quotenode-deploy-v0.9.8-alpha.tar.gz --strip-components=1
cd -
# Nowe lub usunięte ustawienia? Porównaj swój .env z nowym szablonem.
diff <(grep -o '^[A-Z_]*=' .env | sort) <(grep -o '^[A-Z_]*=' ../next/env.example | sort)
  1. Dopisz do .env ustawienia, których wymaga nowe wydanie (porównanie powyżej je wymienia; instalacje utworzone przed pakietami wydań: zobacz Instalacje utworzone przed pakietami wydań). Działająca instalacja jeszcze ich nie używa.
  2. Utwórz punkt kontrolny aktualizacji i zweryfikowaną kopię zapasową narzędziem nowego pakietu. Niczego, co działa, to nie zmienia, a przy pierwszym błędzie się zatrzymuje:
BACKUP_ARCHIVE_ENCRYPTION_MODE=AGE_RECIPIENT BACKUP_AGE_RECIPIENT=age1... \
  ../next/operator/upgrade.sh prepare --export-to ../quotenode-backups

Punkt kontrolny (w .quotenode-upgrade/, używany tylko przez tę instalację) zapisuje zainstalowane docker-compose.yml, .env i release.json, tożsamość działających obrazów oraz stan schematu bazy. Kopia powstaje narzędziami nowego wydania na projekcie Compose i wolumenach tej instalacji, w tym przebiegu pozostaje lokalna nawet przy skonfigurowanych kopiach zdalnych i trafia do ../quotenode-backups dopiero wtedy, gdy zgadza się jej SHA-256. Zanim przejdziesz dalej, skopiuj ten katalog poza serwer. Odbiorcę age weźmiesz z Recovery Kit (Kopie zapasowe i odtwarzanie).

  1. Jeśli kopie planowe są włączone, sprawdź też, czy ostatnia się udała (panel administracyjny).

Procedura aktualizacji

Docker Compose (serwer, LAN, laptop, folder na NAS)

Po liście kontrolnej uruchom w katalogu instalacji, aby projekt Compose i jego wolumeny pozostały te same:

../next/operator/upgrade.sh apply

upgrade.sh apply najpierw pobiera wszystkie obrazy nowego wydania i zatrzymuje się przy pierwszym błędzie: jeśli pobieranie się nie uda, instalacja działa dalej bez zmian. Dopiero potem instaluje z pakietu docker-compose.yml, release.json, env.example i operator/, uruchamia nową wersję i czeka, aż będzie zdrowa. Migracje bazy danych wykonują się automatycznie przy starcie nowego backendu. Wymagany jest Docker Compose 2.17 lub nowszy.

Stos Portainer

upgrade.sh wymaga katalogu instalacji, więc stos Portainer aktualizuje się w Portainerze:

  1. Sprawdź, czy ostatnia zaplanowana kopia zapasowa się powiodła (panel administratora), zabezpiecz wolumeny stosu narzędziem migawek lub kopii zapasowych swojej platformy i zapisz kopię bieżącej definicji stosu oraz jego zmiennych środowiskowych.
  2. Otwórz Editor stosu i zastąp definicję poniższym blokiem: adaptacją docker-compose.yml wydania dla Portainera, tym samym blokiem co w przewodniku Instalacja z Portainerem. Nie wklejaj oryginalnego pliku z pakietu: czyta .env, którego Portainer nie ma.
  3. Zachowaj nazwę stosu i jego zmienne środowiskowe (stack.env); dodaj ustawienia wymagane przez nowe wydanie (porównaj z jego env.example).
  4. Kliknij Update the stack z włączonym pobieraniem obrazów. Migracje bazy danych uruchamiają się przy starcie nowego backendu.
# Portainer Web editor adaptation of the release docker-compose.yml: env_file reads stack.env (the stack's
# environment variables) instead of .env in postgres, backend and backup-worker. Images, services, ports and
# volumes are unchanged. For a folder-based installation use the unchanged file of the release package.
x-json-file-logging: &json-file-logging
  driver: json-file
  options:
    max-size: "${DOCKER_LOG_MAX_SIZE:-10m}"
    max-file: "${DOCKER_LOG_MAX_FILE:-5}"

# ==========================================================================
# QuoteNode — standalone deployment (docker compose)
# GENERATED by scripts/render-deployment.mjs — do not edit by hand.
# Release v0.9.8-alpha (commit ff74453ca68f3c40bd86a32f0b0b813aaffc7aea, build 28); platforms: linux/amd64.
# API image:      ghcr.io/lesisty7/quotenode/quotenode-api@sha256:0ed701f952c27ea0e1db168a00de75facb231f7c6d5f6b4f0f3b77ef98d4f140
# Frontend image: ghcr.io/lesisty7/quotenode/quotenode-frontend@sha256:40a1cdc4fca5cebd9f43d34daef4ba059a88000ff08af821e199566f07260606
#
# Settings: the .env file in this directory (start from env.example, the commented catalogue of every
# setting; postgres, backend and backup-worker read it). Start: docker compose up -d
# DOMAIN: public host name for automatic HTTPS, or :80 / http://<address> for plain HTTP on a trusted LAN.
# Only the caddy entry point publishes ports (HTTP_PORT/HTTPS_PORT, default 80/443).
# Upgrades: replace this file with the next release package version; volumes keep the data.
# ==========================================================================

services:
  postgres:
    # Database (PostgreSQL 18); internal network only, data in the database volume.
    image: postgres:18-alpine@sha256:77f585114c32fbca283dc835b0596f4e52b51b4c6662d7810b2f4084f60a1873
    # JIT is off by default: for this OLTP workload most queries fall below jit_above_cost,
    # so JIT compilation rarely helps and can add latency. Set PG_JIT=on to re-enable.
    command: ["postgres", "-c", "jit=${PG_JIT:-off}"]
    env_file: stack.env
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_INITDB_ARGS: "--data-checksums"
      # postgres:18 refuses to start on a bare /var/lib/postgresql/data mount (new default layout).
      # Pin PGDATA to the legacy path so the existing volume mount keeps working; major upgrades go
      # through a logical dump/restore, never an in-place upgrade of the data directory.
      PGDATA: /var/lib/postgresql/data
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME} -d ${DB_NAME}"]
      interval: 10s
      timeout: 5s
      retries: 10
    # CPU ceilings are opt-in (*_CPUS): 0 = no ceiling, all host cores. Docker refuses a ceiling above the
    # host's core count, so a fixed default would stop the stack on smaller hosts (minimum: 2 cores).
    cpus: ${POSTGRES_CPUS:-0}
    # Ceiling, not a reservation: PG sits at tens of MB until working set/connections grow.
    # Default 512m fits the 4 GB-VM profile; raise POSTGRES_MEM_LIMIT for larger tiers.
    mem_limit: ${POSTGRES_MEM_LIMIT:-512m}
    restart: unless-stopped
    logging: *json-file-logging
    # No published host port: the database is reachable only on the internal network.

  gotenberg:
    # PDF rendering (Chromium) for the backend; internal network only, keeps no data.
    image: gotenberg/gotenberg:8@sha256:aa552cc115db488e0f0bcb07446aac13071ad51505b642c84bb894500907b42b
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:3000/health"]
      interval: 10s
      timeout: 5s
      retries: 5
    cpus: ${GOTENBERG_CPUS:-0}
    # Chromium PDF rendering: measured ~188 MiB peak rendering a real offer template, so
    # 448m keeps ~2.4x headroom. Freed budget goes to backup-worker (closer to its limit).
    mem_limit: ${GOTENBERG_MEM_LIMIT:-448m}
    restart: unless-stopped
    logging: *json-file-logging

  backend:
    # API server (Java): business logic and web jobs; uploads, PDFs and the GeoIP database live in volumes.
    image: ghcr.io/lesisty7/quotenode/quotenode-api@sha256:0ed701f952c27ea0e1db168a00de75facb231f7c6d5f6b4f0f3b77ef98d4f140
    # Time Docker gives the backend between SIGTERM and SIGKILL. 60 s = the SMTP handoff hard limit
    # (mail.handoff.deadline-ms + end-of-data-allowance-ms = 25 s) + 5 s to record its outcome + the HTTP
    # graceful drain phase (30 s). A ceiling, not a delay: an idle backend exits in seconds.
    stop_grace_period: 60s
    depends_on:
      postgres:
        condition: service_healthy
      gotenberg:
        condition: service_healthy
    env_file: stack.env
    environment:
      SPRING_PROFILES_ACTIVE: prod
      JOBS_MODE: web
      # The caddy edge below is the backend's only HTTP peer, so it is the trusted proxy by default (security
      # finding #80); without it every request would appear to come from the edge container. Override only
      # for a custom proxy chain.
      SECURITY_TRUSTED_PROXIES: ${SECURITY_TRUSTED_PROXIES:-caddy}
      BACKUP_LOCAL_DIR: /app/data/backups
    volumes:
      - backend_uploads:/app/data/uploads
      - backend_pdfs:/app/data/pdfs
      - backend_backups:/app/data/backups
      - backend_geoip:/app/data/geoip
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
      interval: 15s
      timeout: 10s
      retries: 5
      start_period: 45s
    cpus: ${BACKEND_CPUS:-0}
    # Heap auto-scales to 70% of this limit (MaxRAMPercentage); default 1536m → ~1 GB heap,
    # fits the 4 GB-VM profile. Raise BACKEND_MEM_LIMIT for heavier load (see resource docs).
    mem_limit: ${BACKEND_MEM_LIMIT:-1536m}
    restart: unless-stopped
    logging: *json-file-logging

  backup-worker:
    # Scheduled backups: same image as the backend, JOBS_MODE=backup-only; archives go to the backups volume.
    image: ghcr.io/lesisty7/quotenode/quotenode-api@sha256:0ed701f952c27ea0e1db168a00de75facb231f7c6d5f6b4f0f3b77ef98d4f140
    depends_on:
      postgres:
        condition: service_healthy
      backend:
        condition: service_healthy
    env_file: stack.env
    environment:
      SPRING_PROFILES_ACTIVE: prod
      JOBS_MODE: backup-only
      BACKUP_LOCAL_DIR: /app/data/backups
      # Worker runs pg_dump in a shell (out-of-JVM) and never does web/import heap work,
      # so it needs little heap. On this small 768m container the ~350 MB fixed non-heap
      # cost makes the global MaxRAMPercentage=70 (538 MB heap → 888 MB total) unsafe.
      # Cap heap lower so heap_max + non-heap stays well under the limit.
      JAVA_OPTS: "-XX:MaxRAMPercentage=45.0 -XX:+UseG1GC -XX:G1PeriodicGCInterval=300000"
    volumes:
      - backend_uploads:/app/data/uploads
      - backend_pdfs:/app/data/pdfs
      - backend_backups:/app/data/backups
      - backend_geoip:/app/data/geoip
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
      interval: 15s
      timeout: 10s
      retries: 5
      # JVM boots a large Spring context (CPU-bound); the grace window must outlast
      # cold start to avoid a false-unhealthy restart loop under load.
      start_period: 300s
    # CPU is a ceiling (idle cost ~0); give the worker enough to boot fast and to run
    # pg_dump + age-encryption/compression bursts without throttling. Idles near zero CPU.
    cpus: ${WORKER_CPUS:-0}
    # Default 832m: measured backup peak (JVM idle + pg_dump + tar + gzip) is ~607 MiB, so
    # this keeps a ~27% margin. Do NOT set WORKER_MEM_LIMIT below ~768m or backups risk OOM.
    mem_limit: ${WORKER_MEM_LIMIT:-832m}
    restart: unless-stopped
    logging: *json-file-logging

  frontend:
    # Web UI: the static build served by Caddy, reached through the caddy entry point.
    image: ghcr.io/lesisty7/quotenode/quotenode-frontend@sha256:40a1cdc4fca5cebd9f43d34daef4ba059a88000ff08af821e199566f07260606
    depends_on:
      backend:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:80/"]
      interval: 15s
      timeout: 5s
      retries: 3
    cpus: ${FRONTEND_CPUS:-0}
    # Prod frontend is Caddy serving the static build (measured ~46 MiB peak under load); 96m is ample.
    # CPU is a free ceiling, so headroom for concurrent connections costs nothing at idle.
    mem_limit: ${FRONTEND_MEM_LIMIT:-96m}
    restart: unless-stopped
    logging: *json-file-logging

  caddy:
    # Entry point: the only published ports (HTTP_PORT/HTTPS_PORT, default 80/443), TLS for DOMAIN, routing, security headers.
    image: ghcr.io/lesisty7/quotenode/quotenode-frontend@sha256:40a1cdc4fca5cebd9f43d34daef4ba059a88000ff08af821e199566f07260606
    # The released frontend image carries the edge config (frontend/caddy/Caddyfile.edge) and the Cloudflare
    # ranges, so the edge needs no host files. Same image digest as the frontend service.
    command: ["caddy", "run", "--config", "/etc/caddy/Caddyfile.edge", "--adapter", "caddyfile"]
    depends_on:
      backend:
        condition: service_healthy
      frontend:
        condition: service_healthy
    environment:
      # Site address for frontend/caddy/Caddyfile.edge: a public host name enables automatic HTTPS; ":80" or
      # "http://host" serves plain HTTP on a trusted LAN. Required: an empty site address is not a valid config.
      DOMAIN: ${DOMAIN:?set DOMAIN to the public host name, or :80 for plain HTTP on a LAN}
      # Optional: address(es) of an operator reverse proxy in front of this edge (default: trust none).
      EDGE_TRUSTED_PROXIES: ${EDGE_TRUSTED_PROXIES:-}
    ports:
      - "${HTTP_PORT:-80}:80"
      - "${HTTPS_PORT:-443}:443"
      - "${HTTPS_PORT:-443}:443/udp"      # HTTP/3 (QUIC)
    volumes:
      - caddy_data:/data
      - caddy_config:/config
    # caddy is the single ingress (TLS, HTTP/3/QUIC, proxying all traffic); give it
    # cores for handshake/encryption bursts under load. CPU idle cost ~0.
    cpus: ${CADDY_CPUS:-0}
    # 96m fits the 4 GB / light-traffic profile. Under heavy TLS load (many concurrent
    # handshakes, large QUIC buffers) raise CADDY_MEM_LIMIT — this ingress is untested at scale.
    mem_limit: ${CADDY_MEM_LIMIT:-96m}
    restart: unless-stopped
    logging: *json-file-logging

# Persistent data: database, uploads, generated PDFs, local backup archives, GeoIP database and the entry
# point's certificates/config. Docker prefixes each name with the Compose project name (by default the
# directory name), so keep the project name across upgrades.
volumes:
  postgres_data:
  backend_uploads:
  backend_pdfs:
  backend_backups:
  backend_geoip:
  caddy_data:
  caddy_config:

Aby wycofać aktualizację, odtwórz kopię wolumenów razem z zapisaną definicją stosu. Nigdy nie uruchamiaj poprzedniej definicji na bazie danych, którą nowe wydanie już zmigrowało.

Coolify

Zastąp definicję Compose zasobu plikiem docker-compose.coolify.yml z nowego pakietu (Edit Compose File) i wdróż. Coolify pobiera nowe obrazy, zanim zatrzyma działające kontenery. Zobacz Instalację w Coolify.

Instalacje utworzone przed pakietami wydań

Jeśli zainstalowano QuoteNode według tych przewodników, zanim pojawiły się pakiety wydań (ręcznie przygotowany docker-compose.yml z obrazami :latest), zaktualizuj w tym samym katalogu tymi samymi poleceniami: upgrade.sh wykonuje kopię narzędziami nowego wydania na projekcie Compose i wolumenach Twojej instalacji, więc wcześniej nie jest potrzebny ani katalog operator/, ani usługa kopii zapasowych. Przed prepare dopisz do .env te ustawienia; działająca instalacja jeszcze ich nie używa:

  • DOMAIN konfiguruje teraz nowy punkt wejścia (caddy): publiczna nazwa hosta automatycznie dostaje HTTPS; dla zwykłego HTTP w LAN lub na laptopie użyj DOMAIN=http://<adres> (na przykład http://192.168.1.20 albo http://localhost).
  • Jeśli porty 80/443 są zajęte, ustaw HTTP_PORT / HTTPS_PORT zamiast edytować plik Compose.

Pakiet zachowuje nazwy wolumenów z wcześniejszych przewodników (postgres_data, backend_uploads, backend_pdfs), więc Twoje dane zostaną użyte. Uruchom upgrade.sh z tego samego katalogu (albo zachowaj tę samą nazwę stosu w Portainerze): inna nazwa projektu wystartowałaby z pustymi wolumenami.

Gdy migracja zatrzyma aktualizację

Migracja może odmówić wykonania, gdy znajdzie dane, których nie wolno jej samodzielnie zmienić. Backend wtedy się nie uruchamia, a ta migracja niczego nie zmienia — wycofuje się w całości i nie zostawia niczego do naprawy w historii migracji. Wcześniejsze migracje z tej samej aktualizacji mogły już zostać wykonane, więc baza jest tuż przed odrzuconym krokiem, a nie w wersji, od której zaczynałeś. Nie ma pośpiechu i nie ma utraty danych.

Przyczynę przeczytasz w logu:

docker compose logs backend | grep -i "cannot enforce"

Dla przypisań sekcji ofert obraz zawiera prowadzoną naprawę, która działa bez uruchomionego backendu — pokazuje oferty, których to dotyczy, i pozwala wybrać, co się z nimi stanie. Zobacz Rozwiązywanie problemów z instalacją.

Nie używaj flyway repair ani baseline, aby obejść odrzuconą migrację. Nie naprawiają danych, a zablokowana migracja nie zostawia niczego do naprawy.

Ponieważ wcześniejsze migracje mogły już zostać wykonane, sam nieudany start nigdy nie pozwala wrócić do poprzednich obrazów — zobacz Wycofanie aktualizacji.

Sprawdzenie po aktualizacji

  1. Otwórz /health — odpowiedź to UP.
  2. Otwórz /actuator/info: jego commitSha jest równy commitSha w nowym release.json.
  3. Zaloguj się i sprawdź nową wersję w Admin > Licencja.
  4. Utwórz testową ofertę i wygeneruj PDF.
  5. Otwórz link publiczny, aby sprawdzić routing.
  6. Jeśli SMTP jest skonfigurowane, wyślij testowe powiadomienie e-mail.

Wycofanie aktualizacji

Nigdy nie uruchamiaj docker compose down -v — to usuwa wszystkie dane, także bazę danych.

upgrade.sh rollback wraca do definicji zapisanej przez prepare tylko wtedy, gdy jest to bezpieczne: punkt kontrolny musi należeć do tej instalacji, schemat bazy musi być dokładnie taki jak zapisany — nieudany start tego nie dowodzi, wcześniejsze migracje mogły już zostać zatwierdzone — a każdy poprzedni obraz musi być wciąż tym, który działał. W przeciwnym razie odmawia i niczego nie zmienia:

../next/operator/upgrade.sh rollback
  • Dozwolone: zapisane docker-compose.yml, .env i release.json wracają, a poprzednie obrazy startują bez pobierania; usługi dodane przez nowe wydanie są usuwane, wolumeny zostają.
  • Odmowa: nie uruchamiaj poprzednich obrazów ręcznie. Jeśli migracja odmówiła wykonania, napraw sytuację w nowej wersji (zobacz Gdy migracja zatrzyma aktualizację) albo odtwórz kopię sprzed aktualizacji — bazę danych i pliki jako jedną całość — jak opisano w artykule Kopie zapasowe i odtwarzanie. Odtwarzanie sprawdza archiwum i jego zgodność, zanim cokolwiek zmieni, i zachowuje kopię bezpieczeństwa, dopóki nie zweryfikuje wyniku.
  • Instalacje utworzone przed pakietami wydań wycofuje się tak samo. Po odmowie odtwórz kopię z ../quotenode-backups narzędziem operator/restore.sh tego wydania; wydanie zaktualizuje odtworzone dane przy starcie.

Format wersji

QuoteNode używa wersjonowania semantycznego z sufiksem kanału:

  • v0.9.0-alpha — wczesny rozwój
  • v0.9.0-beta — publiczna beta
  • v0.9.0-rc — kandydat do wydania
  • v0.9.0 — wydanie stabilne

Etykieta wydania nigdy nie jest ponownie użyta dla innych obrazów. release.json i https://quotenode.dev/releases/latest.json podają wersję, kanał, etykietę, commit i digesty obrazów wydania.

Last reviewed: Recently