From 360e5bf835adf03d12d9aa83c6069e531a8917ce Mon Sep 17 00:00:00 2001 From: mahdikhanzadi <6291970+khanzadimahdi@users.noreply.github.com> Date: Thu, 2 Jan 2025 17:00:10 +0100 Subject: [PATCH] switch to docker stack (#53) --- .github/workflows/infrastructure.yaml | 41 +++++++++---- .gitignore | 1 + compose.yaml | 11 +++- infrastructure/Makefile | 60 +++++++------------ infrastructure/compose.app.yaml | 49 +++++++++++++++ infrastructure/compose.backend.yaml | 49 --------------- infrastructure/compose.docker.yaml | 21 +++---- infrastructure/compose.docker_dashboard.yaml | 24 ++++++++ infrastructure/compose.frontend.yaml | 13 ++-- infrastructure/compose.mongodb.yaml | 25 ++++---- infrastructure/compose.mongodb_dashboard.yaml | 28 +++++++++ infrastructure/compose.nats.yaml | 14 ++++- infrastructure/compose.proxy.yaml | 35 +++++++---- infrastructure/proxy/nginx.conf | 4 +- 14 files changed, 225 insertions(+), 150 deletions(-) create mode 100644 infrastructure/compose.app.yaml delete mode 100644 infrastructure/compose.backend.yaml create mode 100644 infrastructure/compose.docker_dashboard.yaml create mode 100644 infrastructure/compose.mongodb_dashboard.yaml diff --git a/.github/workflows/infrastructure.yaml b/.github/workflows/infrastructure.yaml index 1ad0394a..2ca1fc65 100644 --- a/.github/workflows/infrastructure.yaml +++ b/.github/workflows/infrastructure.yaml @@ -16,6 +16,9 @@ env: TF_VAR_project_name: tarhche TF_VAR_instance_name: backend + DOCKER_REGISTRY: ghcr.io + PROXY_IMAGE_NAME: proxy + EC2_SSH_ADDRESS: ${{ secrets.EC2_SSH_ADDRESS }} EC2_SSH_ENDPOINT: ${{ secrets.EC2_SSH_USER }}@${{ secrets.EC2_SSH_ADDRESS }} @@ -56,9 +59,7 @@ jobs: cd: runs-on: ubuntu-latest - if: | - (format('refs/heads/{0}', github.event.repository.default_branch) == github.ref) - && (github.event.workflow_run.conclusion == 'success') + # if: ${{ format('refs/heads/{0}', github.event.repository.default_branch) == github.ref }} needs: - ci @@ -89,6 +90,22 @@ jobs: run: terraform apply -auto-approve -input=false continue-on-error: false + - name: Build images + run: | + PROXY_IMAGE_ID=$(echo $REGISTRY/${{ github.repository_owner }}/$PROXY_IMAGE_NAME | tr '[A-Z]' '[a-z]') + PROXY_IMAGE_VERSION=${{ github.sha }} + echo "PROXY_IMAGE_ID=$PROXY_IMAGE_ID" >> "$GITHUB_ENV" + echo "PROXY_IMAGE_VERSION=$PROXY_IMAGE_VERSION" >> "$GITHUB_ENV" + docker build . --file Dockerfile --target production --tag $PROXY_IMAGE_ID:$PROXY_IMAGE_VERSION --tag $PROXY_IMAGE_ID:latest + + - name: Log in to registry + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + + - name: Push images + run: | + docker push $PROXY_IMAGE_ID:$PROXY_IMAGE_VERSION + docker push $PROXY_IMAGE_ID:latest + - name: Deploy services run: | # Setup ssh key @@ -140,6 +157,8 @@ jobs: export BACKEND_S3_USE_SSL="${{ secrets.BACKEND_S3_USE_SSL }}" export BACKEND_S3_BUCKET_NAME="${{ secrets.BACKEND_S3_BUCKET_NAME }}" + export PROXY_IMAGE=${{ secrets.PROXY_IMAGE }} + export APP_IMAGE="${{ secrets.APP_IMAGE }}" export PORTAINER_ADMIN_PASSWORD='${{ secrets.PORTAINER_ADMIN_PASSWORD }}' @@ -152,12 +171,12 @@ jobs: # Run Docker Compose cd /opt/deployment/ - docker compose \ - -f compose.mongodb.yaml \ - -f compose.nats.yaml \ - -f compose.docker.yaml \ - -f compose.backend.yaml \ - -f compose.frontend.yaml \ - -f compose.proxy.yaml \ - up --detach --pull always + docker stack deploy -c compose.mongodb.yaml mongodb --detach=false + docker stack deploy -c compose.mongodb_dashboard.yaml mongodb_dashboard --detach=false + docker stack deploy -c compose.nats.yaml nats --detach=false + docker stack deploy -c compose.docker.yaml docker --detach=false + docker stack deploy -c compose.docker_dashboard.yaml docker_dashboard --detach=false + docker stack deploy -c compose.backend.yaml backend --detach=false + docker stack deploy -c compose.frontend.yaml frontend --detach=false + docker stack deploy -c compose.proxy.yaml proxy --detach=false EOF diff --git a/.gitignore b/.gitignore index 2fc028ce..6e512438 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /private /private.pub +/tmp \ No newline at end of file diff --git a/compose.yaml b/compose.yaml index 70b34230..9fb6ca46 100644 --- a/compose.yaml +++ b/compose.yaml @@ -69,6 +69,9 @@ services: restart: unless-stopped ports: - "27017:27017" + volumes: + - ./tmp/mongodb/db:/data/db + - ./tmp/mongodb/configdb:/data/configdb environment: MONGO_INITDB_ROOT_USERNAME: ${MONGO_USERNAME} MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD} @@ -89,7 +92,7 @@ services: image: minio/minio restart: unless-stopped ports: - - "9000:9000" + - "9100:9000" - "9001:9001" environment: MINIO_ROOT_USER: ${S3_ACCESS_KEY} @@ -107,11 +110,13 @@ services: nats: image: nats:2.10 - command: ["--jetstream", "-m", "8222", "-p", "4222"] # --config /etc/nats/nats-server.conf + command: ["--jetstream", "--http_port", "8222", "--port", "4222", "--store_dir", "/data"] ports: - "4222:4222" # client port - "6222:6222" # cluster post - "8222:8222" # HTTP monitoring port + volumes: + - ./tmp/nats:/data natsdashboard: image: mdawar/nats-dashboard @@ -133,7 +138,7 @@ services: depends_on: - docker ports: - - "9100:9000" + - "9200:9000" - "9443:9443" command: > --admin-password="$$2a$$12$$4xcOa82Ni5rjgQF.v.JWi.i71OyUm3fwmfWiumgJHIAPGU.uOw3qu" diff --git a/infrastructure/Makefile b/infrastructure/Makefile index 2aaff00c..6221ed95 100644 --- a/infrastructure/Makefile +++ b/infrastructure/Makefile @@ -1,8 +1,8 @@ export TF_VAR_project_name = tarhche export TF_VAR_instance_name = backend -export EC2_SSH_ADDRESS = -export EC2_SSH_USER = +export EC2_SSH_ADDRESS = ec2-3-124-72-48.eu-central-1.compute.amazonaws.com +export EC2_SSH_USER = ubuntu export EC2_SSH_ENDPOINT = ${EC2_SSH_USER}@${EC2_SSH_ADDRESS} export VOLUME_PATH = ./tmp/volume_01 @@ -35,6 +35,8 @@ export BACKEND_S3_ACCESS_KEY = export BACKEND_S3_USE_SSL = false export BACKEND_S3_BUCKET_NAME = +export PROXY_IMAGE = ghcr.io/tarhche/proxy:latest + export APP_IMAGE = ghcr.io/tarhche/backend:latest # username: admin @@ -43,7 +45,7 @@ export PORTAINER_ADMIN_PASSWORD = $$2a$$12$$4xcOa82Ni5rjgQF.v.JWi.i71OyUm3fwmfWi export FRONTEND_IMAGE = ghcr.io/tarhche/frontend:latest export NEXT_PUBLIC_EXTERNAL_BACKEND_BASE_URL = -export INTERNAL_BACKEND_BASE_URL = +export INTERNAL_BACKEND_BASE_URL = http://app export NEXT_PUBLIC_FILES_BASE_URL = validate: @@ -72,41 +74,21 @@ ssh: ssh -i "ssh-private-key.pem" ${EC2_SSH_ENDPOINT} up: - docker compose \ - -f compose.mongodb.yaml \ - -f compose.nats.yaml \ - -f compose.docker.yaml \ - -f compose.backend.yaml \ - -f compose.frontend.yaml \ - -f compose.proxy.yaml \ - up --detach --pull always + docker stack deploy -c compose.mongodb.yaml mongodb --detach=false + docker stack deploy -c compose.mongodb_dashboard.yaml mongodb_dashboard --detach=false + docker stack deploy -c compose.nats.yaml nats --detach=false + docker stack deploy -c compose.docker.yaml docker --detach=false + docker stack deploy -c compose.docker_dashboard.yaml docker_dashboard --detach=false + docker stack deploy -c compose.backend.yaml backend --detach=false + docker stack deploy -c compose.frontend.yaml frontend --detach=false + docker stack deploy -c compose.proxy.yaml proxy --detach=false down: - docker compose \ - -f compose.mongodb.yaml \ - -f compose.nats.yaml \ - -f compose.docker.yaml \ - -f compose.backend.yaml \ - -f compose.frontend.yaml \ - -f compose.proxy.yaml \ - down --volumes --remove-orphans - -ps: - docker compose \ - -f compose.mongodb.yaml \ - -f compose.nats.yaml \ - -f compose.docker.yaml \ - -f compose.backend.yaml \ - -f compose.frontend.yaml \ - -f compose.proxy.yaml \ - ps -a - -logs%: - docker compose \ - -f compose.mongodb.yaml \ - -f compose.nats.yaml \ - -f compose.docker.yaml \ - -f compose.backend.yaml \ - -f compose.frontend.yaml \ - -f compose.proxy.yaml \ - logs $* + docker stack rm proxy + docker stack rm frontend + docker stack rm backend + docker stack rm docker_dashboard + docker stack rm docker + docker stack rm nats + docker stack rm mongodb_dashboard + docker stack rm mongodb diff --git a/infrastructure/compose.app.yaml b/infrastructure/compose.app.yaml new file mode 100644 index 00000000..c950acf5 --- /dev/null +++ b/infrastructure/compose.app.yaml @@ -0,0 +1,49 @@ +services: + app: + image: ${APP_IMAGE} + networks: + - app + - mongodb + - nats + - docker + deploy: + mode: replicated + replicas: 1 + endpoint_mode: vip + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + environment: + PRIVATE_KEY: ${BACKEND_PRIVATE_KEY} + S3_ENDPOINT: ${BACKEND_S3_ENDPOINT} + S3_ACCESS_KEY: ${BACKEND_S3_ACCESS_KEY} + S3_SECRET_KEY: ${BACKEND_S3_SECRET_KEY} + S3_BUCKET_NAME: ${BACKEND_S3_BUCKET_NAME} + S3_USE_SSL: ${BACKEND_S3_USE_SSL} + MONGO_SCHEME: ${BACKEND_MONGO_SCHEME} + MONGO_USERNAME: ${BACKEND_MONGO_USERNAME} + MONGO_PASSWORD: ${BACKEND_MONGO_PASSWORD} + MONGO_HOST: ${BACKEND_MONGO_HOST} + MONGO_PORT: ${BACKEND_MONGO_PORT} + MONGO_DATABASE_NAME: ${BACKEND_MONGO_DATABASE_NAME} + MAIL_SMTP_FROM: ${BACKEND_MAIL_SMTP_FROM} + MAIL_SMTP_USERNAME: ${BACKEND_MAIL_SMTP_USERNAME} + MAIL_SMTP_PASSWORD: ${BACKEND_MAIL_SMTP_PASSWORD} + MAIL_SMTP_HOST: ${BACKEND_MAIL_SMTP_HOST} + MAIL_SMTP_PORT: ${BACKEND_MAIL_SMTP_PORT} + NATS_URL: ${BACKEND_NATS_URL} + +networks: + app: + name: app + driver: overlay + mongodb: + name: mongodb + external: true + nats: + name: nats + external: true + docker: + name: docker + external: true diff --git a/infrastructure/compose.backend.yaml b/infrastructure/compose.backend.yaml deleted file mode 100644 index ca5bab0b..00000000 --- a/infrastructure/compose.backend.yaml +++ /dev/null @@ -1,49 +0,0 @@ -# app placement -x-app: &app - restart: unless-stopped - environment: - PRIVATE_KEY: ${BACKEND_PRIVATE_KEY} - S3_ENDPOINT: ${BACKEND_S3_ENDPOINT} - S3_ACCESS_KEY: ${BACKEND_S3_ACCESS_KEY} - S3_SECRET_KEY: ${BACKEND_S3_SECRET_KEY} - S3_BUCKET_NAME: ${BACKEND_S3_BUCKET_NAME} - S3_USE_SSL: ${BACKEND_S3_USE_SSL} - MONGO_SCHEME: ${BACKEND_MONGO_SCHEME} - MONGO_USERNAME: ${BACKEND_MONGO_USERNAME} - MONGO_PASSWORD: ${BACKEND_MONGO_PASSWORD} - MONGO_HOST: ${BACKEND_MONGO_HOST} - MONGO_PORT: ${BACKEND_MONGO_PORT} - MONGO_DATABASE_NAME: ${BACKEND_MONGO_DATABASE_NAME} - MAIL_SMTP_FROM: ${BACKEND_MAIL_SMTP_FROM} - MAIL_SMTP_USERNAME: ${BACKEND_MAIL_SMTP_USERNAME} - MAIL_SMTP_PASSWORD: ${BACKEND_MAIL_SMTP_PASSWORD} - MAIL_SMTP_HOST: ${BACKEND_MAIL_SMTP_HOST} - MAIL_SMTP_PORT: ${BACKEND_MAIL_SMTP_PORT} - NATS_URL: ${BACKEND_NATS_URL} - -services: - app: - <<: *app - image: ${APP_IMAGE} - networks: - - backend - - frontend - - mongodb - - nats - - docker - deploy: - mode: replicated - replicas: 2 - endpoint_mode: vip - -networks: - backend: - name: backend - frontend: - name: frontend - mongodb: - name: mongodb - nats: - name: nats - docker: - name: docker diff --git a/infrastructure/compose.docker.yaml b/infrastructure/compose.docker.yaml index b896e0c2..f66b8b1b 100644 --- a/infrastructure/compose.docker.yaml +++ b/infrastructure/compose.docker.yaml @@ -1,24 +1,21 @@ services: docker: image: docker:27-dind - restart: unless-stopped networks: - docker + deploy: + mode: replicated + replicas: 1 + endpoint_mode: vip + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 runtime: sysbox-runc - # privileged: true # uncomment this to test locally and comment runtime. environment: DOCKER_TLS_CERTDIR: "" # disable certs - portainer: - image: portainer/portainer-ce - restart: unless-stopped - networks: - - docker - depends_on: - - docker - command: > - --admin-password="${PORTAINER_ADMIN_PASSWORD}" - networks: docker: name: docker + driver: overlay diff --git a/infrastructure/compose.docker_dashboard.yaml b/infrastructure/compose.docker_dashboard.yaml new file mode 100644 index 00000000..7a4b84fa --- /dev/null +++ b/infrastructure/compose.docker_dashboard.yaml @@ -0,0 +1,24 @@ +services: + docker_dashboard: + image: portainer/portainer-ce + networks: + - docker + - docker_dashboard + deploy: + mode: replicated + replicas: 1 + endpoint_mode: vip + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + command: > + --admin-password="${PORTAINER_ADMIN_PASSWORD}" + +networks: + docker_dashboard: + name: docker_dashboard + driver: overlay + docker: + name: docker + external: true diff --git a/infrastructure/compose.frontend.yaml b/infrastructure/compose.frontend.yaml index 15e92213..d06c2081 100644 --- a/infrastructure/compose.frontend.yaml +++ b/infrastructure/compose.frontend.yaml @@ -1,14 +1,17 @@ services: frontend: image: ${FRONTEND_IMAGE} - restart: unless-stopped networks: - frontend - - backend + - app deploy: mode: replicated replicas: 2 endpoint_mode: vip + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 environment: NEXT_PUBLIC_EXTERNAL_BACKEND_BASE_URL: ${NEXT_PUBLIC_EXTERNAL_BACKEND_BASE_URL} INTERNAL_BACKEND_BASE_URL: ${INTERNAL_BACKEND_BASE_URL} @@ -17,5 +20,7 @@ services: networks: frontend: name: frontend - backend: - name: backend + driver: overlay + app: + name: app + external: true diff --git a/infrastructure/compose.mongodb.yaml b/infrastructure/compose.mongodb.yaml index 1c1ac3e1..704d61be 100644 --- a/infrastructure/compose.mongodb.yaml +++ b/infrastructure/compose.mongodb.yaml @@ -1,27 +1,24 @@ services: mongodb: image: mongo:8.0 - restart: unless-stopped networks: - mongodb + deploy: + mode: replicated + replicas: 1 + endpoint_mode: vip + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 environment: MONGO_INITDB_ROOT_USERNAME: ${MONGO_USERNAME} MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD} volumes: - - ${VOLUME_PATH}/mongodb:/data - - mongodashboard: - image: mongo-express - restart: unless-stopped - networks: - - mongodb - depends_on: - - mongodb - environment: - ME_CONFIG_BASICAUTH_USERNAME: ${DASHBOARD_MONGO_USERNAME} - ME_CONFIG_BASICAUTH_PASSWORD: ${DASHBOARD_MONGO_PASSWORD} - ME_CONFIG_MONGODB_URL: ${DASHBOARD_MONGO_MONGODB_URL} + - ${VOLUME_PATH}/mongodb/db:/data/db + - ${VOLUME_PATH}/mongodb/configdb:/data/configdb networks: mongodb: name: mongodb + driver: overlay diff --git a/infrastructure/compose.mongodb_dashboard.yaml b/infrastructure/compose.mongodb_dashboard.yaml new file mode 100644 index 00000000..bbc9a2d0 --- /dev/null +++ b/infrastructure/compose.mongodb_dashboard.yaml @@ -0,0 +1,28 @@ +services: + mongodb_dashboard: + image: mongo-express + networks: + - mongodb + - mongodb_dashboard + deploy: + mode: replicated + replicas: 1 + endpoint_mode: vip + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + depends_on: + - mongodb + environment: + ME_CONFIG_BASICAUTH_USERNAME: ${DASHBOARD_MONGO_USERNAME} + ME_CONFIG_BASICAUTH_PASSWORD: ${DASHBOARD_MONGO_PASSWORD} + ME_CONFIG_MONGODB_URL: ${DASHBOARD_MONGO_MONGODB_URL} + +networks: + mongodb_dashboard: + name: mongodb_dashboard + driver: overlay + mongodb: + name: mongodb + external: true diff --git a/infrastructure/compose.nats.yaml b/infrastructure/compose.nats.yaml index d3e621db..da55a2dc 100644 --- a/infrastructure/compose.nats.yaml +++ b/infrastructure/compose.nats.yaml @@ -1,13 +1,21 @@ services: nats: image: nats:2.10 - restart: unless-stopped networks: - nats + deploy: + mode: replicated + replicas: 1 + endpoint_mode: vip + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 volumes: - - ${VOLUME_PATH}/nats:/data - command: ["--jetstream", "-m", "8222", "-p", "4222"] + - ${VOLUME_PATH}/nats:/jetstream + command: ["--jetstream", "--http_port", "8222", "--port", "4222", "--store_dir", "/data"] networks: nats: name: nats + driver: overlay diff --git a/infrastructure/compose.proxy.yaml b/infrastructure/compose.proxy.yaml index ff2907ce..b7791a27 100644 --- a/infrastructure/compose.proxy.yaml +++ b/infrastructure/compose.proxy.yaml @@ -1,27 +1,36 @@ services: proxy: - build: - dockerfile: Dockerfile - context: ./proxy - restart: unless-stopped + image: ${PROXY_IMAGE} networks: - - backend + - proxy - frontend - - mongodb - - docker + - app + - mongodb_dashboard + - docker_dashboard deploy: mode: replicated replicas: 1 endpoint_mode: vip + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 ports: - 80:80 networks: - backend: - name: backend + proxy: + name: proxy + driver: overlay frontend: name: frontend - mongodb: - name: mongodb - docker: - name: docker + external: true + app: + name: app + external: true + mongodb_dashboard: + name: mongodb_dashboard + external: true + docker_dashboard: + name: docker_dashboard + external: true diff --git a/infrastructure/proxy/nginx.conf b/infrastructure/proxy/nginx.conf index 919886cd..749055f2 100644 --- a/infrastructure/proxy/nginx.conf +++ b/infrastructure/proxy/nginx.conf @@ -33,7 +33,7 @@ server { server_name "dockerdashboard.*"; location / { - proxy_pass http://portainer:9000; + proxy_pass http://docker_dashboard:9000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -47,7 +47,7 @@ server { server_name "mongodashboard.*"; location / { - proxy_pass http://mongodashboard:8081; + proxy_pass http://mongodb_dashboard:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;