Skip to content

Portainer Deployment

Portainer is a web-based Docker management UI. If you're already running Portainer to manage your Docker environment, you can deploy Dreadnought as a Stack directly from the Portainer UI.


Prerequisites

  • Portainer installed and running (Community Edition is free)
  • Docker running on the same host
  • Access to the Portainer web UI
  • A Cloudflare API token — see Cloudflare Setup

This method keeps the stack in sync with the GitHub repository.

Step 1 — Create a New Stack

  1. Log in to your Portainer instance
  2. Go to Stacks → Add Stack
  3. Give it a name: dreadnought-ddns
  4. Select Repository as the build method

Step 2 — Configure the Repository

  • Repository URL: https://github.com/dreadnought-0/Dreadnought-DDNS
  • Repository reference: refs/heads/main
  • Compose path: docker-compose.yml

Leave Authentication unchecked (the repo is public).

Optional — Enable automatic updates: - Check Automatic updates - Set polling interval (e.g. every 5 minutes) - Portainer will re-pull and redeploy if the repository changes

Step 3 — Set Environment Variables

Scroll down to the Environment variables section. Add each variable:

Name Value
CF_API_TOKEN Your Cloudflare API token
ADMIN_EMAIL Your login email
ADMIN_PASSWORD A strong password
SECRET_KEY Run openssl rand -hex 32 and paste the result
POLL_INTERVAL_SECONDS 300
IPV6_ENABLED false
DISCORD_WEBHOOK_URL (leave blank or enter webhook URL)
TZ e.g. America/New_York

Step 4 — Deploy the Stack

Click Deploy the stack. Portainer will: 1. Pull the repository 2. Build all three images 3. Start the containers

Build time: 2–5 minutes. Watch progress in the Portainer interface.

Step 5 — Prepare the Data Directory

Before containers start successfully, the ./data directory needs to exist with write permissions. In Portainer's terminal or on the host via SSH:

# On the host, in the directory where Portainer stored the stack
# Portainer usually stores stacks in /data/compose/<id>/
ls /data/compose/

# Find the dreadnought stack directory and create ./data inside it
mkdir -p /data/compose/<stack-id>/data
chmod 777 /data/compose/<stack-id>/data

Or click on the container in Portainer → Console → run:

mkdir -p /data && chmod 777 /data

Tip: If you're not sure where Portainer stores the stack files, SSH into the host and run docker inspect dreadnought-ddns-api-1 and look for the volume mount source path.


Method 2 — Deploy via Web Editor (Paste docker-compose.yml)

This method lets you paste and customize the compose file directly in Portainer.

Step 1 — Create a New Stack

  1. Go to Stacks → Add Stack
  2. Name: dreadnought-ddns
  3. Select Web editor

Step 2 — Paste the Compose File

Copy the contents of docker-compose.yml from the repository and paste it into the editor. Then modify the web service's NEXT_PUBLIC_API_URL and other environment variables inline:

services:
  api:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "8081:8000"
    volumes:
      - ./data:/data
    environment:
      - DATABASE_URL=sqlite:////data/ddns.db
      - CF_API_TOKEN=your_token_here
      - ADMIN_EMAIL=you@example.com
      - ADMIN_PASSWORD=your_password
      - SECRET_KEY=your_secret_key
      - POLL_INTERVAL_SECONDS=300
      - IPV6_ENABLED=false
      - DISCORD_WEBHOOK_URL=
      - TZ=America/New_York
    restart: unless-stopped

  worker:
    build:
      context: ./backend
      dockerfile: Dockerfile.worker
    volumes:
      - ./data:/data
    environment:
      - DATABASE_URL=sqlite:////data/ddns.db
      - CF_API_TOKEN=your_token_here
      - POLL_INTERVAL_SECONDS=300
      - IPV6_ENABLED=false
      - DISCORD_WEBHOOK_URL=
      - TZ=America/New_York
    restart: unless-stopped

  web:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "8082:3000"
    environment:
      - NEXT_PUBLIC_API_URL=http://your-server-ip:8081
      - NODE_ENV=production
    depends_on:
      - api
    restart: unless-stopped

Note: When using the web editor, build: with context: paths refers to relative paths on the Docker host. For this to work, Portainer needs the source code on the host. Consider using the Repository method above instead, or pre-build and push images to a registry.

Step 3 — Deploy

Click Deploy the stack.


Method 3 — Use Pre-Built Images

If you've built and pushed images to a registry (see Manual Dockerfile Build), configure the stack to use those images:

services:
  api:
    image: yourusername/dreadnought-api:latest
    ports:
      - "8081:8000"
    volumes:
      - dreadnought-data:/data
    environment:
      - DATABASE_URL=sqlite:////data/ddns.db
      - CF_API_TOKEN=your_token_here
      - ADMIN_EMAIL=you@example.com
      - ADMIN_PASSWORD=your_password
      - SECRET_KEY=your_secret_key
      - POLL_INTERVAL_SECONDS=300
      - IPV6_ENABLED=false
      - DISCORD_WEBHOOK_URL=
      - TZ=America/New_York
    restart: unless-stopped

  worker:
    image: yourusername/dreadnought-worker:latest
    volumes:
      - dreadnought-data:/data
    environment:
      - DATABASE_URL=sqlite:////data/ddns.db
      - CF_API_TOKEN=your_token_here
      - POLL_INTERVAL_SECONDS=300
      - IPV6_ENABLED=false
      - DISCORD_WEBHOOK_URL=
      - TZ=America/New_York
    restart: unless-stopped

  web:
    image: yourusername/dreadnought-web:latest
    ports:
      - "8082:3000"
    environment:
      - NEXT_PUBLIC_API_URL=http://your-server-ip:8081
      - NODE_ENV=production
    depends_on:
      - api
    restart: unless-stopped

volumes:
  dreadnought-data:

This uses a named Docker volume (dreadnought-data) instead of a host directory — Portainer manages it automatically and permissions are handled by Docker.


Accessing the Dashboard

Once running, open:

http://your-server-ip:8082

Log in with your ADMIN_EMAIL and ADMIN_PASSWORD.


Managing the Stack in Portainer

Action How
View container logs Stacks → dreadnought-ddns → Click service → Logs
Restart a service Stacks → dreadnought-ddns → Click service → Restart
Stop all Stacks → dreadnought-ddns → Stop
Update (pull new images) Stacks → dreadnought-ddns → Pull and redeploy
View resource usage Containers → select container → Stats

Adding HTTPS

Portainer doesn't manage TLS by itself. Options:

  1. Use Portainer with Traefik — many Portainer setups already include Traefik. Add Traefik labels to the stack services (see Traefik guide).
  2. Use Nginx on the same host — see Nginx guide.
  3. Use Caddy on the same host — see Caddy guide.

Troubleshooting

Containers fail to start with database error

sqlite3.OperationalError: unable to open database file

The ./data directory doesn't exist or isn't writable. See Step 5 in Method 1 above to create and permission it.

Build fails in Portainer

  • Check the build logs in Portainer (Stacks → your stack → Logs during build)
  • Make sure the repository source is configured correctly
  • On low-memory systems, the Next.js build may fail — see the Raspberry Pi guide for swap tips

Environment variables not taking effect

  • After changing variables, click Update the stack in Portainer
  • For NEXT_PUBLIC_API_URL, a full rebuild is required (not just a restart) since it's baked into the frontend at build time