Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
40da583
Refactor Docker workflow to build and push image
Harish-Naruto Jun 23, 2026
a2ea3c0
Update Docker image workflow with persist-credentials
Harish-Naruto Jun 23, 2026
3bf578c
Merge pull request #76 from call-0f-code/docker-worflow
Harish-Naruto Jun 23, 2026
5be76b9
refactor: remove legacy database dump, local setup scripts, and assoc…
Harish-Naruto Jun 23, 2026
ae9b53a
Merge branch 'main' of https://github.com/call-0f-code/COC-API into f…
Harish-Naruto Jun 23, 2026
cec5ef4
Merge pull request #77 from call-0f-code/fuck/local-dev
callofcode07 Jun 23, 2026
30814e6
feat: add docker-compose configurations for full stack development en…
Harish-Naruto Jun 24, 2026
5d5d9c3
Merge pull request #78 from call-0f-code/complete/local-dev
Harish-Naruto Jun 24, 2026
2722de2
feat: add docker-compose configuration to orchestrate API and platfor…
Harish-Naruto Jun 24, 2026
085162b
feat: add master docker-compose stack for running all platforms simul…
Harish-Naruto Jun 24, 2026
d4d3eb4
chore: inject VITE_API_URL environment variable into admin and member…
Harish-Naruto Jun 24, 2026
2ca2d11
Merge pull request #79 from call-0f-code/add/local-dev
Harish-Naruto Jun 24, 2026
a8296b7
Add routes for birthday mail service
Sherin-2711 Oct 21, 2026
8cca9d0
fix: address review feedback on birthday email API
i-am-that-guy Oct 21, 2026
0f5bfdf
fix: accept UNCERTAIN failures and tighten birthday API input
i-am-that-guy Oct 21, 2026
f1055fd
refactor: simplify birthday email service
i-am-that-guy Oct 21, 2026
a23d0f7
Merge pull request #81 from call-0f-code/birthday-feature
i-am-that-guy Oct 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Dependencies
node_modules
bun.lockb
bun.lock

# Build outputs
dist
Expand All @@ -9,8 +9,7 @@ build

# Environment files
.env
.env.local
.env.*.local
.env.*

# Logs
logs
Expand Down
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ SUPABASE_SERVICE_ROLE_KEY=
# Environment variables for the application
NODE_ENV=development

# Service-to-service internal authentication secret (used by codenest backend)
INTERNAL_SERVICE_SECRET=

33 changes: 33 additions & 0 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Docker Image CI

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
build-and-push:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Log in to Docker Hub
if: github.event_name == 'push'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: ${{ github.event_name == 'push' }}
tags: callofcode07/coc-api:latest

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ web_modules/
# dotenv environment variable files
.env
.env.*
!.env.local.*.example
!.env.example

# parcel-bundler cache (https://parceljs.org/)
Expand Down
269 changes: 269 additions & 0 deletions DOCKER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
# 🐳 Docker — Local Development Guide

This guide covers everything you need to run any part of the Call of Code platform locally using Docker Compose.

---

## Overview

The repository ships with **five Docker Compose configurations**:

| File | Purpose | Services |
|------|---------|----------|
| `docker-compose.yml` | **API-only** dev (standalone) | `coc-api` |
| `docker/docker-compose.yml` | **All platforms** master stack | all 6 services |
| `docker/coc-member/docker-compose.yml` | Full **COC Member** stack | `coc-api` + `server` + `web` |
| `docker/coc-admin/docker-compose.yml` | Full **COC Admin** stack | `coc-api` + `server` + `web` |
| `docker/callofcode.in/docker-compose.yml` | Full **callofcode.in** website stack | `coc-api` + `frontend` |

> All platform stacks build `coc-api` locally from the repo root `Dockerfile` and pull their respective frontend/backend images from Docker Hub.

---

## Prerequisites

- [Docker Desktop](https://docs.docker.com/get-docker/) or Docker Engine + Docker Compose plugin (v2.22+)
- Git

No need to install Bun, Node, or any other runtime locally — everything runs inside containers.

---

## Environment Setup

### 1. API environment (required by all stacks)

Copy the example and fill in your Supabase credentials:

```bash
cp .env.example .env.local
```

| Variable | Description |
|----------|-------------|
| `DATABASE_URL` | Supabase connection-pooling URL (Prisma runtime) |
| `DIRECT_URL` | Direct DB connection URL (Prisma Migrate) |
| `SUPABASE_URL` | Your Supabase project URL |
| `SUPABASE_SERVICE_ROLE_KEY` | Supabase service-role secret key |

### 2. Platform-specific environments

Each platform directory ships **example files** with all variables documented and placeholder values. Copy and fill in only the secrets you need:

```bash
# COC Member
cp docker/coc-member/.env.local.backend.example docker/coc-member/.env.local.backend
cp docker/coc-member/.env.local.frontend.example docker/coc-member/.env.local.frontend

# COC Admin
cp docker/coc-admin/.env.local.backend.example docker/coc-admin/.env.local.backend
cp docker/coc-admin/.env.local.frontend.example docker/coc-admin/.env.local.frontend

# callofcode.in
cp docker/callofcode.in/.env.local.frontend.example docker/callofcode.in/.env.local.frontend
```

| Platform | File | Key Variables |
|----------|------|---------------|
| All backends | `.env.local.backend` | `JWT_SECRET`, `REFRESH_SECRET`, `RESEND_API_KEY` |
| `coc-admin` backend | `.env.local.backend` | + `WHATSAPP_LINK`, `DISCORD_LINK` |
| `coc-member` frontend | `.env.local.frontend` | `VITE_API_URL` |
| `coc-admin` frontend | `.env.local.frontend` | `VITE_API_URL`, `VITE_GIF_URL` |
| `callofcode.in` frontend | `.env.local.frontend` | `API_BASE_URL`, `GITHUB_TOKEN` (optional) |

> **Never commit real secrets.** All `*.env.local*` files are git-ignored by default.

---

## Running the Stacks

### All platforms together (master stack)

Use this when you need all three platforms running simultaneously (e.g. testing cross-platform API behaviour or running the full suite locally):

```bash
# From the repo root — watch mode recommended
docker compose -f docker/docker-compose.yml up --watch

# Or standard mode
docker compose -f docker/docker-compose.yml up --build
```

All six services share a single `coc-network` bridge and a single `coc-api` instance:

| Service | Container | Host port | Override env var |
|---------|-----------|-----------|------------------|
| `coc-api` | `3000` | **3000** | `COC_API_PORT` |
| `callofcode-frontend` | `3001` | **3001** | `CALLOFCODE_PORT` |
| `coc-admin-server` | `8000` | **8001** | `COC_ADMIN_BACKEND_PORT` |
| `coc-admin-web` | `5173` | **5174** | `COC_ADMIN_FRONTEND_PORT` |
| `coc-member-server` | `8000` | **8002** | `COC_MEMBER_BACKEND_PORT` |
| `coc-member-web` | `5173` | **5175** | `COC_MEMBER_FRONTEND_PORT` |

> **Port remapping**: because `coc-admin` and `coc-member` both internally bind `8000` and `5173`, the master stack remaps them to unique host ports to avoid conflicts. Internal service-to-service communication (`API_URL=http://coc-api:3000`) still uses the original container ports.

> **Env files required**: make sure all six env files exist before starting (see [Environment Setup](#environment-setup) above).

---

### API-only (standalone development)

Use this when you're only working on the `coc-api` itself:

```bash
# Standard mode
docker compose up --build

# Watch mode — Docker syncs src/ changes and restarts bun automatically
docker compose watch
```

The API will be available at **http://localhost:3000**

Health check: **http://localhost:3000/health**

---

### COC Member stack

```bash
cd docker/coc-member
docker compose up --build
```

| Service | URL |
|---------|-----|
| `coc-api` | http://localhost:3000 |
| `server` (member backend) | http://localhost:8000 |
| `web` (member frontend) | http://localhost:5173 |

---

### COC Admin stack

```bash
cd docker/coc-admin
docker compose up --build
```

| Service | URL |
|---------|-----|
| `coc-api` | http://localhost:3000 |
| `server` (admin backend) | http://localhost:8000 |
| `web` (admin frontend) | http://localhost:5173 |

---

### callofcode.in website

```bash
cd docker/callofcode.in
docker compose up --build
```

| Service | URL |
|---------|-----|
| `coc-api` | http://localhost:3000 |
| `frontend` | http://localhost:3001 |

---

## Startup Order & Health Checks

All stacks use health-checked `depends_on` to ensure correct startup ordering:

```
coc-api (healthy) → server/backend (healthy) → web/frontend
```

The `coc-api` health check polls `GET /health` every 30 seconds with a 15-second grace period on startup. Downstream services only start once `coc-api` reports healthy.

---

## Hot Reload (API-only stack)

The root `docker-compose.yml` supports `docker compose watch` with the following rules:

| Path changed | Action |
|---|---|
| `src/**` | **Sync** — files copied into container instantly; `bun --watch` picks up the change |
| `package.json` / `bun.lock` | **Rebuild** — full image rebuild to reinstall dependencies |
| `prisma/**` | **Rebuild** — triggers `prisma generate` on next container start |

```bash
# Start in watch mode (preferred for API development)
docker compose watch
```

---

## Common Commands

```bash
# Start in the background (detached)
docker compose up -d --build

# Follow logs
docker compose logs -f

# Follow logs for a specific service
docker compose logs -f coc-api

# Stop all containers
docker compose down

# Stop and remove volumes (clean slate)
docker compose down -v

# Rebuild a single service without restarting others
docker compose build coc-api

# Open a shell inside a running container
docker compose exec coc-api sh

# Run Prisma Studio (from inside the coc-api container)
docker compose exec coc-api bunx prisma studio
```

---

## Dockerfile Stages

The root `Dockerfile` uses a multi-stage build:

| Stage | Target | Purpose |
|-------|--------|---------|
| `deps` | — | Installs production dependencies only |
| `builder` | `target: builder` | Installs all deps + generates Prisma client; **used by all dev compose files** |
| `runner` | — | Lean production image; runs as non-root `cocuser` |

The dev compose files use `target: builder` so that devDependencies and the Prisma CLI are available inside the container.

---

## Troubleshooting

**`open Dockerfile: no such file or directory`**
The `dockerfile:` path in compose is relative to the `context`, not the compose file. Our configs set `context: ../..` (repo root) so `dockerfile: Dockerfile` resolves correctly.

**Port already in use**
For the individual stacks, set a custom port via the `PORT` env variable:
```bash
PORT=3001 docker compose up
```
For the master stack, override the specific service port:
```bash
COC_API_PORT=3010 COC_ADMIN_BACKEND_PORT=8010 docker compose -f docker/docker-compose.yml up
```

**Prisma migration errors on startup**
The `coc-api` container runs `prisma migrate deploy` on every start. If the DB is unreachable, the container will exit. Verify your `DATABASE_URL` and `DIRECT_URL` in `.env.local`.

**Container exits immediately after `healthy`**
Check logs with `docker compose logs coc-api`. Common causes: missing env vars or a failed migration.

**Stale node_modules in container**
The anonymous volume `/app/node_modules` is intentionally excluded from the host mount to avoid cross-OS binary conflicts. If you change `package.json`, let Docker rebuild:
```bash
docker compose build --no-cache coc-api
```
Loading
Loading