From 5e0b5a8e7ab685b11dd007b47667fec54fc9e718 Mon Sep 17 00:00:00 2001 From: Wuesteon Date: Mon, 8 Dec 2025 16:04:50 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20ci:=20add=20Docker=20deployment?= =?UTF-8?q?=20for=20Manacore,=20Todo,=20Calendar,=20and=20Clock=20apps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add complete Docker deployment infrastructure for 4 new applications: - Dockerfiles for backend (NestJS) and web (SvelteKit) apps - docker-entrypoint.sh scripts with PostgreSQL wait and schema push - Updated docker-compose.staging.yml with 7 new services - Updated CI/CD workflows with build matrix and health checks --- .github/workflows/cd-staging.yml | 93 +++++++ .github/workflows/ci.yml | 7 + apps/calendar/apps/backend/Dockerfile | 68 +++++ .../apps/backend/docker-entrypoint.sh | 23 ++ apps/calendar/apps/web/Dockerfile | 72 ++++++ apps/clock/apps/backend/Dockerfile | 68 +++++ apps/clock/apps/backend/docker-entrypoint.sh | 23 ++ apps/clock/apps/web/Dockerfile | 72 ++++++ apps/manacore/apps/web/Dockerfile | 74 ++++++ apps/todo/apps/backend/Dockerfile | 67 +++++ apps/todo/apps/backend/docker-entrypoint.sh | 23 ++ apps/todo/apps/web/Dockerfile | 72 ++++++ docker-compose.staging.yml | 236 ++++++++++++++++++ 13 files changed, 898 insertions(+) create mode 100644 apps/calendar/apps/backend/Dockerfile create mode 100644 apps/calendar/apps/backend/docker-entrypoint.sh create mode 100644 apps/calendar/apps/web/Dockerfile create mode 100644 apps/clock/apps/backend/Dockerfile create mode 100644 apps/clock/apps/backend/docker-entrypoint.sh create mode 100644 apps/clock/apps/web/Dockerfile create mode 100644 apps/manacore/apps/web/Dockerfile create mode 100644 apps/todo/apps/backend/Dockerfile create mode 100644 apps/todo/apps/backend/docker-entrypoint.sh create mode 100644 apps/todo/apps/web/Dockerfile diff --git a/.github/workflows/cd-staging.yml b/.github/workflows/cd-staging.yml index 8c6e83955..1852ed42a 100644 --- a/.github/workflows/cd-staging.yml +++ b/.github/workflows/cd-staging.yml @@ -24,6 +24,13 @@ on: - mana-core-auth - chat-backend - chat-web + - manacore-web + - todo-backend + - todo-web + - calendar-backend + - calendar-web + - clock-backend + - clock-web workflow_call: permissions: @@ -184,6 +191,15 @@ jobs: # Create chat database (for chat-backend service) docker compose exec -T postgres psql -U postgres -c "CREATE DATABASE chat;" 2>/dev/null || echo "chat database already exists" + # Create todo database (for todo-backend service) + docker compose exec -T postgres psql -U postgres -c "CREATE DATABASE todo;" 2>/dev/null || echo "todo database already exists" + + # Create calendar database (for calendar-backend service) + docker compose exec -T postgres psql -U postgres -c "CREATE DATABASE calendar;" 2>/dev/null || echo "calendar database already exists" + + # Create clock database (for clock-backend service) + docker compose exec -T postgres psql -U postgres -c "CREATE DATABASE clock;" 2>/dev/null || echo "clock database already exists" + echo "✅ Databases ready" EOF @@ -238,6 +254,83 @@ jobs: exit 1 fi + # Check manacore-web + echo "Checking manacore-web..." + if docker compose exec -T manacore-web wget -q -O - http://localhost:5173/health > /dev/null 2>&1; then + echo "✅ manacore-web is healthy" + else + echo "❌ manacore-web health check failed" + echo "=== Logs ===" + docker compose logs --tail=50 manacore-web + exit 1 + fi + + # Check todo-backend + echo "Checking todo-backend..." + if docker compose exec -T todo-backend wget -q -O - http://localhost:3018/api/v1/health > /dev/null 2>&1; then + echo "✅ todo-backend is healthy" + else + echo "❌ todo-backend health check failed" + echo "=== Logs ===" + docker compose logs --tail=50 todo-backend + exit 1 + fi + + # Check todo-web + echo "Checking todo-web..." + if docker compose exec -T todo-web wget -q -O - http://localhost:5188/health > /dev/null 2>&1; then + echo "✅ todo-web is healthy" + else + echo "❌ todo-web health check failed" + echo "=== Logs ===" + docker compose logs --tail=50 todo-web + exit 1 + fi + + # Check calendar-backend + echo "Checking calendar-backend..." + if docker compose exec -T calendar-backend wget -q -O - http://localhost:3016/api/v1/health > /dev/null 2>&1; then + echo "✅ calendar-backend is healthy" + else + echo "❌ calendar-backend health check failed" + echo "=== Logs ===" + docker compose logs --tail=50 calendar-backend + exit 1 + fi + + # Check calendar-web + echo "Checking calendar-web..." + if docker compose exec -T calendar-web wget -q -O - http://localhost:5186/health > /dev/null 2>&1; then + echo "✅ calendar-web is healthy" + else + echo "❌ calendar-web health check failed" + echo "=== Logs ===" + docker compose logs --tail=50 calendar-web + exit 1 + fi + + # Check clock-backend + echo "Checking clock-backend..." + if docker compose exec -T clock-backend wget -q -O - http://localhost:3017/api/v1/health > /dev/null 2>&1; then + echo "✅ clock-backend is healthy" + else + echo "❌ clock-backend health check failed" + echo "=== Logs ===" + docker compose logs --tail=50 clock-backend + exit 1 + fi + + # Check clock-web + echo "Checking clock-web..." + if docker compose exec -T clock-web wget -q -O - http://localhost:5187/health > /dev/null 2>&1; then + echo "✅ clock-web is healthy" + else + echo "❌ clock-web health check failed" + echo "=== Logs ===" + docker compose logs --tail=50 clock-web + exit 1 + fi + echo "" echo "✅ All health checks passed!" EOF diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f30b9b10a..1d56ac667 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,6 +86,13 @@ jobs: - { name: 'mana-core-auth', path: 'services/mana-core-auth', port: '3001' } - { name: 'chat-backend', path: 'apps/chat/apps/backend', port: '3002' } - { name: 'chat-web', path: 'apps/chat/apps/web', port: '3000' } + - { name: 'manacore-web', path: 'apps/manacore/apps/web', port: '5173' } + - { name: 'todo-backend', path: 'apps/todo/apps/backend', port: '3018' } + - { name: 'todo-web', path: 'apps/todo/apps/web', port: '5188' } + - { name: 'calendar-backend', path: 'apps/calendar/apps/backend', port: '3016' } + - { name: 'calendar-web', path: 'apps/calendar/apps/web', port: '5186' } + - { name: 'clock-backend', path: 'apps/clock/apps/backend', port: '3017' } + - { name: 'clock-web', path: 'apps/clock/apps/web', port: '5187' } fail-fast: false steps: - name: Checkout code diff --git a/apps/calendar/apps/backend/Dockerfile b/apps/calendar/apps/backend/Dockerfile new file mode 100644 index 000000000..129862166 --- /dev/null +++ b/apps/calendar/apps/backend/Dockerfile @@ -0,0 +1,68 @@ +# Build stage +FROM node:20-alpine AS builder + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate + +WORKDIR /app + +# Copy root workspace files +COPY pnpm-workspace.yaml ./ +COPY package.json ./ +COPY pnpm-lock.yaml ./ + +# Copy shared packages +COPY packages/shared-errors ./packages/shared-errors +COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth + +# Copy calendar packages and backend +COPY apps/calendar/packages ./apps/calendar/packages +COPY apps/calendar/apps/backend ./apps/calendar/apps/backend + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Build shared packages first +WORKDIR /app/packages/shared-errors +RUN pnpm build + +WORKDIR /app/packages/shared-nestjs-auth +RUN pnpm build + +# Build the backend +WORKDIR /app/apps/calendar/apps/backend +RUN pnpm build + +# Production stage +FROM node:20-alpine AS production + +# Install pnpm and postgresql-client for health checks +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate \ + && apk add --no-cache postgresql-client + +WORKDIR /app + +# Copy everything from builder (including node_modules) +COPY --from=builder /app/pnpm-workspace.yaml ./ +COPY --from=builder /app/package.json ./ +COPY --from=builder /app/pnpm-lock.yaml ./ +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/packages ./packages +COPY --from=builder /app/apps/calendar ./apps/calendar + +# Copy entrypoint script +COPY apps/calendar/apps/backend/docker-entrypoint.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +WORKDIR /app/apps/calendar/apps/backend + +# Expose port +EXPOSE 3016 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:3016/api/v1/health || exit 1 + +# Run entrypoint script +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["node", "dist/main.js"] diff --git a/apps/calendar/apps/backend/docker-entrypoint.sh b/apps/calendar/apps/backend/docker-entrypoint.sh new file mode 100644 index 000000000..bda857019 --- /dev/null +++ b/apps/calendar/apps/backend/docker-entrypoint.sh @@ -0,0 +1,23 @@ +#!/bin/sh +set -e + +echo "=== Calendar Backend Entrypoint ===" + +# Wait for PostgreSQL to be ready +echo "Waiting for PostgreSQL..." +until pg_isready -h ${DB_HOST:-postgres} -p ${DB_PORT:-5432} -U ${DB_USER:-postgres} 2>/dev/null; do + echo "PostgreSQL is unavailable - sleeping" + sleep 2 +done +echo "PostgreSQL is up!" + +cd /app/apps/calendar/apps/backend + +# Run schema push +echo "Pushing database schema..." +npx drizzle-kit push --force +echo "Schema push completed!" + +# Execute the main command +echo "Starting application..." +exec "$@" diff --git a/apps/calendar/apps/web/Dockerfile b/apps/calendar/apps/web/Dockerfile new file mode 100644 index 000000000..04040c048 --- /dev/null +++ b/apps/calendar/apps/web/Dockerfile @@ -0,0 +1,72 @@ +# Build stage +FROM node:20-alpine AS builder + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate + +WORKDIR /app + +# Copy root workspace files +COPY pnpm-workspace.yaml ./ +COPY package.json ./ +COPY pnpm-lock.yaml ./ + +# Copy shared packages needed by calendar web +COPY packages/shared-auth ./packages/shared-auth +COPY packages/shared-auth-ui ./packages/shared-auth-ui +COPY packages/shared-branding ./packages/shared-branding +COPY packages/shared-feedback-service ./packages/shared-feedback-service +COPY packages/shared-feedback-types ./packages/shared-feedback-types +COPY packages/shared-feedback-ui ./packages/shared-feedback-ui +COPY packages/shared-i18n ./packages/shared-i18n +COPY packages/shared-icons ./packages/shared-icons +COPY packages/shared-tailwind ./packages/shared-tailwind +COPY packages/shared-theme ./packages/shared-theme +COPY packages/shared-theme-ui ./packages/shared-theme-ui +COPY packages/shared-subscription-types ./packages/shared-subscription-types +COPY packages/shared-subscription-ui ./packages/shared-subscription-ui +COPY packages/shared-profile-ui ./packages/shared-profile-ui +COPY packages/shared-ui ./packages/shared-ui +COPY packages/shared-utils ./packages/shared-utils + +# Copy calendar packages and web +COPY apps/calendar/packages ./apps/calendar/packages +COPY apps/calendar/apps/web ./apps/calendar/apps/web + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Build shared packages that need building +WORKDIR /app/packages/shared-auth +RUN pnpm build || true + +# Build the web app +WORKDIR /app/apps/calendar/apps/web +RUN pnpm build + +# Production stage +FROM node:20-alpine AS production + +WORKDIR /app + +# Copy built application +COPY --from=builder /app/apps/calendar/apps/web/build ./build +COPY --from=builder /app/apps/calendar/apps/web/package.json ./ + +# Install only production dependencies for the built app +RUN npm install --omit=dev 2>/dev/null || true + +# Expose port +EXPOSE 5186 + +# Set environment variables +ENV NODE_ENV=production +ENV PORT=5186 +ENV HOST=0.0.0.0 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:5186/health || exit 1 + +# Run the app +CMD ["node", "build"] diff --git a/apps/clock/apps/backend/Dockerfile b/apps/clock/apps/backend/Dockerfile new file mode 100644 index 000000000..a2b05c80b --- /dev/null +++ b/apps/clock/apps/backend/Dockerfile @@ -0,0 +1,68 @@ +# Build stage +FROM node:20-alpine AS builder + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate + +WORKDIR /app + +# Copy root workspace files +COPY pnpm-workspace.yaml ./ +COPY package.json ./ +COPY pnpm-lock.yaml ./ + +# Copy shared packages +COPY packages/shared-errors ./packages/shared-errors +COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth + +# Copy clock packages and backend +COPY apps/clock/packages ./apps/clock/packages +COPY apps/clock/apps/backend ./apps/clock/apps/backend + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Build shared packages first +WORKDIR /app/packages/shared-errors +RUN pnpm build + +WORKDIR /app/packages/shared-nestjs-auth +RUN pnpm build + +# Build the backend +WORKDIR /app/apps/clock/apps/backend +RUN pnpm build + +# Production stage +FROM node:20-alpine AS production + +# Install pnpm and postgresql-client for health checks +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate \ + && apk add --no-cache postgresql-client + +WORKDIR /app + +# Copy everything from builder (including node_modules) +COPY --from=builder /app/pnpm-workspace.yaml ./ +COPY --from=builder /app/package.json ./ +COPY --from=builder /app/pnpm-lock.yaml ./ +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/packages ./packages +COPY --from=builder /app/apps/clock ./apps/clock + +# Copy entrypoint script +COPY apps/clock/apps/backend/docker-entrypoint.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +WORKDIR /app/apps/clock/apps/backend + +# Expose port +EXPOSE 3017 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:3017/api/v1/health || exit 1 + +# Run entrypoint script +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["node", "dist/main.js"] diff --git a/apps/clock/apps/backend/docker-entrypoint.sh b/apps/clock/apps/backend/docker-entrypoint.sh new file mode 100644 index 000000000..f34aebf6e --- /dev/null +++ b/apps/clock/apps/backend/docker-entrypoint.sh @@ -0,0 +1,23 @@ +#!/bin/sh +set -e + +echo "=== Clock Backend Entrypoint ===" + +# Wait for PostgreSQL to be ready +echo "Waiting for PostgreSQL..." +until pg_isready -h ${DB_HOST:-postgres} -p ${DB_PORT:-5432} -U ${DB_USER:-postgres} 2>/dev/null; do + echo "PostgreSQL is unavailable - sleeping" + sleep 2 +done +echo "PostgreSQL is up!" + +cd /app/apps/clock/apps/backend + +# Run schema push +echo "Pushing database schema..." +npx drizzle-kit push --force +echo "Schema push completed!" + +# Execute the main command +echo "Starting application..." +exec "$@" diff --git a/apps/clock/apps/web/Dockerfile b/apps/clock/apps/web/Dockerfile new file mode 100644 index 000000000..8b9baf360 --- /dev/null +++ b/apps/clock/apps/web/Dockerfile @@ -0,0 +1,72 @@ +# Build stage +FROM node:20-alpine AS builder + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate + +WORKDIR /app + +# Copy root workspace files +COPY pnpm-workspace.yaml ./ +COPY package.json ./ +COPY pnpm-lock.yaml ./ + +# Copy shared packages needed by clock web +COPY packages/shared-auth ./packages/shared-auth +COPY packages/shared-auth-ui ./packages/shared-auth-ui +COPY packages/shared-branding ./packages/shared-branding +COPY packages/shared-feedback-service ./packages/shared-feedback-service +COPY packages/shared-feedback-types ./packages/shared-feedback-types +COPY packages/shared-feedback-ui ./packages/shared-feedback-ui +COPY packages/shared-i18n ./packages/shared-i18n +COPY packages/shared-icons ./packages/shared-icons +COPY packages/shared-tailwind ./packages/shared-tailwind +COPY packages/shared-theme ./packages/shared-theme +COPY packages/shared-theme-ui ./packages/shared-theme-ui +COPY packages/shared-subscription-types ./packages/shared-subscription-types +COPY packages/shared-subscription-ui ./packages/shared-subscription-ui +COPY packages/shared-profile-ui ./packages/shared-profile-ui +COPY packages/shared-ui ./packages/shared-ui +COPY packages/shared-utils ./packages/shared-utils + +# Copy clock packages and web +COPY apps/clock/packages ./apps/clock/packages +COPY apps/clock/apps/web ./apps/clock/apps/web + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Build shared packages that need building +WORKDIR /app/packages/shared-auth +RUN pnpm build || true + +# Build the web app +WORKDIR /app/apps/clock/apps/web +RUN pnpm build + +# Production stage +FROM node:20-alpine AS production + +WORKDIR /app + +# Copy built application +COPY --from=builder /app/apps/clock/apps/web/build ./build +COPY --from=builder /app/apps/clock/apps/web/package.json ./ + +# Install only production dependencies for the built app +RUN npm install --omit=dev 2>/dev/null || true + +# Expose port +EXPOSE 5187 + +# Set environment variables +ENV NODE_ENV=production +ENV PORT=5187 +ENV HOST=0.0.0.0 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:5187/health || exit 1 + +# Run the app +CMD ["node", "build"] diff --git a/apps/manacore/apps/web/Dockerfile b/apps/manacore/apps/web/Dockerfile new file mode 100644 index 000000000..7fb03759d --- /dev/null +++ b/apps/manacore/apps/web/Dockerfile @@ -0,0 +1,74 @@ +# Build stage +FROM node:20-alpine AS builder + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate + +WORKDIR /app + +# Copy root workspace files +COPY pnpm-workspace.yaml ./ +COPY package.json ./ +COPY pnpm-lock.yaml ./ + +# Copy shared packages needed by manacore web +COPY packages/shared-auth ./packages/shared-auth +COPY packages/shared-auth-ui ./packages/shared-auth-ui +COPY packages/shared-branding ./packages/shared-branding +COPY packages/shared-config ./packages/shared-config +COPY packages/shared-feedback-service ./packages/shared-feedback-service +COPY packages/shared-feedback-types ./packages/shared-feedback-types +COPY packages/shared-feedback-ui ./packages/shared-feedback-ui +COPY packages/shared-i18n ./packages/shared-i18n +COPY packages/shared-icons ./packages/shared-icons +COPY packages/shared-tailwind ./packages/shared-tailwind +COPY packages/shared-theme ./packages/shared-theme +COPY packages/shared-theme-ui ./packages/shared-theme-ui +COPY packages/shared-subscription-types ./packages/shared-subscription-types +COPY packages/shared-subscription-ui ./packages/shared-subscription-ui +COPY packages/shared-profile-ui ./packages/shared-profile-ui +COPY packages/shared-supabase ./packages/shared-supabase +COPY packages/shared-types ./packages/shared-types +COPY packages/shared-ui ./packages/shared-ui +COPY packages/shared-utils ./packages/shared-utils + +# Copy manacore web +COPY apps/manacore/apps/web ./apps/manacore/apps/web + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Build shared packages that need building +WORKDIR /app/packages/shared-auth +RUN pnpm build || true + +# Build the web app +WORKDIR /app/apps/manacore/apps/web +RUN pnpm build + +# Production stage +FROM node:20-alpine AS production + +WORKDIR /app + +# Copy built application +COPY --from=builder /app/apps/manacore/apps/web/build ./build +COPY --from=builder /app/apps/manacore/apps/web/package.json ./ + +# Install only production dependencies for the built app +RUN npm install --omit=dev 2>/dev/null || true + +# Expose port +EXPOSE 5173 + +# Set environment variables +ENV NODE_ENV=production +ENV PORT=5173 +ENV HOST=0.0.0.0 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:5173/health || exit 1 + +# Run the app +CMD ["node", "build"] diff --git a/apps/todo/apps/backend/Dockerfile b/apps/todo/apps/backend/Dockerfile new file mode 100644 index 000000000..e589ef07b --- /dev/null +++ b/apps/todo/apps/backend/Dockerfile @@ -0,0 +1,67 @@ +# Build stage +FROM node:20-alpine AS builder + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate + +WORKDIR /app + +# Copy root workspace files +COPY pnpm-workspace.yaml ./ +COPY package.json ./ +COPY pnpm-lock.yaml ./ + +# Copy shared packages +COPY packages/shared-errors ./packages/shared-errors +COPY packages/shared-nestjs-auth ./packages/shared-nestjs-auth + +# Copy todo backend +COPY apps/todo/apps/backend ./apps/todo/apps/backend + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Build shared packages first +WORKDIR /app/packages/shared-errors +RUN pnpm build + +WORKDIR /app/packages/shared-nestjs-auth +RUN pnpm build + +# Build the backend +WORKDIR /app/apps/todo/apps/backend +RUN pnpm build + +# Production stage +FROM node:20-alpine AS production + +# Install pnpm and postgresql-client for health checks +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate \ + && apk add --no-cache postgresql-client + +WORKDIR /app + +# Copy everything from builder (including node_modules) +COPY --from=builder /app/pnpm-workspace.yaml ./ +COPY --from=builder /app/package.json ./ +COPY --from=builder /app/pnpm-lock.yaml ./ +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/packages ./packages +COPY --from=builder /app/apps/todo/apps/backend ./apps/todo/apps/backend + +# Copy entrypoint script +COPY apps/todo/apps/backend/docker-entrypoint.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +WORKDIR /app/apps/todo/apps/backend + +# Expose port +EXPOSE 3018 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:3018/api/v1/health || exit 1 + +# Run entrypoint script +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["node", "dist/main.js"] diff --git a/apps/todo/apps/backend/docker-entrypoint.sh b/apps/todo/apps/backend/docker-entrypoint.sh new file mode 100644 index 000000000..e50cbfd33 --- /dev/null +++ b/apps/todo/apps/backend/docker-entrypoint.sh @@ -0,0 +1,23 @@ +#!/bin/sh +set -e + +echo "=== Todo Backend Entrypoint ===" + +# Wait for PostgreSQL to be ready +echo "Waiting for PostgreSQL..." +until pg_isready -h ${DB_HOST:-postgres} -p ${DB_PORT:-5432} -U ${DB_USER:-postgres} 2>/dev/null; do + echo "PostgreSQL is unavailable - sleeping" + sleep 2 +done +echo "PostgreSQL is up!" + +cd /app/apps/todo/apps/backend + +# Run schema push +echo "Pushing database schema..." +npx drizzle-kit push --force +echo "Schema push completed!" + +# Execute the main command +echo "Starting application..." +exec "$@" diff --git a/apps/todo/apps/web/Dockerfile b/apps/todo/apps/web/Dockerfile new file mode 100644 index 000000000..6d15865e6 --- /dev/null +++ b/apps/todo/apps/web/Dockerfile @@ -0,0 +1,72 @@ +# Build stage +FROM node:20-alpine AS builder + +# Install pnpm +RUN corepack enable && corepack prepare pnpm@9.15.0 --activate + +WORKDIR /app + +# Copy root workspace files +COPY pnpm-workspace.yaml ./ +COPY package.json ./ +COPY pnpm-lock.yaml ./ + +# Copy shared packages needed by todo web +COPY packages/shared-auth ./packages/shared-auth +COPY packages/shared-auth-ui ./packages/shared-auth-ui +COPY packages/shared-branding ./packages/shared-branding +COPY packages/shared-feedback-service ./packages/shared-feedback-service +COPY packages/shared-feedback-types ./packages/shared-feedback-types +COPY packages/shared-feedback-ui ./packages/shared-feedback-ui +COPY packages/shared-i18n ./packages/shared-i18n +COPY packages/shared-icons ./packages/shared-icons +COPY packages/shared-tailwind ./packages/shared-tailwind +COPY packages/shared-theme ./packages/shared-theme +COPY packages/shared-theme-ui ./packages/shared-theme-ui +COPY packages/shared-subscription-types ./packages/shared-subscription-types +COPY packages/shared-subscription-ui ./packages/shared-subscription-ui +COPY packages/shared-profile-ui ./packages/shared-profile-ui +COPY packages/shared-ui ./packages/shared-ui +COPY packages/shared-utils ./packages/shared-utils + +# Copy todo packages and web +COPY apps/todo/packages ./apps/todo/packages +COPY apps/todo/apps/web ./apps/todo/apps/web + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Build shared packages that need building +WORKDIR /app/packages/shared-auth +RUN pnpm build || true + +# Build the web app +WORKDIR /app/apps/todo/apps/web +RUN pnpm build + +# Production stage +FROM node:20-alpine AS production + +WORKDIR /app + +# Copy built application +COPY --from=builder /app/apps/todo/apps/web/build ./build +COPY --from=builder /app/apps/todo/apps/web/package.json ./ + +# Install only production dependencies for the built app +RUN npm install --omit=dev 2>/dev/null || true + +# Expose port +EXPOSE 5188 + +# Set environment variables +ENV NODE_ENV=production +ENV PORT=5188 +ENV HOST=0.0.0.0 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:5188/health || exit 1 + +# Run the app +CMD ["node", "build"] diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml index 509561d3e..a8d5b5d97 100644 --- a/docker-compose.staging.yml +++ b/docker-compose.staging.yml @@ -159,6 +159,242 @@ services: max-size: "10m" max-file: "3" + # ============================================ + # Manacore App + # ============================================ + + manacore-web: + image: ${DOCKER_REGISTRY:-ghcr.io/memo-2023}/manacore-web:${MANACORE_WEB_VERSION:-latest} + container_name: manacore-web-staging + restart: unless-stopped + depends_on: + mana-core-auth: + condition: service_healthy + environment: + NODE_ENV: staging + PORT: 5173 + PUBLIC_MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + PUBLIC_MANA_CORE_AUTH_URL_CLIENT: http://46.224.108.214:3001 + ports: + - "5173:5173" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5173/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - manacore-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + # ============================================ + # Todo App + # ============================================ + + todo-backend: + image: ${DOCKER_REGISTRY:-ghcr.io/memo-2023}/todo-backend:${TODO_VERSION:-latest} + container_name: todo-backend-staging + restart: unless-stopped + depends_on: + mana-core-auth: + condition: service_healthy + postgres: + condition: service_healthy + environment: + NODE_ENV: staging + PORT: 3018 + DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@postgres:5432/todo + DB_HOST: postgres + DB_PORT: 5432 + DB_USER: ${POSTGRES_USER:-postgres} + MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + CORS_ORIGINS: http://46.224.108.214:5188,http://localhost:5188 + ports: + - "3018:3018" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3018/api/v1/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - manacore-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + todo-web: + image: ${DOCKER_REGISTRY:-ghcr.io/memo-2023}/todo-web:${TODO_WEB_VERSION:-latest} + container_name: todo-web-staging + restart: unless-stopped + depends_on: + todo-backend: + condition: service_healthy + environment: + NODE_ENV: staging + PORT: 5188 + PUBLIC_BACKEND_URL: http://todo-backend:3018 + PUBLIC_MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + PUBLIC_BACKEND_URL_CLIENT: http://46.224.108.214:3018 + PUBLIC_MANA_CORE_AUTH_URL_CLIENT: http://46.224.108.214:3001 + ports: + - "5188:5188" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5188/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - manacore-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + # ============================================ + # Calendar App + # ============================================ + + calendar-backend: + image: ${DOCKER_REGISTRY:-ghcr.io/memo-2023}/calendar-backend:${CALENDAR_VERSION:-latest} + container_name: calendar-backend-staging + restart: unless-stopped + depends_on: + mana-core-auth: + condition: service_healthy + postgres: + condition: service_healthy + environment: + NODE_ENV: staging + PORT: 3016 + DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@postgres:5432/calendar + DB_HOST: postgres + DB_PORT: 5432 + DB_USER: ${POSTGRES_USER:-postgres} + MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + CORS_ORIGINS: http://46.224.108.214:5186,http://localhost:5186 + ports: + - "3016:3016" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3016/api/v1/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - manacore-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + calendar-web: + image: ${DOCKER_REGISTRY:-ghcr.io/memo-2023}/calendar-web:${CALENDAR_WEB_VERSION:-latest} + container_name: calendar-web-staging + restart: unless-stopped + depends_on: + calendar-backend: + condition: service_healthy + environment: + NODE_ENV: staging + PORT: 5186 + PUBLIC_BACKEND_URL: http://calendar-backend:3016 + PUBLIC_MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + PUBLIC_BACKEND_URL_CLIENT: http://46.224.108.214:3016 + PUBLIC_MANA_CORE_AUTH_URL_CLIENT: http://46.224.108.214:3001 + ports: + - "5186:5186" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5186/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - manacore-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + # ============================================ + # Clock App + # ============================================ + + clock-backend: + image: ${DOCKER_REGISTRY:-ghcr.io/memo-2023}/clock-backend:${CLOCK_VERSION:-latest} + container_name: clock-backend-staging + restart: unless-stopped + depends_on: + mana-core-auth: + condition: service_healthy + postgres: + condition: service_healthy + environment: + NODE_ENV: staging + PORT: 3017 + DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@postgres:5432/clock + DB_HOST: postgres + DB_PORT: 5432 + DB_USER: ${POSTGRES_USER:-postgres} + MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + CORS_ORIGINS: http://46.224.108.214:5187,http://localhost:5187 + ports: + - "3017:3017" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3017/api/v1/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - manacore-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + clock-web: + image: ${DOCKER_REGISTRY:-ghcr.io/memo-2023}/clock-web:${CLOCK_WEB_VERSION:-latest} + container_name: clock-web-staging + restart: unless-stopped + depends_on: + clock-backend: + condition: service_healthy + environment: + NODE_ENV: staging + PORT: 5187 + PUBLIC_BACKEND_URL: http://clock-backend:3017 + PUBLIC_MANA_CORE_AUTH_URL: http://mana-core-auth:3001 + PUBLIC_BACKEND_URL_CLIENT: http://46.224.108.214:3017 + PUBLIC_MANA_CORE_AUTH_URL_CLIENT: http://46.224.108.214:3001 + ports: + - "5187:5187" + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5187/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - manacore-network + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + # ============================================ # Networks # ============================================