Add Docker deployment support for API and Web services
- Add Dockerfiles for API and Web apps with multi-stage builds. - Configure `docker-compose.yml` to manage services (Postgres, API, Web, pgAdmin). - Add `.dockerignore` for optimized builds. - Include `DOCKER_SETUP.md` for deployment steps and guidance.main
parent
8bb8fb8dba
commit
4bc2454f44
|
|
@ -0,0 +1,19 @@
|
|||
# Dependency
|
||||
node_modules
|
||||
dist
|
||||
.svelte-kit
|
||||
build
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Docker
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
.dockerignore
|
||||
|
|
@ -4,19 +4,7 @@
|
|||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="6c8b3c54-eabb-40e5-967f-c7b594c750bc" name="Changes" comment="Add user profile management with avatar upload and update support - Create `+page.svelte` for managing user profiles, including name, avatar, and password updates. - Add `Avatar.svelte` component for rendering user avatars with Gravatar and fallback initials support. - Implement backend APIs for fetching and updating user profiles (`/users/profile`). - Add support for avatar uploads with file validation (max size: 5MB). - Update `FloorplanViewer.svelte` to display user names and avatars in reservations. - Introduce utilities for Gravatar URLs and user avatar management (`getGravatarUrl`, `getInitials`).">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/apps/api/prisma/schema.prisma" beforeDir="false" afterPath="$PROJECT_DIR$/apps/api/prisma/schema.prisma" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/apps/api/src/organizations/dto/update-organization.dto.ts" beforeDir="false" afterPath="$PROJECT_DIR$/apps/api/src/organizations/dto/update-organization.dto.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/apps/api/src/users/users.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/apps/api/src/users/users.service.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/apps/web/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/apps/web/package.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/apps/web/src/lib/components/BookingModal.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/apps/web/src/lib/components/BookingModal.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/apps/web/src/lib/stores/organization.ts" beforeDir="false" afterPath="$PROJECT_DIR$/apps/web/src/lib/stores/organization.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/apps/web/src/routes/+layout.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/apps/web/src/routes/+layout.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/apps/web/src/routes/admin/organization/+page.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/apps/web/src/routes/admin/organization/+page.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/apps/web/src/routes/dashboard/+page.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/apps/web/src/routes/dashboard/+page.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/apps/web/src/routes/dashboard/my-bookings/+page.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/apps/web/src/routes/dashboard/my-bookings/+page.svelte" afterDir="false" />
|
||||
</list>
|
||||
<list default="true" id="6c8b3c54-eabb-40e5-967f-c7b594c750bc" name="Changes" comment="Update prompts to include progress indicator for documentation readability" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
|
|
@ -137,7 +125,7 @@
|
|||
<updated>1774643312599</updated>
|
||||
<workItem from="1774643313611" duration="74000" />
|
||||
<workItem from="1774643422240" duration="5278000" />
|
||||
<workItem from="1774706361502" duration="9064000" />
|
||||
<workItem from="1774706361502" duration="9383000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="Initialize Hot Desking app with web and API services - Set up SvelteKit for the web interface with Tailwind CSS. - Build the API using NestJS with Prisma ORM for database interaction. - Add environment variable management and docker-compose for PostgreSQL and PgAdmin instances. - Create shared data models for consistent typing across services. - Establish basic routing and layouts for web and API services.">
|
||||
<option name="closed" value="true" />
|
||||
|
|
@ -267,7 +255,23 @@
|
|||
<option name="project" value="LOCAL" />
|
||||
<updated>1774714977147</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="17" />
|
||||
<task id="LOCAL-00017" summary="Add i18n support with English and Spanish translations - Introduce `svelte-i18n` for internationalization. - Add English (`en.json`) and Spanish (`es-ES.json`) locale files. - Implement `setupI18n` function for initializing and managing locales. - Update project dependencies to include `svelte-i18n`.">
|
||||
<option name="closed" value="true" />
|
||||
<created>1774715653258</created>
|
||||
<option name="number" value="00017" />
|
||||
<option name="presentableId" value="LOCAL-00017" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1774715653258</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00018" summary="Update prompts to include progress indicator for documentation readability">
|
||||
<option name="closed" value="true" />
|
||||
<created>1774715728737</created>
|
||||
<option name="number" value="00018" />
|
||||
<option name="presentableId" value="LOCAL-00018" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1774715728737</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="19" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
|
|
@ -292,6 +296,8 @@
|
|||
<MESSAGE value="Add organization management with logo support - Implement organization settings page (`+page.svelte`) for updating organization name and logo. - Create backend APIs for retrieving and updating organization details with role-based access control. - Add `OrganizationsModule`, `OrganizationsService`, and DTOs for input validation in NestJS. - Update Prisma schema to include `logoUrl` field for organizations. - Enhance navigation to dynamically display organization logo and name." />
|
||||
<MESSAGE value="Add assets module with file upload and retrieval support - Introduce `AssetsModule` with APIs for uploading and retrieving organization logos, building images, and floor plans. - Implement file validation for type and size (10MB max). - Add `resolveAssetUrl` utility for generating absolute asset URLs. - Enhance admin UI components to support image file uploads and previews. - Update Prisma schema to associate assets with organizations, buildings, and floors. - Modify existing update logic to clear references when external URLs are used." />
|
||||
<MESSAGE value="Add user profile management with avatar upload and update support - Create `+page.svelte` for managing user profiles, including name, avatar, and password updates. - Add `Avatar.svelte` component for rendering user avatars with Gravatar and fallback initials support. - Implement backend APIs for fetching and updating user profiles (`/users/profile`). - Add support for avatar uploads with file validation (max size: 5MB). - Update `FloorplanViewer.svelte` to display user names and avatars in reservations. - Introduce utilities for Gravatar URLs and user avatar management (`getGravatarUrl`, `getInitials`)." />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Add user profile management with avatar upload and update support - Create `+page.svelte` for managing user profiles, including name, avatar, and password updates. - Add `Avatar.svelte` component for rendering user avatars with Gravatar and fallback initials support. - Implement backend APIs for fetching and updating user profiles (`/users/profile`). - Add support for avatar uploads with file validation (max size: 5MB). - Update `FloorplanViewer.svelte` to display user names and avatars in reservations. - Introduce utilities for Gravatar URLs and user avatar management (`getGravatarUrl`, `getInitials`)." />
|
||||
<MESSAGE value="Add i18n support with English and Spanish translations - Introduce `svelte-i18n` for internationalization. - Add English (`en.json`) and Spanish (`es-ES.json`) locale files. - Implement `setupI18n` function for initializing and managing locales. - Update project dependencies to include `svelte-i18n`." />
|
||||
<MESSAGE value="Update prompts to include progress indicator for documentation readability" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Update prompts to include progress indicator for documentation readability" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
# Docker Setup Guide
|
||||
|
||||
This guide describes how to deploy the application using Docker and Docker Compose.
|
||||
|
||||
## Prerequisites
|
||||
- Docker (20.10+)
|
||||
- Docker Compose (v2.0+)
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Create a `.env` file in the root directory. The following variables are supported (with their default values shown):
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `DB_USER` | PostgreSQL username | `postgres` |
|
||||
| `DB_PASSWORD` | PostgreSQL password | `postgres` |
|
||||
| `DB_NAME` | PostgreSQL database name | `hotdesking` |
|
||||
| `DB_PORT_EXTERNAL` | External port for PostgreSQL | `5433` |
|
||||
| `API_PORT_EXTERNAL` | External port for the API | `3000` |
|
||||
| `WEB_PORT_EXTERNAL` | External port for the Web app | `5173` |
|
||||
| `JWT_SECRET` | Secret key for JWT signing | `super-secret-change-me` |
|
||||
| `WEB_ORIGIN` | The origin of the web app (required by SvelteKit) | `http://localhost:5173` |
|
||||
| `VITE_API_BASE_URL` | The URL of the API (for the web app) | `http://localhost:3000` |
|
||||
|
||||
## Deployment Steps
|
||||
|
||||
1. **Build and start the containers:**
|
||||
```bash
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
2. **Run Database Migrations:**
|
||||
Since the API uses Prisma, you need to run migrations to set up the database schema:
|
||||
```bash
|
||||
docker exec -it hotdesking_api npx prisma migrate deploy
|
||||
```
|
||||
|
||||
3. **(Optional) Seed the Database:**
|
||||
If you have a seed script defined in `apps/api/prisma/seed.ts`:
|
||||
```bash
|
||||
docker exec -it hotdesking_api npx prisma db seed
|
||||
```
|
||||
|
||||
4. **Access the Applications:**
|
||||
- Web App: [http://localhost:5173](http://localhost:5173)
|
||||
- API: [http://localhost:3000](http://localhost:3000)
|
||||
- pgAdmin: [http://localhost:5051](http://localhost:5051) (Login: `admin@local.dev` / `admin`)
|
||||
|
||||
## Development with Docker
|
||||
|
||||
To watch logs:
|
||||
```bash
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
To stop the applications:
|
||||
```bash
|
||||
docker-compose down
|
||||
```
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
FROM node:20-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy root configs
|
||||
COPY package*.json ./
|
||||
COPY tsconfig.json ./
|
||||
COPY tsconfig.base.json ./
|
||||
|
||||
# Copy packages
|
||||
COPY apps/api/package*.json ./apps/api/
|
||||
COPY shared/package*.json ./shared/
|
||||
|
||||
# Install dependencies (using npm ci for better builds)
|
||||
RUN npm ci
|
||||
|
||||
# Copy source code
|
||||
COPY apps/api ./apps/api
|
||||
COPY shared ./shared
|
||||
|
||||
# Generate Prisma client
|
||||
WORKDIR /app/apps/api
|
||||
RUN npx prisma generate
|
||||
|
||||
# Build the app
|
||||
RUN npm run build
|
||||
|
||||
# ---
|
||||
FROM node:20-alpine AS runner
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy build artifacts and necessary files
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY --from=builder /app/apps/api/node_modules ./apps/api/node_modules
|
||||
COPY --from=builder /app/apps/api/dist ./apps/api/dist
|
||||
COPY --from=builder /app/apps/api/package.json ./apps/api/package.json
|
||||
COPY --from=builder /app/apps/api/prisma ./apps/api/prisma
|
||||
COPY --from=builder /app/shared/dist ./shared/dist
|
||||
COPY --from=builder /app/shared/package.json ./shared/package.json
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT=3000
|
||||
ENV NODE_ENV=production
|
||||
|
||||
WORKDIR /app/apps/api
|
||||
CMD ["node", "dist/main"]
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
FROM node:20-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy root configs
|
||||
COPY package*.json ./
|
||||
COPY tsconfig.json ./
|
||||
COPY tsconfig.base.json ./
|
||||
|
||||
# Copy packages
|
||||
COPY apps/web/package*.json ./apps/web/
|
||||
COPY shared/package*.json ./shared/
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci
|
||||
|
||||
# Copy source code
|
||||
COPY apps/web ./apps/web
|
||||
COPY shared ./shared
|
||||
|
||||
# Build the app
|
||||
WORKDIR /app/apps/web
|
||||
# We need VITE_API_BASE_URL at build time for SvelteKit static replacements if any,
|
||||
# but usually it's better to use dynamic env vars if possible.
|
||||
# For now, let's assume it can be provided during build or we use the default.
|
||||
RUN npm run build
|
||||
|
||||
# ---
|
||||
FROM node:20-alpine AS runner
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy build artifacts and necessary files
|
||||
COPY --from=builder /app/apps/web/build ./apps/web/build
|
||||
COPY --from=builder /app/apps/web/package.json ./apps/web/package.json
|
||||
# Node adapter needs dependencies to run
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
|
||||
EXPOSE 5173
|
||||
|
||||
ENV PORT=5173
|
||||
ENV NODE_ENV=production
|
||||
|
||||
WORKDIR /app/apps/web
|
||||
CMD ["node", "build"]
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^3.3.1",
|
||||
"@sveltejs/adapter-node": "^5.2.11",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
||||
"autoprefixer": "^10.4.0",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import adapter from '@sveltejs/adapter-auto';
|
||||
import adapter from '@sveltejs/adapter-node';
|
||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
|
|
|
|||
|
|
@ -1,19 +1,47 @@
|
|||
version: "3.9"
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16
|
||||
container_name: hotdesking_postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: hotdesking
|
||||
POSTGRES_USER: ${DB_USER:-postgres}
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
|
||||
POSTGRES_DB: ${DB_NAME:-hotdesking}
|
||||
ports:
|
||||
- "5433:5432"
|
||||
- "${DB_PORT_EXTERNAL:-5433}:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
||||
api:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: apps/api/Dockerfile
|
||||
container_name: hotdesking_api
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${API_PORT_EXTERNAL:-3000}:3000"
|
||||
environment:
|
||||
DATABASE_URL: "postgresql://${DB_USER:-postgres}:${DB_PASSWORD:-postgres}@postgres:5432/${DB_NAME:-hotdesking}"
|
||||
PORT: 3000
|
||||
JWT_SECRET: ${JWT_SECRET:-super-secret-change-me}
|
||||
depends_on:
|
||||
- postgres
|
||||
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: apps/web/Dockerfile
|
||||
container_name: hotdesking_web
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${WEB_PORT_EXTERNAL:-5173}:5173"
|
||||
environment:
|
||||
PORT: 5173
|
||||
ORIGIN: ${WEB_ORIGIN:-http://localhost:5173}
|
||||
VITE_API_BASE_URL: ${VITE_API_BASE_URL:-http://localhost:3000}
|
||||
depends_on:
|
||||
- api
|
||||
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4:8
|
||||
container_name: hotdesking_pgadmin
|
||||
|
|
|
|||
Loading…
Reference in New Issue