From 5832e9e691ae7678b56f6111ec80961c515911f8 Mon Sep 17 00:00:00 2001 From: Knee Cola Date: Tue, 25 Nov 2025 19:28:16 +0100 Subject: [PATCH] Refactor deployment scripts to separate standalone and swarm modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove ambiguous docker-compose-deploy.yml and debug-deploy.sh - Update deploy-standalone.sh to use docker-compose-standalone.yaml - Update deploy-swarm.sh to use docker-compose-swarm.yml - Standardize error messages to English in deployment scripts - Add db-backup-swarm.sh for swarm-specific backups - Unify network naming to util-bills-mongo-network across configs - Fix MongoDB credentials in swarm compose file 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- db-backup-swarm.sh | 36 ++++++++++++++++ debug-deploy.sh | 38 ----------------- deploy-standalone.sh | 11 +++-- deploy-swarm.sh | 9 ++-- docker-compose-deploy.yml | 77 ---------------------------------- docker-compose-standalone.yaml | 31 +++++++------- docker-compose-swarm.yml | 19 +++++---- 7 files changed, 74 insertions(+), 147 deletions(-) create mode 100755 db-backup-swarm.sh delete mode 100755 debug-deploy.sh delete mode 100644 docker-compose-deploy.yml diff --git a/db-backup-swarm.sh b/db-backup-swarm.sh new file mode 100755 index 0000000..6783abc --- /dev/null +++ b/db-backup-swarm.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Configuration +MONGO_SERVICE="utility-bills-tracker_mongo" + +# scale down mongo service while we copy its volume +docker service scale "$MONGO_SERVICE"=0 + +# timestamp for filename +TIMESTAMP=$(date +"%Y-%m-%d-%H-%M") + +# backup directory and retention (can be overridden via env) +BACKUP_DIR="${BACKUP_DIR:-backups}" +KEEP="${KEEP:-7}" + +mkdir -p "$BACKUP_DIR" + +BACKUP_FILE="$BACKUP_DIR/mongo-volume-backup-$TIMESTAMP.tar.gz" + +sudo tar -czvpf "$BACKUP_FILE" mongo-volume + +# rotate old backups: keep only the newest $KEEP files +if [ "$KEEP" -gt 0 ]; then + # gather files sorted newest-first + mapfile -t files < <(ls -1t "$BACKUP_DIR"/mongo-volume-backup-*.tar.gz 2>/dev/null || true) + if [ "${#files[@]}" -gt "$KEEP" ]; then + for f in "${files[@]:$KEEP}"; do + echo "Removing old backup: $f" + rm -f -- "$f" + done + fi +fi + +# bring mongo service back up +docker service scale "$MONGO_SERVICE"=1 diff --git a/debug-deploy.sh b/debug-deploy.sh deleted file mode 100755 index d9133b1..0000000 --- a/debug-deploy.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -# print menu: (1) deploy stack, (2) follow logs of "web-app" service, (3) remove stack -echo "1. Deploy stack" -echo "2. Follow logs of 'web-app' service" -echo "3. Remove stack" -echo "" -echo "Ctrl+C to exit" -echo "" - -# read user input -read -p "Enter your choice: " -n 1 -r -echo "" - -# deploy stack -if [ $REPLY -eq 1 ] -then - #docker stack deploy -c docker-compose-deploy.yml utility-bills-tracker - HOSTNAME=0.0.0.0 \ - NEXTAUTH_URL=https://rezije.app \ - docker stack deploy \ - -c docker-compose-deploy.yml utility-bills-tracker -fi - -# follow logs of "web-app" service -if [ $REPLY -eq 2 ] -then - docker service logs -f utility-bills-tracker_web-app -fi - -# remove stack -if [ $REPLY -eq 3 ] -then - docker stack rm utility-bills-tracker -fi - -# go back to menu -./debug-deploy.sh \ No newline at end of file diff --git a/deploy-standalone.sh b/deploy-standalone.sh index b13b3a4..448a1ac 100755 --- a/deploy-standalone.sh +++ b/deploy-standalone.sh @@ -1,15 +1,18 @@ #!/bin/bash if [ "$1" == "" ] ; then - printf "\nNisi zadao verziju Docker image-a koji treba deployati" - printf "\n\nSintaksa:\n\n deploy.sh 1.0.0\n\n" + printf "\nDocker image-a version param missing" + printf "\n\nSyntax:\n\n deploy-standalone.sh 1.0.0\n\n" exit 1 fi printf "\nBUILD START ...\n\n" IMAGE_VERSION=$1 +COMPOSE_FILE="docker-compose-standalone.yaml" -echo "Deploying $STACK_NAME with image version: $IMAGE_VERSION" +echo "Deploying with image version: $IMAGE_VERSION" # Pass IMAGE_VERSION env var for compose variable substitution -IMAGE_VERSION="$IMAGE_VERSION" docker compose up -d \ No newline at end of file +IMAGE_VERSION="$IMAGE_VERSION" docker compose \ + -f "$COMPOSE_FILE" \ + up -d \ No newline at end of file diff --git a/deploy-swarm.sh b/deploy-swarm.sh index 484b38d..8b43799 100755 --- a/deploy-swarm.sh +++ b/deploy-swarm.sh @@ -1,17 +1,18 @@ #!/bin/bash if [ "$1" == "" ] ; then - printf "\nNisi zadao verziju Docker image-a koji treba deployati" - printf "\n\nSintaksa:\n\n deploy.sh 1.0.0\n\n" + printf "\nDocker image-a version param missing" + printf "\n\nSyntax:\n\n deploy-swarm.sh 1.0.0\n\n" exit 1 fi printf "\nBUILD START ...\n\n" IMAGE_VERSION=$1 +COMPOSE_FILE="docker-compose-swarm.yml" -echo "Deploying $STACK_NAME with image version: $IMAGE_VERSION" +echo "Deploying with image version: $IMAGE_VERSION" # Pass IMAGE_VERSION env var for compose variable substitution IMAGE_VERSION="$IMAGE_VERSION" docker stack deploy \ - -c docker-compose-deploy.yml \ + -c "$COMPOSE_FILE" \ utility-bills-tracker \ No newline at end of file diff --git a/docker-compose-deploy.yml b/docker-compose-deploy.yml deleted file mode 100644 index 8f56318..0000000 --- a/docker-compose-deploy.yml +++ /dev/null @@ -1,77 +0,0 @@ -# this compose file runs Postgres db and exposes it's port to the host machine -version: "3.7" - -networks: - traefik-network: - name: "traefik-network" - external: true - util-bills-mongo-network: - name: "util-bills-mongo-network" - attachable: false - external: false - internal: true - -services: - app: - image: utility-bills-tracker:${IMAGE_VERSION} - networks: - - traefik-network - - util-bills-mongo-network - volumes: - - ./etc/hosts/:/etc/hosts - environment: - MONGODB_URI: mongodb://rezije.app:w4z4piJBgCdAm4tpawqB@mongo:27017/utility-bills - GOOGLE_ID: 355397364527-adjrokm6hromcaaar0qfhk050mfr35ou.apps.googleusercontent.com - GOOGLE_SECRET: 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 - AUTH_SECRET: Gh0jQ35oq6DR8HkLR3heA8EaEDtxYN/xkP6blvukZ0w= - LINKEDIN_ID: 776qlcsykl1rag - LINKEDIN_SECRET: ugf61aJ2iyErLK40 - HOSTNAME: rezije.app # IP address at which the server will be listening (0.0.0.0 = listen on all addresses) - NEXTAUTH_URL: https://rezije.app # URL next-auth will use while redirecting user during authentication (if not set - will use HOSTNAME) - PORT: ${PORT:-80} - deploy: - # u slucaju rušenja kontejnera čekamo 5s i dižemo novi kontejner => ako se i on sruši opet ceka 5s i pokusava ponovno (tako 5 puta) - restart_policy: - condition: any - delay: 5s - max_attempts: 0 # u slučaju rušenja containera pokušavaj ga pokrenuti dok ne uspije = BESKONAČNO - labels: - - traefik.enable=true - - traefik.docker.network=traefik-network # mreže preko koje ide komunikacija sa Traefikom - - traefik.http.services.web-app.loadbalancer.server.port=80 - - traefik.http.routers.web-app.entrypoints=http - - traefik.http.routers.web-app.rule=Host(`${FQDN:-rezije.app}`) - mongo: - image: mongo:4.4.27 - ulimits: - nofile: - soft: 64000 - hard: 64000 - environment: - MONGO_INITDB_ROOT_USERNAME: root - MONGO_INITDB_ROOT_PASSWORD: example - volumes: - - ./mongo-volume:/data/db - networks: - - util-bills-mongo-network - mongo-express: - image: mongo-express - environment: - ME_CONFIG_MONGODB_ADMINUSERNAME: root - ME_CONFIG_MONGODB_ADMINPASSWORD: HjktJCPWMBtM1ACrDaw7 - ME_CONFIG_MONGODB_URL: mongodb://root:HjktJCPWMBtM1ACrDaw7@mongo:27017/ - networks: - - traefik-network - - util-bills-mongo-network - deploy: - # u slucaju rušenja kontejnera čekamo 5s i dižemo novi kontejner => ako se i on sruši opet ceka 5s i pokusava ponovno (tako 5 puta) - restart_policy: - condition: any - delay: 5s - max_attempts: 0 # u slučaju rušenja containera pokušavaj ga pokrenuti dok ne uspije = BESKONAČNO - labels: - - traefik.enable=true - - traefik.docker.network=traefik-network # mreže preko koje ide komunikacija sa Traefikom - - traefik.http.services.mongo-express.loadbalancer.server.port=8081 - - traefik.http.routers.mongo-express.entrypoints=http - - traefik.http.routers.mongo-express.rule=Host(`mongo.rezije.app`) diff --git a/docker-compose-standalone.yaml b/docker-compose-standalone.yaml index ec799d5..10d2f49 100644 --- a/docker-compose-standalone.yaml +++ b/docker-compose-standalone.yaml @@ -6,19 +6,17 @@ networks: name: traefik-network external: true util-bills-mongo-network: - name: util-bills-mongo-network - internal: true # bridge network, isolated from host and other networks + name: "util-bills-mongo-network" + attachable: false + external: false + internal: true # bridge network, isolated from host and other networks services: web-app: image: utility-bills-tracker:${IMAGE_VERSION} - container_name: evidencija-rezija__web-app - restart: unless-stopped # u slučaju rušenja containera pokušavaj ga pokrenuti dok ne uspije = BESKONAČNO networks: - traefik-network - util-bills-mongo-network - depends_on: - - mongo volumes: - ./etc/hosts/:/etc/hosts environment: @@ -28,9 +26,13 @@ services: AUTH_SECRET: Gh0jQ35oq6DR8HkLR3heA8EaEDtxYN/xkP6blvukZ0w= LINKEDIN_ID: 776qlcsykl1rag LINKEDIN_SECRET: ugf61aJ2iyErLK40 - HOSTNAME: rezije.app # IP address at which the server will be listening (0.0.0.0 = listen on all addresses) + HOSTNAME: rezije.app # IP address at which the server will be listening (0.0.0.0 = listen on all addresses) NEXTAUTH_URL: https://rezije.app # URL next-auth will use while redirecting user during authentication (if not set - will use HOSTNAME) PORT: ${PORT:-80} + container_name: evidencija-rezija__web-app + restart: unless-stopped # u slučaju rušenja containera pokušavaj ga pokrenuti dok ne uspije = BESKONAČNO + depends_on: + - mongo labels: - traefik.enable=true - traefik.docker.network=traefik-network # mreže preko koje ide komunikacija sa Traefikom @@ -49,20 +51,19 @@ services: - ./mongo-volume:/data/db networks: - util-bills-mongo-network - mongo-express: image: mongo-express - container_name: evidencija-rezija__mongo-express - restart: unless-stopped - networks: - - traefik-network - - util-bills-mongo-network - depends_on: - - mongo environment: ME_CONFIG_MONGODB_ADMINUSERNAME: root ME_CONFIG_MONGODB_ADMINPASSWORD: HjktJCPWMBtM1ACrDaw7 ME_CONFIG_MONGODB_URL: mongodb://root:HjktJCPWMBtM1ACrDaw7@mongo:27017/ + networks: + - traefik-network + - util-bills-mongo-network + container_name: evidencija-rezija__mongo-express + restart: unless-stopped + depends_on: + - mongo labels: - traefik.enable=true - traefik.docker.network=traefik-network # mreže preko koje ide komunikacija sa Traefikom diff --git a/docker-compose-swarm.yml b/docker-compose-swarm.yml index 290ba21..87decb0 100644 --- a/docker-compose-swarm.yml +++ b/docker-compose-swarm.yml @@ -5,22 +5,22 @@ networks: traefik-network: name: "traefik-network" external: true - mongo-network: - name: "mongo-network" + util-bills-mongo-network: + name: "util-bills-mongo-network" attachable: false external: false - internal: true + internal: true # bridge network, isolated from host and other networks services: web-app: image: utility-bills-tracker:${IMAGE_VERSION} networks: - traefik-network - - mongo-network + - util-bills-mongo-network volumes: - ./etc/hosts/:/etc/hosts environment: - MONGODB_URI: mongodb://root:example@mongo:27017/ + MONGODB_URI: mongodb://rezije.app:w4z4piJBgCdAm4tpawqB@mongo:27017/utility-bills GOOGLE_ID: 355397364527-adjrokm6hromcaaar0qfhk050mfr35ou.apps.googleusercontent.com GOOGLE_SECRET: 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 AUTH_SECRET: Gh0jQ35oq6DR8HkLR3heA8EaEDtxYN/xkP6blvukZ0w= @@ -49,16 +49,16 @@ services: volumes: - ./mongo-volume:/data/db networks: - - mongo-network + - util-bills-mongo-network mongo-express: image: mongo-express environment: ME_CONFIG_MONGODB_ADMINUSERNAME: root - ME_CONFIG_MONGODB_ADMINPASSWORD: example - ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/ + ME_CONFIG_MONGODB_ADMINPASSWORD: HjktJCPWMBtM1ACrDaw7 + ME_CONFIG_MONGODB_URL: mongodb://root:HjktJCPWMBtM1ACrDaw7@mongo:27017/ networks: - traefik-network - - mongo-network + - util-bills-mongo-network deploy: # u slucaju rušenja kontejnera čekamo 5s i dižemo novi kontejner => ako se i on sruši opet ceka 5s i pokusava ponovno (tako 5 puta) restart_policy: @@ -71,3 +71,4 @@ services: - traefik.http.services.mongo-express.loadbalancer.server.port=8081 - traefik.http.routers.mongo-express.entrypoints=http - traefik.http.routers.mongo-express.rule=Host(`mongo.rezije.app`) +