Overview
Tambo360 includes complete Docker configuration for both development and production environments. This guide covers setting up and running the application using Docker containers.
Docker simplifies deployment by containerizing the backend, frontend, and database into isolated, reproducible environments.
Prerequisites
Docker Version 20.10 or higher
Docker Compose Version 2.0 or higher
Install Docker
# Ubuntu/Debian
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add user to docker group
sudo usermod -aG docker $USER
newgrp docker
Download and install Docker Desktop for Windows Ensure WSL2 is enabled for optimal performance on Windows.
Verify Docker Installation
docker --version
# Docker version 20.10.x or higher
docker compose version
# Docker Compose version 2.x.x or higher
Docker Architecture
Tambo360’s Docker setup includes three main services:
Services Configuration
Service Container Name Port Base Image Database tambo-db5433:5432 postgres:15Backend Auto-generated 3000:3000 node:20-slimFrontend Auto-generated 5173:5173 node:18-alpine
Docker Compose Configuration
The docker-compose.yml file defines the complete application stack:
version : '3.8'
services :
db :
image : postgres:15
container_name : tambo-db
restart : always
environment :
POSTGRES_USER : postgres
POSTGRES_PASSWORD : tambo360
POSTGRES_DB : tambo
ports :
- "5433:5432"
volumes :
- postgres_data:/var/lib/postgresql/data
backend :
build :
context : ./apps/backend
target : development
ports :
- "3000:3000"
environment :
- NODE_ENV=${NODE_ENV}
- PORT=${PORT}
- DATABASE_URL=${DATABASE_URL}
- JWT_SECRET=${JWT_SECRET}
- FRONTEND_URL=${FRONTEND_URL}
volumes :
- ./apps/backend:/app
- /app/node_modules
depends_on :
- db
frontend :
build :
context : ./apps/frontend
target : development
ports :
- "5173:5173"
environment :
- VITE_API_URL=http://localhost:3000/api
volumes :
- ./apps/frontend:/app
- /app/node_modules
depends_on :
- backend
volumes :
postgres_data :
networks :
default :
name : example-auth-network
Backend Dockerfile
The backend uses a multi-stage Dockerfile for optimal image sizes:
# -------- BASE --------
FROM node:20-slim AS base
RUN apt-get update -y \
&& apt-get install -y openssl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY package*.json ./
# -------- DEVELOPMENT --------
FROM base AS development
RUN npm install
COPY . .
EXPOSE 3000
CMD [ "sh" , "-c" , "npx prisma generate && npx prisma migrate deploy && npm run dev" ]
# -------- BUILD --------
FROM base AS build
RUN npm install
COPY . .
RUN npx prisma generate
RUN npm run build
# -------- PRODUCTION --------
FROM node:20-slim AS production
RUN apt-get update -y \
&& apt-get install -y openssl ca-certificates \
&& update-ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY package*.json ./
RUN npm install --omit=dev
COPY prisma ./prisma
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules/.prisma ./node_modules/.prisma
ENV NODE_ENV=production
EXPOSE 3000
CMD [ "node" , "dist/server.js" ]
Build Stages Explained
Uses Node.js 20 slim image
Installs OpenSSL (required for Prisma)
Sets up working directory
Copies package files
Installs all dependencies including devDependencies
Generates Prisma client
Runs database migrations
Starts development server with hot reload
Compiles TypeScript to JavaScript
Generates optimized Prisma client
Prepares production artifacts
Uses minimal Node.js image
Installs only production dependencies
Copies compiled code from build stage
Runs compiled JavaScript (not TypeScript)
Frontend Dockerfile
The frontend also uses multi-stage builds with different targets:
FROM node:18-alpine AS base
WORKDIR /app
COPY package*.json pnpm-lock.yaml* ./
RUN npm install -g pnpm
RUN pnpm install --frozen-lockfile && pnpm store prune
# Development stage
FROM base AS development
COPY . .
EXPOSE 5173
CMD [ "pnpm" , "run" , "dev" ]
# Build stage
FROM base AS build
COPY . .
RUN pnpm run build
# Production stage
FROM nginx:alpine AS production
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1
CMD [ "nginx" , "-g" , "daemon off;" ]
The production frontend uses Nginx to serve static files efficiently.
Running with Docker Compose
Development Environment
Create environment file
Create a .env file in the root directory: NODE_ENV = development
PORT = 3000
DATABASE_URL = postgresql://postgres:tambo360@db:5432/tambo
JWT_SECRET = your-secret-key-change-in-production
FRONTEND_URL = http://localhost:5173
EMAIL_USER = [email protected]
EMAIL_PASS = your-app-password
Start all services
docker compose up --build
This command:
Builds Docker images for backend and frontend
Pulls the PostgreSQL 15 image
Creates a Docker network
Starts all containers
Streams logs to the console
Run in Detached Mode
To run containers in the background:
View Logs
# View all logs
docker compose logs -f
# View specific service logs
docker compose logs -f backend
docker compose logs -f frontend
docker compose logs -f db
Stop Services
# Stop containers (preserves volumes)
docker compose stop
# Stop and remove containers
docker compose down
# Stop and remove containers + volumes (deletes database data)
docker compose down -v
Production Deployment
For production, use the production build targets:
Update docker-compose.yml for production
Uncomment the production backend service and modify environment variables: version : '3.8'
services :
backend :
build :
context : ./apps/backend
target : production
environment :
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:tambo360@db:5432/tambo
restart : always
frontend :
build :
context : ./apps/frontend
target : production
ports :
- "80:80"
restart : always
Build and run production containers
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Run database migrations
docker compose exec backend npx prisma migrate deploy
Always use secure passwords and secrets in production. Never commit .env files to version control.
Docker Commands Reference
Container Management
# List running containers
docker compose ps
# Restart a specific service
docker compose restart backend
# Execute command in running container
docker compose exec backend sh
# View container resource usage
docker stats
Image Management
# Rebuild images without cache
docker compose build --no-cache
# Pull latest base images
docker compose pull
# List all images
docker images
# Remove unused images
docker image prune -a
Volume Management
# List volumes
docker volume ls
# Inspect database volume
docker volume inspect tambo360_postgres_data
# Backup database volume
docker run --rm -v tambo360_postgres_data:/data -v $( pwd ) :/backup ubuntu tar czf /backup/db-backup.tar.gz /data
# Remove all unused volumes
docker volume prune
Health Checks
The backend includes a health check endpoint:
# Check backend health
curl http://localhost:3000/api/health
# View health status in Docker
docker inspect --format= '{{.State.Health.Status}}' < container-i d >
Troubleshooting
If ports 3000, 5173, or 5433 are already in use: # Find process using port
lsof -ti:3000 | xargs kill -9
# Or change ports in docker-compose.yml
ports:
- "3001:3000" # Use different host port
Database connection refused
Ensure the database service is running: docker compose ps db
docker compose logs db
# Restart database service
docker compose restart db
Prisma client not generated
Regenerate Prisma client inside the container: docker compose exec backend npx prisma generate
docker compose restart backend
On Linux, you may need to fix permissions: sudo chown -R $USER : $USER ./apps
Container keeps restarting
Check container logs for errors: docker compose logs --tail=100 backend
# View exit code
docker compose ps
Best Practices
Use .dockerignore Exclude node_modules, .git, and other unnecessary files from the build context.
Multi-stage Builds Keep production images small by using multi-stage builds and only copying necessary artifacts.
Health Checks Implement health checks for automatic container restart on failures.
Volume Backups Regularly backup database volumes before updates or migrations.
Next Steps
Database Setup Configure PostgreSQL and run migrations
Environment Variables Complete configuration reference
Deployment Deploy to production platforms