Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 36 additions & 2 deletions DOCKER.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ This guide covers everything you need to run any part of the Call of Code platfo

## Overview

The repository ships with **four Docker Compose configurations**:
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` |
Expand Down Expand Up @@ -76,6 +77,35 @@ cp docker/callofcode.in/.env.local.frontend.example docker/callofcode.in/.env.lo

## 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).
Comment on lines +103 to +105

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the blank line inside this blockquote.

That empty quoted line trips MD028 and will keep markdownlint failing.

🛠️ Suggested fix
 > **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).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
> **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).
> **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).
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 104-104: Blank line inside blockquote

(MD028, no-blanks-blockquote)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DOCKER.md` around lines 103 - 105, The blockquote in the Docker docs contains
an empty quoted line that triggers MD028. Update the quoted text in the affected
section so the two quoted paragraphs are adjacent without a blank blockquote
line, keeping the content in the same place and preserving the existing wording
in the DOCKER.md section.

Source: Linters/SAST tools


---

### API-only (standalone development)

Use this when you're only working on the `coc-api` itself:
Expand Down Expand Up @@ -217,10 +247,14 @@ The dev compose files use `target: builder` so that devDependencies and the Pris
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**
Set a custom port via the `PORT` env variable before running:
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
```
Comment on lines +250 to +257

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor

Scope the port override example to the compose file being used. PORT=3001 docker compose up only applies when run from the directory containing that compose file, or with an explicit -f, so call out that the nested platform stacks still need cd into their folder or a matching -f.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DOCKER.md` around lines 250 - 257, The port override example is too generic
for the individual stacks and should be scoped to the compose file actually
being used. Update the documentation around the `PORT` example to make it clear
that it only works when running from the directory containing that compose file
or when paired with an explicit `-f`, and note that the nested platform stacks
still require changing into their folder or using a matching `-f` just like the
`docker compose` example near the stack instructions.


**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`.
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ COC-API/
│ ├── SiteContent.test.ts
│ └── imageUtils.test.ts
├── docker/ # Platform-specific Docker Compose stacks
├── docker/ # Docker Compose stacks
│ ├── docker-compose.yml # ★ Master stack — all platforms together
│ ├── coc-member/ # Full COC Member platform stack
│ │ ├── docker-compose.yml
│ │ ├── .env.local.backend.example
Expand Down Expand Up @@ -145,9 +146,12 @@ bun install

### 4. Local development (Docker)

The project ships **four Docker Compose stacks**. Choose the one you need:
The project ships **five Docker Compose stacks**. Choose the one you need:

```bash
# ★ All platforms at once (recommended for full-stack development)
docker compose -f docker/docker-compose.yml up --watch

# API only (for coc-api development)
docker compose up --build

Expand Down
173 changes: 173 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# =============================================================================
# Master Docker Compose — All Platforms
# Runs coc-api + all three frontends/backends together on a single network.
#
# Usage:
# docker compose -f docker/docker-compose.yml up --watch
#
# Port map:
# 3000 → coc-api (shared API)
# 3001 → callofcode.in (frontend)
# 8001 → coc-admin backend
# 5174 → coc-admin frontend
# 8002 → coc-member backend
# 5175 → coc-member frontend
# =============================================================================

name: coc-all

services:

coc-api:
image: coc-api
build:
context: ..
dockerfile: Dockerfile
target: builder # builder stage has devDeps + bun --watch
restart: unless-stopped
ports:
- "${COC_API_PORT:-3000}:3000"
env_file:
- ../.env.local # Local dev env vars (Supabase connection strings, etc.)
environment:
NODE_ENV: development
volumes:
- ../:/app
- /app/node_modules
- /app/node_modules/.prisma
command: >
sh -c "bunx prisma generate &&
bunx prisma migrate deploy &&
bun --watch src/server.ts"
develop:
watch:
- path: ../src
action: sync
target: /app/src
- path: ../package.json
action: rebuild
- path: ../bun.lock
action: rebuild
- path: ../prisma
action: rebuild
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
networks:
- coc-network

# callofcode.in — main website frontend

callofcode-frontend:
image: callofcode07/callofcode:latest
pull_policy: missing
restart: unless-stopped
ports:
- "${CALLOFCODE_PORT:-3001}:3001"
env_file:
- callofcode.in/.env.local.frontend
Comment on lines +70 to +71

@coderabbitai coderabbitai Bot Jun 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether the referenced env files exist relative to docker/
for f in \
  docker/callofcode.in/.env.local.frontend \
  docker/coc-admin/.env.local.backend \
  docker/coc-admin/.env.local.frontend \
  docker/coc-member/.env.local.backend \
  docker/coc-member/.env.local.frontend \
  .env.local ; do
  if [ -e "$f" ]; then echo "FOUND: $f"; else echo "MISSING: $f"; fi
done
# Also surface any similarly named env files anywhere in the repo
fd -H -t f '.env.local'

Repository: call-0f-code/COC-API

Length of output: 641


🏁 Script executed:

#!/bin/bash
set -e
git ls-files docker/docker-compose.yml docker/callofcode.in/.env.local.frontend.example docker/coc-admin/.env.local.backend.example docker/coc-admin/.env.local.frontend.example docker/coc-member/.env.local.backend.example docker/coc-member/.env.local.frontend.example
printf '\n--- docker-compose excerpts ---\n'
sed -n '60,180p' docker/docker-compose.yml
printf '\n--- all env_file refs ---\n'
rg -n "env_file:|- \.env|\.env\.local" docker/docker-compose.yml docker -g '!**/.git/**'

Repository: call-0f-code/COC-API

Length of output: 6780


🏁 Script executed:

#!/bin/bash
set -e
git ls-files docker/docker-compose.yml docker/callofcode.in/.env.local.frontend.example docker/coc-admin/.env.local.backend.example docker/coc-admin/.env.local.frontend.example docker/coc-member/.env.local.backend.example docker/coc-member/.env.local.frontend.example
printf '\n--- docker-compose excerpts ---\n'
sed -n '60,180p' docker/docker-compose.yml
printf '\n--- all env_file refs ---\n'
rg -n "env_file:|- \.env|\.env\.local" docker/docker-compose.yml docker -g '!**/.git/**'

Repository: call-0f-code/COC-API

Length of output: 6780


🏁 Script executed:

#!/bin/bash
set -e
git ls-files docker/docker-compose.yml docker/callofcode.in/.env.local.frontend.example docker/coc-admin/.env.local.backend.example docker/coc-admin/.env.local.frontend.example docker/coc-member/.env.local.backend.example docker/coc-member/.env.local.frontend.example
printf '\n--- docker-compose excerpts ---\n'
sed -n '60,180p' docker/docker-compose.yml
printf '\n--- all env_file refs ---\n'
rg -n "env_file:|- \.env|\.env\.local" docker/docker-compose.yml docker -g '!**/.git/**'

Repository: call-0f-code/COC-API

Length of output: 6780


Add the missing .env.local.* files or point to the .example files.
These env_file entries resolve relative to docker/docker-compose.yml, and only the matching .example files exist under docker/. docker compose up will fail unless docker/callofcode.in/.env.local.frontend, docker/coc-admin/.env.local.backend, docker/coc-admin/.env.local.frontend, docker/coc-member/.env.local.backend, and docker/coc-member/.env.local.frontend are created.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docker/docker-compose.yml` around lines 70 - 71, The docker-compose env_file
entries point to missing local env files, so update the references in
docker-compose configuration to use the existing .example files or add the
corresponding .env.local.* files under docker/. Check the env_file blocks for
callofcode.in, coc-admin, and coc-member so they resolve correctly relative to
docker/docker-compose.yml and do not break docker compose up.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

us bro us

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@i-am-that-guy haha, fair enough! Just making sure no one on the team gets tripped up by a missing env file when spinning up the stack for the first time. 😄

Since those .env.local.* files are gitignored (as expected), it's worth either:

  1. Ensuring the .example counterparts (e.g., callofcode.in/.env.local.frontend.example) are up to date so devs know what to create, or
  2. Documenting the setup step in DOCKER.md — something like "Copy the .example files and fill in your values before running the master stack."

That way new contributors joining the team won't be left wondering why docker compose up fails immediately. Want me to open a follow-up issue to track this?

ʕ •ᴥ•ʔ

environment:
- NODE_ENV=development
- API_BASE_URL=http://coc-api:3000
depends_on:
coc-api:
condition: service_healthy
networks:
- coc-network
command: ["npm", "run", "dev"]

# coc-admin — admin backend

coc-admin-server:
image: callofcode07/coc-admin-backend:latest
pull_policy: missing
restart: unless-stopped
ports:
- "${COC_ADMIN_BACKEND_PORT:-8001}:8000" # remapped to 8001 to avoid conflict
env_file:
- coc-admin/.env.local.backend
environment:
- PORT=8000
- API_URL=http://coc-api:3000
- ALLOWED_ORIGINS=http://localhost:${COC_ADMIN_FRONTEND_PORT:-5174}
depends_on:
coc-api:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8000/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 10s
networks:
- coc-network

# coc-admin — admin frontend
coc-admin-web:
image: callofcode07/coc-admin-frontend:latest
pull_policy: missing
restart: unless-stopped
ports:
- "${COC_ADMIN_FRONTEND_PORT:-5174}:5173" # remapped to 5174 to avoid conflict
env_file:
- coc-admin/.env.local.frontend
environment:
- VITE_API_URL=http://localhost:8001
depends_on:
coc-admin-server:
condition: service_healthy
networks:
- coc-network

# ---------------------------------------------------------------------------
# coc-member — member backend
# ---------------------------------------------------------------------------
coc-member-server:
image: callofcode07/coc-member-backend:latest
pull_policy: missing
restart: unless-stopped
ports:
- "${COC_MEMBER_BACKEND_PORT:-8002}:8000" # remapped to 8002 to avoid conflict
env_file:
- coc-member/.env.local.backend
environment:
- PORT=8000
- API_URL=http://coc-api:3000
- ALLOWED_ORIGINS=http://localhost:${COC_MEMBER_FRONTEND_PORT:-5175}
depends_on:
coc-api:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8000/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 10s
networks:
- coc-network

# ---------------------------------------------------------------------------
# coc-member — member frontend
# ---------------------------------------------------------------------------
coc-member-web:
image: callofcode07/coc-member-frontend:latest
pull_policy: missing
restart: unless-stopped
ports:
- "${COC_MEMBER_FRONTEND_PORT:-5175}:5173" # remapped to 5175 to avoid conflict
env_file:
- coc-member/.env.local.frontend
environment:
- VITE_API_URL=http://localhost:8002
depends_on:
coc-member-server:
condition: service_healthy
networks:
- coc-network

networks:
coc-network:
driver: bridge
Loading