Skip to content

Commit 957ba39

Browse files
committed
feat: add Docker support with multi-stage builds for frontend and backend; include .dockerignore and docker management script
1 parent f9cb89b commit 957ba39

File tree

8 files changed

+340
-24
lines changed

8 files changed

+340
-24
lines changed

.dockerignore

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Dependencies
2+
node_modules/
3+
npm-debug.log*
4+
yarn-debug.log*
5+
yarn-error.log*
6+
7+
# Build outputs
8+
dist/
9+
build/
10+
.next/
11+
12+
# Environment variables
13+
.env
14+
.env.local
15+
.env.development.local
16+
.env.test.local
17+
.env.production.local
18+
19+
# IDE
20+
.vscode/
21+
.idea/
22+
*.swp
23+
*.swo
24+
25+
# OS
26+
.DS_Store
27+
Thumbs.db
28+
29+
# Git
30+
.git/
31+
.gitignore
32+
33+
# Docker
34+
Dockerfile
35+
docker-compose.yml
36+
.dockerignore
37+
38+
# Logs
39+
logs/
40+
*.log
41+
42+
# Database
43+
data/
44+
45+
# Temporary files
46+
tmp/
47+
temp/

Dockerfile

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Multi-stage Dockerfile for monorepo
2+
# This is optional - docker-compose is the recommended approach
3+
4+
# Stage 1: Build Frontend
5+
FROM oven/bun:1 AS frontend-build
6+
WORKDIR /app
7+
8+
# Copy root dependencies and common folder
9+
COPY package*.json bun.lock ./
10+
COPY common/ ./common/
11+
12+
# Copy ALL workspace directories so bun can resolve workspaces
13+
COPY server/ ./server/
14+
COPY web/ ./web/
15+
16+
# Install dependencies from root
17+
RUN bun install
18+
19+
# Set working directory to web for build
20+
WORKDIR /app/web
21+
ARG VITE_BACKEND_URL=http://localhost:5000
22+
ENV VITE_BACKEND_URL=$VITE_BACKEND_URL
23+
RUN bun run build
24+
25+
# Stage 2: Build Backend
26+
FROM oven/bun:1 AS backend-build
27+
WORKDIR /app
28+
29+
# Copy root dependencies and common folder
30+
COPY package*.json bun.lock ./
31+
COPY common/ ./common/
32+
33+
# Copy ALL workspace directories so bun can resolve workspaces
34+
COPY server/ ./server/
35+
COPY web/ ./web/
36+
37+
# Install dependencies from root
38+
RUN bun install
39+
40+
# Stage 3: Production
41+
FROM oven/bun:1
42+
WORKDIR /app
43+
44+
# Install nginx and curl
45+
USER root
46+
RUN apt-get update && apt-get install -y nginx curl && rm -rf /var/lib/apt/lists/*
47+
48+
# Copy common folder to production image
49+
COPY common/ ./common/
50+
51+
# Copy backend from build stage
52+
COPY --from=backend-build /app/server /app/server
53+
WORKDIR /app/server
54+
RUN mkdir -p public/uploads
55+
56+
# Copy frontend build to nginx
57+
COPY --from=frontend-build /app/web/dist /usr/share/nginx/html
58+
COPY web/nginx.conf /etc/nginx/conf.d/default.conf
59+
60+
# Create startup script
61+
RUN echo '#!/bin/sh' > /app/start.sh && \
62+
echo 'nginx &' >> /app/start.sh && \
63+
echo 'cd /app/server && bun run dev' >> /app/start.sh && \
64+
chmod +x /app/start.sh
65+
66+
# Switch back to bun user
67+
USER bun
68+
69+
EXPOSE 80 5000
70+
71+
CMD ["/app/start.sh"]

docker-compose.yml

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,78 @@
11
version: '3.8'
2+
23
services:
4+
# PostgreSQL Database
35
db:
4-
image: postgres
6+
image: postgres:15-alpine
57
restart: always
68
environment:
79
POSTGRES_USER: postgres
810
POSTGRES_PASSWORD: password
911
POSTGRES_DB: rchat
1012
volumes:
11-
- ./data:/var/lib/postgresql/data
13+
- postgres_data:/var/lib/postgresql/data
1214
ports:
13-
- 5432:5432
15+
- "5432:5432"
16+
healthcheck:
17+
test: ["CMD-SHELL", "pg_isready -U postgres"]
18+
interval: 30s
19+
timeout: 10s
20+
retries: 3
1421

22+
# Redis Cache
1523
redis:
1624
image: redis
1725
restart: always
1826
ports:
19-
- 6379:6379
27+
- "6379:6379"
28+
healthcheck:
29+
test: ["CMD", "redis-cli", "ping"]
30+
interval: 30s
31+
timeout: 10s
32+
retries: 3
33+
34+
# # Backend API Server
35+
# backend:
36+
# build:
37+
# context: .
38+
# dockerfile: server/Dockerfile
39+
# restart: always
40+
# ports:
41+
# - "5000:5000"
42+
# environment:
43+
# - NODE_ENV=development
44+
# - DATABASE_URL=postgresql://postgres:password@localhost:5432/rchat
45+
# - FRONTEND_URL=http://localhost:3000
46+
# volumes:
47+
# - ./server/public/uploads:/app/server/public/uploads
48+
# - ./common:/app/common:ro
49+
# depends_on:
50+
# db:
51+
# condition: service_healthy
52+
# redis:
53+
# condition: service_healthy
54+
# healthcheck:
55+
# test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
56+
# interval: 30s
57+
# timeout: 10s
58+
# retries: 3
59+
60+
# Frontend Web Application
61+
frontend:
62+
build:
63+
context: .
64+
dockerfile: web/Dockerfile
65+
args:
66+
VITE_BACKEND_URL: http://localhost:5000
67+
restart: always
68+
ports:
69+
- "3000:80"
70+
healthcheck:
71+
test: ["CMD", "curl", "-f", "http://localhost:80"]
72+
interval: 30s
73+
timeout: 10s
74+
retries: 3
75+
76+
volumes:
77+
postgres_data:
78+
redis_data:

docker.sh

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/bin/bash
2+
3+
# Docker management script for the chat application
4+
5+
case "$1" in
6+
"build")
7+
echo "Building all services..."
8+
docker-compose build
9+
;;
10+
"up")
11+
echo "Starting all services..."
12+
docker-compose up -d
13+
;;
14+
"down")
15+
echo "Stopping all services..."
16+
docker-compose down
17+
;;
18+
"logs")
19+
if [ -n "$2" ]; then
20+
echo "Showing logs for service: $2"
21+
docker-compose logs -f "$2"
22+
else
23+
echo "Showing logs for all services..."
24+
docker-compose logs -f
25+
fi
26+
;;
27+
"restart")
28+
echo "Restarting all services..."
29+
docker-compose restart
30+
;;
31+
"clean")
32+
echo "Cleaning up containers, networks, and volumes..."
33+
docker-compose down -v
34+
docker system prune -f
35+
;;
36+
"dev")
37+
echo "Starting development environment..."
38+
docker-compose up --build
39+
;;
40+
*)
41+
echo "Usage: $0 {build|up|down|logs|restart|clean|dev}"
42+
echo ""
43+
echo "Commands:"
44+
echo " build - Build all Docker images"
45+
echo " up - Start all services in detached mode"
46+
echo " down - Stop all services"
47+
echo " logs - Show logs (optionally specify service name)"
48+
echo " restart - Restart all services"
49+
echo " clean - Clean up all containers, networks, and volumes"
50+
echo " dev - Start development environment with build"
51+
exit 1
52+
;;
53+
esac

server/.dockerignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
node_modules
2+
Dockerfile*
3+
docker-compose*
4+
.dockerignore
5+
.git
6+
.gitignore
7+
README.md
8+
LICENSE
9+
.vscode
10+
Makefile
11+
helm-charts
12+
.env
13+
.editorconfig
14+
.idea
15+
coverage*

server/Dockerfile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Backend Dockerfile for monorepo
2+
FROM oven/bun:1
3+
4+
# Set working directory to the root of the monorepo
5+
WORKDIR /app
6+
7+
# Copy root package.json and lockfile first for better caching
8+
COPY package*.json bun.lock ./
9+
10+
# Copy common folder (shared dependencies and types)
11+
COPY common/ ./common/
12+
13+
# Copy ALL workspace directories so bun can resolve workspaces
14+
COPY server/ ./server/
15+
COPY web/ ./web/
16+
17+
# Install dependencies from root (this handles all deps including shared ones)
18+
RUN bun install
19+
20+
# Set working directory to server
21+
WORKDIR /app/server
22+
23+
# Create uploads directory
24+
RUN mkdir -p public/uploads
25+
26+
# Expose port
27+
EXPOSE 5000
28+
29+
# Start the server (make sure common folder is available)
30+
CMD ["bun", "run", "dev"]

web/Dockerfile

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,41 @@
1-
FROM oven/bun:1 AS base
2-
WORKDIR /usr/src/app
3-
4-
# install dependencies into temp directory
5-
# this will cache them and speed up future builds
6-
FROM base AS install
7-
RUN mkdir -p /temp/dev
8-
COPY package.json bun.lockb /temp/dev/
9-
RUN cd /temp/dev && bun install
10-
11-
# copy node_modules from temp directory
12-
# then copy all (non-ignored) project files into the image
13-
FROM base AS prerelease
14-
COPY --from=install /temp/dev/node_modules node_modules
15-
COPY . .
16-
# COPY common ../common
17-
18-
ENV NODE_ENV=production
19-
RUN bun run build
1+
# Frontend Dockerfile for monorepo
2+
FROM oven/bun:1 AS build
3+
4+
# Set working directory to the root of the monorepo
5+
WORKDIR /app
6+
7+
# Copy root package.json and lockfile first for better caching
8+
COPY package*.json bun.lock ./
9+
10+
# Copy common folder (shared dependencies and types)
11+
COPY common/ ./common/
12+
13+
# Copy ALL workspace directories so bun can resolve workspaces
14+
COPY server/ ./server/
15+
COPY web/ ./web/
2016

17+
# Install dependencies from root (this handles all deps including shared ones)
18+
RUN bun install
2119

20+
# Set working directory to web for build
21+
WORKDIR /app/web
22+
23+
# Build the app (make sure common folder is available)
24+
ARG VITE_BACKEND_URL=http://localhost:5000
25+
ENV VITE_BACKEND_URL=$VITE_BACKEND_URL
26+
RUN bun run build
27+
28+
# Production stage with nginx
2229
FROM nginx:alpine
2330

24-
COPY --from=prerelease /usr/src/app/dist /usr/share/nginx/html
31+
# Copy built files to nginx
32+
COPY --from=build /app/web/dist /usr/share/nginx/html
2533

34+
# Copy nginx config
35+
COPY web/nginx.conf /etc/nginx/conf.d/default.conf
36+
37+
# Expose port
2638
EXPOSE 80
39+
40+
# Start nginx
2741
CMD ["nginx", "-g", "daemon off;"]

web/nginx.conf

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
server {
2+
listen 80;
3+
server_name localhost;
4+
5+
root /usr/share/nginx/html;
6+
index index.html index.htm;
7+
8+
# Handle client-side routing
9+
location / {
10+
try_files $uri $uri/ /index.html;
11+
}
12+
13+
# Static assets with cache headers
14+
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
15+
expires 1y;
16+
add_header Cache-Control "public, immutable";
17+
}
18+
19+
# Security headers
20+
add_header X-Frame-Options "SAMEORIGIN" always;
21+
add_header X-Content-Type-Options "nosniff" always;
22+
add_header X-XSS-Protection "1; mode=block" always;
23+
24+
# Gzip compression
25+
gzip on;
26+
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
27+
}

0 commit comments

Comments
 (0)