Apache Superset Docker Deployment

Superset is a powerful, open-source data visualization and business intelligence platform maintained by the Apache Foundation. It’s ideal for teams who want modern dashboards without handing data over to third parties. After experimenting with tools like Metabase, I landed on Superset for its extensibility, better dashboard customisation, and alerting/reporting features.

I struggled finding a comprehensive guide for Docker-based deployments beyond the basic setup, so I'll walk through my deployment process for Superset, from setting up the host and containers, to branding and email alerts.


Why Superset?

Before diving into deployment, a quick comparison.

Feature Superset Metabase
Data engine support Wide (SQLAlchemy-compatible) Limited but growing
Chart/dash flexibility Advanced (custom CSS, D3, JS plugins) Simple and opinionated
Alerts & reports Built-in with scheduling (via Celery) Available on paid plans
Embedding options Fine-grained (auth, iframe, SSO) Basic iframe embedding
Community Apache-backed, active dev scene Also solid, with a user-friendly vibe

Metabase is simpler and easier to get started with, especially for business users. But if you're comfortable with SQL and want granular control, Superset offers a lot more power.


Deploying Superset with Docker Compose

I’m running this on a remote Linux server via Docker. We’ll use a persistent folder for Superset configs and database volumes.

Step 1: Prepare the Host

SSH into your server and run:

sudo mkdir -p /opt/superset/{home,db}
sudo chown -R 1000:1000 /opt/superset

This creates persistent storage for Superset's configuration and the PostgreSQL database.


Step 2: Docker Compose Setup (Full Version with Commands)

The complete Compose stack includes Superset, Postgres, Redis, a Celery worker for async tasks, and a beat scheduler for scheduled reports.

version: "3.8"

services:
  superset:
    image: apache/superset:latest
    container_name: superset
    ports:
      - "8088:8088"
    environment:
      - SUPERSET_ENV=production
      - SUPERSET_LOAD_EXAMPLES=no
      - SUPERSET_SECRET_KEY=your-secret-key
      - SUPERSET_REDIS_HOST=redis
      - SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset
      - CELERY_BROKER_URL=redis://redis:6379/0
    volumes:
      - /opt/superset/home:/app/superset_home
      - /opt/superset/home/superset_config.py:/app/pythonpath/superset_config.py
    depends_on:
      - db
      - redis
    restart: always
    networks:
      - shared_network
    command: >
      /bin/bash -c "
        pip install --no-cache-dir --no-warn-script-location psycopg2-binary prophet gevent openpyxl pandas-gbq pymysql elasticsearch-dbapi snowflake-connector-python cryptography flask-mail &&
        export FLASK_APP=superset &&
        superset db upgrade &&
        if ! superset fab list-users | grep -q admin; then
          superset fab create-admin --username admin --firstname Superset --lastname Admin --email [email protected] --password 'YourSecurePassword';
        fi &&
        superset init &&
        gunicorn --workers 4 --worker-class gthread --timeout 120 -b 0.0.0.0:8088 'superset.app:create_app()'
      "

  db:
    image: postgres:13
    container_name: superset_db
    environment:
      - POSTGRES_DB=superset
      - POSTGRES_USER=superset
      - POSTGRES_PASSWORD=superset
    ports:
      - "6125:5432"
    volumes:
      - /opt/superset/db:/var/lib/postgresql/data
    restart: always
    networks:
      - shared_network

  redis:
    image: redis:latest
    container_name: superset_redis
    restart: always
    networks:
      - shared_network

  worker:
    image: apache/superset:latest-dev
    container_name: superset_worker
    command: celery --app=superset.tasks.celery_app:app worker --pool=gevent --concurrency=4
    environment:
      - SUPERSET_ENV=production
      - SUPERSET_SECRET_KEY=your-secret-key
      - SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=db+postgresql://superset:superset@db:5432/superset
    volumes:
      - /opt/superset/home:/app/superset_home
      - /opt/superset/home/superset_config.py:/app/pythonpath/superset_config.py
    depends_on:
      - redis
      - db
    restart: always
    networks:
      - shared_network

  beat:
    image: apache/superset:latest-dev
    container_name: superset_beat
    command: >
      /bin/bash -c "mkdir -p /app/superset_home && chmod -R a+rwX /app/superset_home && celery \
      --app=superset.tasks.celery_app:app beat \
      --pidfile= \
      --schedule=/app/superset_home/celerybeat-schedule \
      --loglevel=info"
    environment:
      - SUPERSET_ENV=production
      - SUPERSET_SECRET_KEY=your-secret-key
      - SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=db+postgresql://superset:superset@db:5432/superset
    volumes:
      - /opt/superset/home:/app/superset_home
      - /opt/superset/home/superset_config.py:/app/pythonpath/superset_config.py
    depends_on:
      - redis
      - db
    restart: always
    networks:
      - shared_network

networks:
  shared_network:
    external: true

`docker-compose.yml

If running this in production, use secrets and do not embed the credentials in the compose file.


Custom Branding

Tweak your /opt/superset/home/superset_config.py to rebrand the UI:

APP_NAME = "My BI Platform"  # Top-left title and browser tab title

# Where clicking the logo takes users (e.g., your dashboard homepage)
LOGO_TARGET_PATH = "https://yourdomain.com"

# Replace the Superset logo (top-left) with your own
APP_ICON = "https://yourdomain.com/static/logo.svg"

# Favicon (browser tab icon)
FAVICONS = [
    {
        "rel": "icon",
        "type": "image/png",
        "sizes": "32x32",
        "href": "https://yourdomain.com/static/favicon-32x32.png",
    },
    {
        "rel": "icon",
        "type": "image/png",
        "sizes": "16x16",
        "href": "https://yourdomain.com/static/favicon-16x16.png",
    },
]

Enabling Email Reports

Add this to the same config, this will enable the report/alert feature on Superset:

EMAIL_NOTIFICATIONS = True
SMTP_HOST = "smtp.yourprovider.com"
SMTP_PORT = 587
SMTP_STARTTLS = True
SMTP_SSL = False
SMTP_USER = "[email protected]"
SMTP_PASSWORD = os.getenv("SMTP_PASSWORD", "")
SMTP_MAIL_FROM = "[email protected]"

ALERT_REPORTS_SUPERSET_WEBDRIVER = {
    "auth_type": "AUTH_FORM",
    "auth_user": "admin",
    "auth_password": os.getenv("SUPERSET_ADMIN_PW", ""),
    "login_url": "https://yourdomain.com/login/",
}

What’s Next?

  • Hook up your databases
  • Build dashboards and slice charts
  • Embed dashboards internally or in apps
  • Define roles and access rules

Final Thoughts

Superset can be a bit heavy out the gate, but once it’s running, it becomes a versatile and professional-grade BI platform, all while keeping your data under your control.