From 534dea7317128400a2ee2c2a011ff2d7437a38af Mon Sep 17 00:00:00 2001 From: thibaud-leclere Date: Wed, 6 May 2026 15:06:35 +0200 Subject: [PATCH] feat: split dev and prod compose workflows --- .env.example | 7 ++++ Makefile | 54 +++++++++++++++++++++--- docker-compose.prod.yml | 67 ++++++++++++++++++++++++++++++ docker-compose.yml | 91 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 207 insertions(+), 12 deletions(-) create mode 100644 docker-compose.prod.yml diff --git a/.env.example b/.env.example index 66196da8..6e0da0a1 100644 --- a/.env.example +++ b/.env.example @@ -38,3 +38,10 @@ VITE_PROXYSCOTCH_ACCESS_TOKEN= # Set to `true` for subpath based access ENABLE_SUBPATH_BASED_ACCESS=false + +#-----------------------Docker Image Config-------------------------# +# Used by docker-compose.prod.yml and Makefile image targets. +API_CLIENT_REGISTRY=forge.lclr.dev +API_CLIENT_NAMESPACE=thibaud-lclr +API_CLIENT_IMAGE_PREFIX=api-client +API_CLIENT_TAG=latest diff --git a/Makefile b/Makefile index 2680aadc..7efdf2aa 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,64 @@ COMPOSE := docker compose ENV_FILE := .env ENV_EXAMPLE := .env.example +PROD_COMPOSE := docker-compose.prod.yml -.PHONY: up down logs ps ensure-env +REGISTRY ?= forge.lclr.dev +NAMESPACE ?= thibaud-lclr +IMAGE_PREFIX ?= api-client +TAG ?= latest -up: ensure-env +BACKEND_IMAGE := $(REGISTRY)/$(NAMESPACE)/$(IMAGE_PREFIX)-backend:$(TAG) +APP_IMAGE := $(REGISTRY)/$(NAMESPACE)/$(IMAGE_PREFIX)-app:$(TAG) +SH_ADMIN_IMAGE := $(REGISTRY)/$(NAMESPACE)/$(IMAGE_PREFIX)-sh-admin:$(TAG) + +PROD_ENV := API_CLIENT_REGISTRY=$(REGISTRY) API_CLIENT_NAMESPACE=$(NAMESPACE) API_CLIENT_IMAGE_PREFIX=$(IMAGE_PREFIX) API_CLIENT_TAG=$(TAG) + +.PHONY: up dev-up prod-up down dev-down prod-down logs dev-logs prod-logs ps dev-ps prod-ps ensure-env docker-build-images docker-push-images docker-build-push-images + +up: dev-up + +dev-up: ensure-env $(COMPOSE) up -d --build -down: +prod-up: ensure-env + $(PROD_ENV) $(COMPOSE) -f $(PROD_COMPOSE) up -d + +down: dev-down + +dev-down: $(COMPOSE) down -logs: +prod-down: + $(PROD_ENV) $(COMPOSE) -f $(PROD_COMPOSE) down + +logs: dev-logs + +dev-logs: $(COMPOSE) logs -f -ps: +prod-logs: + $(PROD_ENV) $(COMPOSE) -f $(PROD_COMPOSE) logs -f + +ps: dev-ps + +dev-ps: $(COMPOSE) ps +prod-ps: + $(PROD_ENV) $(COMPOSE) -f $(PROD_COMPOSE) ps + ensure-env: @test -f $(ENV_FILE) || cp $(ENV_EXAMPLE) $(ENV_FILE) + +docker-build-images: + docker build --file prod.Dockerfile --target backend --tag $(BACKEND_IMAGE) . + docker build --file prod.Dockerfile --target app --tag $(APP_IMAGE) . + docker build --file prod.Dockerfile --target sh_admin --tag $(SH_ADMIN_IMAGE) . + +docker-push-images: + docker push $(BACKEND_IMAGE) + docker push $(APP_IMAGE) + docker push $(SH_ADMIN_IMAGE) + +docker-build-push-images: docker-build-images docker-push-images diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 00000000..1ab9484f --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,67 @@ +services: + hoppscotch-db: + image: postgres:15 + user: postgres + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-testpass} + POSTGRES_DB: ${POSTGRES_DB:-hoppscotch} + volumes: + - hoppscotch-db:/var/lib/postgresql/data + healthcheck: + test: + [ + "CMD-SHELL", + "sh -c 'pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}'", + ] + interval: 5s + timeout: 5s + retries: 10 + + hoppscotch-backend: + container_name: hoppscotch-backend + restart: unless-stopped + image: ${API_CLIENT_REGISTRY:-forge.lclr.dev}/${API_CLIENT_NAMESPACE:-thibaud-lclr}/${API_CLIENT_IMAGE_PREFIX:-api-client}-backend:${API_CLIENT_TAG:-latest} + env_file: + - ./.env + environment: + DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-testpass}@hoppscotch-db:5432/${POSTGRES_DB:-hoppscotch} + depends_on: + hoppscotch-db: + condition: service_healthy + command: + [ + "sh", + "-c", + "pnpm exec prisma migrate deploy && node prod_run.mjs", + ] + ports: + - "3170:3170" + + hoppscotch-app: + container_name: hoppscotch-app + restart: unless-stopped + image: ${API_CLIENT_REGISTRY:-forge.lclr.dev}/${API_CLIENT_NAMESPACE:-thibaud-lclr}/${API_CLIENT_IMAGE_PREFIX:-api-client}-app:${API_CLIENT_TAG:-latest} + env_file: + - ./.env + depends_on: + hoppscotch-backend: + condition: service_started + ports: + - "3000:3000" + - "3200:3200" + + hoppscotch-sh-admin: + container_name: hoppscotch-sh-admin + restart: unless-stopped + image: ${API_CLIENT_REGISTRY:-forge.lclr.dev}/${API_CLIENT_NAMESPACE:-thibaud-lclr}/${API_CLIENT_IMAGE_PREFIX:-api-client}-sh-admin:${API_CLIENT_TAG:-latest} + env_file: + - ./.env + depends_on: + hoppscotch-backend: + condition: service_started + ports: + - "3100:3100" + +volumes: + hoppscotch-db: diff --git a/docker-compose.yml b/docker-compose.yml index 55d08340..960b1e4f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,13 +18,29 @@ services: timeout: 5s retries: 10 - hoppscotch-aio: - container_name: hoppscotch-aio + hoppscotch-dev-deps: + build: + dockerfile: prod.Dockerfile + context: . + target: base_builder + env_file: + - ./.env + environment: + DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-testpass}@hoppscotch-db:5432/${POSTGRES_DB:-hoppscotch} + working_dir: /usr/src/app + command: ["pnpm", "install", "-f", "--prefer-offline"] + volumes: + - .:/usr/src/app + - hoppscotch-node-modules:/usr/src/app/node_modules + - hoppscotch-pnpm-store:/root/.local/share/pnpm/store/v10 + + hoppscotch-backend: + container_name: hoppscotch-backend-dev restart: unless-stopped build: dockerfile: prod.Dockerfile context: . - target: aio + target: base_builder env_file: - ./.env environment: @@ -32,18 +48,79 @@ services: depends_on: hoppscotch-db: condition: service_healthy + hoppscotch-dev-deps: + condition: service_completed_successfully + working_dir: /usr/src/app/packages/hoppscotch-backend command: [ "sh", "-c", - "pnpm exec prisma migrate deploy && node /usr/src/app/aio_run.mjs", + "pnpm exec prisma migrate deploy && pnpm run start:dev", ] + volumes: + - .:/usr/src/app + - hoppscotch-node-modules:/usr/src/app/node_modules + - hoppscotch-pnpm-store:/root/.local/share/pnpm/store/v10 + ports: + - "3170:3170" + + hoppscotch-app: + container_name: hoppscotch-app-dev + restart: unless-stopped + build: + dockerfile: prod.Dockerfile + context: . + target: base_builder + env_file: + - ./.env + depends_on: + hoppscotch-dev-deps: + condition: service_completed_successfully + hoppscotch-backend: + condition: service_started + working_dir: /usr/src/app/packages/hoppscotch-selfhost-web + command: + [ + "sh", + "-c", + "pnpm run dev:gql-codegen & pnpm exec vite --host 0.0.0.0 --port 3000", + ] + volumes: + - .:/usr/src/app + - hoppscotch-node-modules:/usr/src/app/node_modules + - hoppscotch-pnpm-store:/root/.local/share/pnpm/store/v10 ports: - "3000:3000" + + hoppscotch-sh-admin: + container_name: hoppscotch-sh-admin-dev + restart: unless-stopped + build: + dockerfile: prod.Dockerfile + context: . + target: base_builder + env_file: + - ./.env + depends_on: + hoppscotch-dev-deps: + condition: service_completed_successfully + hoppscotch-backend: + condition: service_started + working_dir: /usr/src/app/packages/hoppscotch-sh-admin + command: + [ + "sh", + "-c", + "pnpm run dev:gql-codegen & pnpm exec vite --host 0.0.0.0 --port 3100", + ] + volumes: + - .:/usr/src/app + - hoppscotch-node-modules:/usr/src/app/node_modules + - hoppscotch-pnpm-store:/root/.local/share/pnpm/store/v10 + ports: - "3100:3100" - - "3170:3170" - - "3200:3200" - - "3080:80" volumes: hoppscotch-db: + hoppscotch-node-modules: + hoppscotch-pnpm-store: