Containers
18 containers managed by a single docker-compose.yml at /opt/camlab/.
Container Inventory
| Container | Image | Port (host) | Volume(s) | Health Check | Restart |
|---|---|---|---|---|---|
| mysql | mysql:8.0 | 127.0.0.1:3306 | ./mysql/data, ./mysql/init |
mysqladmin ping | unless-stopped |
| ghost-cam4 | ghost:6-alpine | 127.0.0.1:2368 | ./ghost/cam4 |
— | unless-stopped |
| ghost-cam4models | ghost:6-alpine | 127.0.0.1:2369 | ./ghost/cam4models |
— | unless-stopped |
| ghost-cam4pays | ghost:6-alpine | 127.0.0.1:2370 | ./ghost/cam4pays |
— | unless-stopped |
| ghost-mcp | ghost-mcp (local build) | 127.0.0.1:3002 | — | — | unless-stopped |
| n8n | n8n-claude:latest (local build) | 127.0.0.1:5678 | ./n8n/data, ./n8n/projects, docker.sock, ghost image dirs |
— | unless-stopped |
| runner-cam4 | claude-runner:latest (local build) | — | ./runners/cam4/claude-config, .claude.json, workspace |
— | unless-stopped |
| runner-cam4models | claude-runner:latest (local build) | — | ./runners/cam4models/claude-config, .claude.json, workspace |
— | unless-stopped |
| runner-cam4pays | claude-runner:latest (local build) | — | ./runners/cam4pays/claude-config, .claude.json, workspace |
— | unless-stopped |
| reddit-mcp | mcp-reddit-proxy:latest (local build) | 127.0.0.1:8080 | — | — | unless-stopped |
| playwright-mcp | mcr.microsoft.com/playwright/mcp:latest | 127.0.0.1:8931 | — | — | unless-stopped |
| runware-mcp | mcp-runware:latest (local build) | 127.0.0.1:8081 | — | POST /mcp | unless-stopped |
| twitter-mcp | x-twitter-mcp:latest (local build) | 127.0.0.1:8083 | — | — | unless-stopped |
| stockimages-mcp | mcp-stock-images:latest (local build) | 127.0.0.1:8084 | — | — | unless-stopped |
| memes-mcp | mcp-memes:latest (local build) | 127.0.0.1:8085 | — | — | unless-stopped |
| dozzle | amir20/dozzle:latest | 127.0.0.1:9999 | docker.sock | — | unless-stopped |
| glances | nicolargo/glances:latest | 127.0.0.1:61208 | docker.sock | — | unless-stopped |
| docs | squidfunk/mkdocs-material:latest | 127.0.0.1:8082 | ./docs |
— | unless-stopped |
Custom Images (built locally)
| Image | Build Context | Dockerfile | Base |
|---|---|---|---|
| ghost-mcp | ./ghost-mcp |
Dockerfile |
node:20-slim |
| n8n-claude:latest | ./n8n |
Dockerfile.claude |
n8nio/n8n:latest + docker CLI |
| claude-runner:latest | ./runners |
Dockerfile |
python:3.11-slim + Node.js 20 |
| mcp-reddit-proxy:latest | ./mcp-servers/reddit |
Dockerfile |
node:20-slim + mcp-proxy + uvx |
| mcp-runware:latest | ./mcp-servers/runware |
Dockerfile |
python:3.11-slim |
| x-twitter-mcp:latest | ./mcp-servers/twitter |
Dockerfile |
python:3.13-slim |
| mcp-stock-images:latest | ./mcp-servers/stock-images |
Dockerfile |
python:3.11-slim + Node.js 20 + mcp-proxy |
| mcp-memes:latest | ./mcp-servers/memes |
Dockerfile |
node:20-slim + mcp-proxy |
Common Commands
cd /opt/camlab
# Status of all containers
docker compose ps
# Rebuild a specific image and recreate container
docker compose build ghost-mcp
docker compose up -d ghost-mcp
# Rebuild all images
docker compose build
# View logs
docker compose logs --tail 50 ghost-cam4
docker compose logs -f n8n
# Restart a service
docker compose restart runner-cam4
# Resource usage
docker stats --no-stream
Dependencies
graph TB
MySQL[("MySQL")]
cam4["ghost-cam4"] --> MySQL
cam4m["ghost-cam4models"] --> MySQL
cam4p["ghost-cam4pays"] --> MySQL
gmcp["ghost-mcp"] --> cam4 & cam4m & cam4p
n8n -. "docker exec" .-> rc4["runner-cam4"]
n8n -. "docker exec" .-> rc4m["runner-cam4models"]
n8n -. "docker exec" .-> rc4p["runner-cam4pays"]
rc4 --> gmcp
rc4 --> rmcp["reddit-mcp"] & pmcp["playwright-mcp"] & wmcp["runware-mcp"] & tmcp["twitter-mcp"] & smcp["stockimages-mcp"] & mmcp["memes-mcp"]
rc4m --> gmcp & rmcp & pmcp & wmcp & tmcp & smcp & mmcp
rc4p --> gmcp & rmcp & pmcp & wmcp & tmcp & smcp & mmcp
Network
All containers are on the camlab_network bridge network. Containers reference each other by container name (e.g., ghost-cam4, reddit-mcp).
Important Notes
- All host ports bind to
127.0.0.1only — no direct external access - Caddy (system-level, not containerized) handles TLS termination and reverse proxying
- n8n runs as
user: rootto access Docker socket for runner exec - Runner
.claude.jsonfiles are bind-mounted for persistence across container recreation - n8n data mounts to
/root/.n8n(matching the root user, not the default node user)