Labelgate

Single Host

Docker Compose examples for single-host deployments.

DNS-Only Setup

The simplest setup - Labelgate manages DNS records only, no tunnels needed.

services:
  labelgate:
    image: labelgate:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - labelgate-data:/app/config
    environment:
      - LABELGATE_CLOUDFLARE_API_TOKEN

  # Web server with auto DNS
  nginx:
    image: nginx:alpine
    labels:
      labelgate.dns.web.hostname: "www.example.com"
      labelgate.dns.web.type: "A"
      labelgate.dns.web.target: "auto"
      labelgate.dns.web.proxied: "true"

volumes:
  labelgate-data:

Tunnel-Only Setup

Expose services through Cloudflare Tunnel - no public ports needed.

services:
  labelgate:
    image: labelgate:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - labelgate-data:/app/config
    environment:
      - LABELGATE_CLOUDFLARE_API_TOKEN
      - LABELGATE_CLOUDFLARE_ACCOUNT_ID
      - LABELGATE_CLOUDFLARE_TUNNEL_ID

  cloudflared:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel run --token ${TUNNEL_TOKEN}

  # Web application
  webapp:
    image: nginx:alpine
    labels:
      labelgate.tunnel.web.hostname: "app.example.com"
      labelgate.tunnel.web.service: "http://webapp:80"

  # API server
  api:
    image: node:alpine
    labels:
      labelgate.tunnel.api.hostname: "api.example.com"
      labelgate.tunnel.api.service: "http://api:3000"

volumes:
  labelgate-data:

Use Docker service names (e.g., http://webapp:80) in service labels, not localhost. Containers communicate via Docker's internal network.

DNS + Tunnel (Different Hostnames)

Combine DNS records and tunnel services on different hostnames.

services:
  labelgate:
    image: labelgate:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - labelgate-data:/app/config
    environment:
      - LABELGATE_CLOUDFLARE_API_TOKEN
      - LABELGATE_CLOUDFLARE_ACCOUNT_ID
      - LABELGATE_CLOUDFLARE_TUNNEL_ID

  cloudflared:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel run --token ${TUNNEL_TOKEN}

  app:
    image: myapp:latest
    labels:
      # Tunnel: expose via Cloudflare Tunnel
      labelgate.tunnel.web.hostname: "app.example.com"
      labelgate.tunnel.web.service: "http://app:80"

      # DNS: point a different hostname to server IP
      labelgate.dns.legacy.hostname: "old.example.com"
      labelgate.dns.legacy.type: "A"
      labelgate.dns.legacy.target: "203.0.113.1"

volumes:
  labelgate-data:

With Access Policy

Protect services with Zero Trust Access.

services:
  labelgate:
    image: labelgate:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - labelgate-data:/app/config
    environment:
      - LABELGATE_CLOUDFLARE_API_TOKEN
      - LABELGATE_CLOUDFLARE_ACCOUNT_ID
      - LABELGATE_CLOUDFLARE_TUNNEL_ID

  cloudflared:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel run --token ${TUNNEL_TOKEN}

  admin-panel:
    image: admin:latest
    labels:
      # Define access policy
      labelgate.access.team.policy.decision: "allow"
      labelgate.access.team.policy.include.emails_ending_in: "@company.io"
      labelgate.access.team.session_duration: "8h"

      # Tunnel with access policy
      labelgate.tunnel.admin.hostname: "admin.company.io"
      labelgate.tunnel.admin.service: "http://admin-panel:8080"
      labelgate.tunnel.admin.access: "team"

  # Public docs - no access policy needed
  docs:
    image: docs:latest
    labels:
      labelgate.tunnel.docs.hostname: "docs.company.io"
      labelgate.tunnel.docs.service: "http://docs:80"

volumes:
  labelgate-data:

PR Preview Environment

Automatic preview deployments with cleanup on container stop.

services:
  labelgate:
    image: labelgate:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - labelgate-data:/app/config
    environment:
      - LABELGATE_CLOUDFLARE_API_TOKEN
      - LABELGATE_CLOUDFLARE_ACCOUNT_ID
      - LABELGATE_CLOUDFLARE_TUNNEL_ID

  cloudflared:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel run --token ${TUNNEL_TOKEN}

  preview:
    image: myapp:pr-${PR_NUMBER:-0}
    labels:
      labelgate.tunnel.preview.hostname: "pr-${PR_NUMBER:-0}.preview.example.com"
      labelgate.tunnel.preview.service: "http://preview:3000"
      labelgate.tunnel.preview.cleanup: "true"

volumes:
  labelgate-data:

On this page