Skip to main content

Docker Compose files

Joystick IoT platform provides three Docker Compose configurations for different deployment scenarios:
  • docker-compose.yml - Production deployment with Traefik reverse proxy
  • docker-compose.linux.yml - Linux-optimized deployment with host networking
  • docker-compose.dev.yml - Development environment with exposed ports and mounted volumes

Production deployment

Architecture

The production deployment uses Traefik as a reverse proxy to route requests to different services:
services:
  traefik:
    image: traefik:v2.11
    ports:
      - "80:80"
      - "8080:8080"
    command:
      - "--providers.docker"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.http.address=:80"
      - "--api.insecure=true"

Service routing

Services are exposed through Traefik using labels:
ServiceURL PathInternal Port
App/80
Joystick API/joystick8000
Panel/panel4000
Baker/baker3000
Switcher/switcher8080
Whisper/whisper8081
Studio/studio8001

Starting services

docker-compose up -d

Stopping services

docker-compose down

Viewing logs

# All services
docker-compose logs -f

# Specific service
docker-compose logs -f joystick

Linux deployment

When to use

Use docker-compose.linux.yml when:
  • Deploying on Linux servers
  • You need maximum network performance
  • You want to avoid Docker network overhead

Host networking

All services use network_mode: host, which means:
  • Services bind directly to host ports
  • No Docker network bridge overhead
  • Better performance for video streaming
  • Services use host IP addresses

Starting services

docker-compose -f docker-compose.linux.yml up -d

Service configuration example

services:
  pocketbase:
    image: ghcr.io/skylineagle/joystick/pb:latest
    network_mode: "host"
    restart: unless-stopped
    environment:
      - BAKER_URL=http://baker:3000
      - MEDIAMTX_API=http://mediamtx:9997
    volumes:
      - pb_data:/pb_data

Development deployment

When to use

Use docker-compose.dev.yml when:
  • Developing locally
  • You need to modify PocketBase hooks or migrations
  • You want direct access to services without a reverse proxy

Exposed ports

services:
  pocketbase:
    ports:
      - "8090:8090"
  
  mediamtx:
    ports:
      - "9997:9997"  # API
      - "8554:8554"  # RTSP
      - "8888:8888"  # HLS
      - "1935:1935"  # RTMP

Mounted volumes

Development mode mounts local directories for live code changes:
volumes:
  - ./pocketbase/pb_data:/pb_data
  - ./pocketbase/pb_public:/pb_public
  - ./pocketbase/pb_hooks:/pb_hooks
  - ./pocketbase/pb_migrations:/pb_migrations

Starting services

docker-compose -f docker-compose.dev.yml up -d

Service management

Restart a service

docker-compose restart joystick

Rebuild and restart

docker-compose up -d --build joystick

View service status

docker-compose ps

Execute commands in a container

docker-compose exec joystick sh

View resource usage

docker stats

Common Docker Compose patterns

Health checks

PocketBase includes a health check to ensure it’s ready before dependent services start:
healthcheck:
  test: wget --no-verbose --tries=1 --spider http://localhost:8090/api/health || exit 1
  interval: 5s
  timeout: 5s
  retries: 5
Dependent services wait for PocketBase to be healthy:
depends_on:
  pocketbase:
    condition: service_healthy
  mediamtx:
    condition: service_started

Restart policies

All services use restart: unless-stopped:
restart: unless-stopped
This ensures services automatically restart after crashes or system reboots, unless manually stopped.

Shared configuration

Docker Compose anchors reduce duplication:
x-platform-restart: &default-platform-restart
  platform: linux/amd64
  restart: unless-stopped

services:
  joystick:
    <<: *default-platform-restart
    # other configuration...

CORS configuration

CORS headers are configured via Traefik middleware:
labels:
  - "traefik.http.middlewares.cors.headers.accesscontrolallowmethods=*"
  - "traefik.http.middlewares.cors.headers.accesscontrolallowheaders=*"
  - "traefik.http.middlewares.cors.headers.accesscontrolalloworiginlist=*"
  - "traefik.http.middlewares.cors.headers.addvaryheader=true"

Updating services

Update all services

docker-compose pull
docker-compose up -d

Update specific service

docker-compose pull joystick
docker-compose up -d joystick

Backup and restore

Backup PocketBase data

docker run --rm -v joystick_pb_data:/data -v $(pwd):/backup \
  alpine tar czf /backup/pb_data_backup.tar.gz /data

Restore PocketBase data

docker run --rm -v joystick_pb_data:/data -v $(pwd):/backup \
  alpine tar xzf /backup/pb_data_backup.tar.gz -C /

Cleanup

Remove stopped containers

docker-compose down

Remove containers and volumes

docker-compose down -v

Remove unused images

docker image prune -a

Build docs developers (and LLMs) love