Last updated: 2026-04-02
This guide documents how to install and expose Apache Superset on the shared workstation by using the upstream Apache Superset Docker Compose setup on Windows. It is intended for administrative setup and maintenance.
Important scope note:
apache/superset repository.docker/.env-local, docker-compose.override.yml, superset_config.py, and files under docker/local/.git clone https://github.com/apache/superset.git
The upstream docker-compose.yml binds the internal Superset database to 127.0.0.1:5432 by default. On the workstation this conflicts with an already running PostGIS container.
Create a root-level .env file in the Superset repository root, next to docker-compose.yml:
DATABASE_PORT=5433
Important:
.env file, not docker/.env..env.In docker/.env, keep the internal container port on 5432:
DATABASE_PORT=5432
Verify the effective port mapping before starting the stack:
docker compose config | findstr /i "published"
Expected result:
Generate a secret key:
python -c "import secrets; print(secrets.token_hex(42))"
Create docker/.env-local if it does not exist yet and place the generated value there:
SUPERSET_SECRET_KEY='<your-generated-key>'
If the generated key contains special characters such as $, !, or #, wrap it in single quotes.
Recommended additional local overrides in docker/.env-local:
SUPERSET_LOAD_EXAMPLES=no
TAILSCALE_HOSTNAME=<your-hostname>.ts.net
MCP_PORT=5008
MCP_DEV_USERNAME=admin
MCP_AUTH_ENABLED=false
Run the initial build:
docker compose up --build
Notes:
docker compose up -d
superset web container is started directly with Gunicorn from the existing container virtual environment instead of the slower dev bootstrap path; this avoids repeated editable installs on every restartdocker-compose.override.yml, recreate only the affected web services:docker compose up -d --force-recreate --no-deps superset nginx
Open the Tailscale admin console:
Enable HTTPS Certificates for the tailnet.
Run the following command in WSL or Git Bash on the workstation:
tailscale cert '<workstation-tailscale-domain>'
This creates two files:
<hostname>.ts.net.crt<hostname>.ts.net.keyCreate the local certificate target folder in the Superset repository and copy both files into it:
mkdir docker\local\certs
Target folder:
docker/local/certs/Create docker/local/nginx/superset.conf.template with the following configuration:
upstream superset_app {
server host.docker.internal:8088;
keepalive 100;
}
upstream superset_websocket {
server host.docker.internal:8080;
keepalive 100;
}
# Redirect HTTP to HTTPS
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
# HTTPS server
server {
listen 443 ssl default_server;
server_name _;
ssl_certificate /etc/nginx/certs/${TAILSCALE_HOSTNAME}.crt;
ssl_certificate_key /etc/nginx/certs/${TAILSCALE_HOSTNAME}.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location /ws {
proxy_pass http://superset_websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
location ${SUPERSET_APP_ROOT}/static {
proxy_pass http://host.docker.internal:9000;
proxy_http_version 1.1;
proxy_set_header Host $host;
}
location ${SUPERSET_APP_ROOT} {
proxy_pass http://superset_app;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_http_version 1.1;
port_in_redirect off;
proxy_connect_timeout 300;
}
}
Add the Tailscale hostname to docker/.env-local:
TAILSCALE_HOSTNAME=<your-hostname>.ts.net
Create a local docker-compose.override.yml in the Superset repository root so that HTTPS and the certificate mount are enabled without modifying the tracked upstream docker-compose.yml:
nginx:
ports:
- "${NGINX_PORT:-80}:80"
- "443:443"
volumes:
- ./docker/local/nginx/superset.conf.template:/etc/nginx/templates/superset.conf.template:ro
- ./docker/local/certs:/etc/nginx/certs:ro
Apply the nginx changes:
docker compose up -d --force-recreate --no-build nginx
Create an ignored superset_config.py in the Superset repository root and mount it via docker-compose.override.yml.
Minimal local superset_config.py:
import importlib.util
import os
from pathlib import Path
def _load_base_config() -> None:
base_config_path = Path("/app/docker/pythonpath_dev/superset_config.py")
spec = importlib.util.spec_from_file_location(
"superset_base_config",
base_config_path,
)
if spec is None or spec.loader is None:
raise RuntimeError(f"Unable to load base Superset config from {base_config_path}")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
for key in dir(module):
if key.isupper():
globals()[key] = getattr(module, key)
_load_base_config()
FAB_ADD_SECURITY_API = True
MCP_SERVICE_HOST = "0.0.0.0"
MCP_SERVICE_PORT = int(os.getenv("MCP_PORT", "5008"))
MCP_AUTH_ENABLED = os.getenv("MCP_AUTH_ENABLED", "false").lower() == "true"
MCP_DEBUG = os.getenv("MCP_DEBUG", "false").lower() == "true"
if MCP_AUTH_ENABLED:
jwt_algorithm = os.getenv("MCP_JWT_ALGORITHM")
if jwt_algorithm:
MCP_JWT_ALGORITHM = jwt_algorithm
else:
MCP_DEV_USERNAME = os.getenv("MCP_DEV_USERNAME", "admin")
tailscale_hostname = os.getenv("TAILSCALE_HOSTNAME")
if tailscale_hostname:
MCP_SERVICE_URL = f"https://{tailscale_hostname}"
Extend docker-compose.override.yml so the Superset containers and the MCP container use that config file, and add an mcp service:
superset:
command: ["/bin/bash", "-lc", "export DEV_MODE=false && /app/.venv/bin/gunicorn --bind ${SUPERSET_BIND_ADDRESS:-0.0.0.0}:${SUPERSET_PORT:-8088} --access-logfile ${ACCESS_LOG_FILE:--} --error-logfile ${ERROR_LOG_FILE:--} --workers ${SERVER_WORKER_AMOUNT:-1} --worker-class ${SERVER_WORKER_CLASS:-gthread} --threads ${SERVER_THREADS_AMOUNT:-20} --log-level ${GUNICORN_LOGLEVEL:-info} --timeout ${GUNICORN_TIMEOUT:-60} --keep-alive ${GUNICORN_KEEPALIVE:-2} --max-requests ${WORKER_MAX_REQUESTS:-0} --max-requests-jitter ${WORKER_MAX_REQUESTS_JITTER:-0} --limit-request-line ${SERVER_LIMIT_REQUEST_LINE:-0} --limit-request-field_size ${SERVER_LIMIT_REQUEST_FIELD_SIZE:-0} 'superset.app:create_app()'"]
environment:
DEV_MODE: "false"
SUPERSET_CONFIG_PATH: /app/superset_config.py
volumes:
- ./superset_config.py:/app/superset_config.py:ro
superset-init:
environment:
DEV_MODE: "false"
SUPERSET_CONFIG_PATH: /app/superset_config.py
volumes:
- ./superset_config.py:/app/superset_config.py:ro
superset-worker:
environment:
DEV_MODE: "false"
SUPERSET_CONFIG_PATH: /app/superset_config.py
volumes:
- ./superset_config.py:/app/superset_config.py:ro
superset-worker-beat:
environment:
DEV_MODE: "false"
SUPERSET_CONFIG_PATH: /app/superset_config.py
volumes:
- ./superset_config.py:/app/superset_config.py:ro
mcp:
image: superset-superset:latest
command: ["/bin/bash", "-lc", "export DEV_MODE=false && /app/.venv/bin/superset mcp run --host 0.0.0.0 --port ${MCP_PORT:-5008} --debug"]
env_file:
- path: docker/.env
required: true
- path: docker/.env-local
required: false
environment:
SUPERSET_CONFIG_PATH: /app/superset_config.py
restart: unless-stopped
ports:
- "127.0.0.1:${MCP_PORT:-5008}:5008"
healthcheck:
test:
- CMD-SHELL
- >-
curl -fsS -X POST http://127.0.0.1:5008/mcp
-H 'Accept: application/json, text/event-stream'
-H 'Content-Type: application/json'
--data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"docker-healthcheck","version":"1.0"}}}'
| grep -q '"protocolVersion":"2024-11-05"'
interval: 30s
timeout: 10s
retries: 3
start_period: 20s
volumes:
- ./superset_config.py:/app/superset_config.py:ro
Important:
127.0.0.1:5008/mcp; an inherited check against localhost:8088 marks the container unhealthy even when MCP itself is working/app/.venv/bin/gunicorn so that routine restarts do not re-run the slower editable install bootstrapStart MCP locally:
docker compose up -d --force-recreate --no-build mcp
Local MCP endpoint for VS Code:
http://127.0.0.1:5008/mcp
Check the service locally:
curl http://localhost:8088/health
Check the service over Tailscale HTTPS:
curl https://<hostname>.ts.net/health
Expected response:
OK
Open Superset in a browser:
https://<hostname>.ts.net
Default login after initial setup:
adminadminChange the default password immediately.
Superset can connect to the existing PostGIS container when both services share a Docker network.
Inspect the network of the running PostGIS container:
docker inspect <postgis-container-name> | findstr /i "network"
If Superset and PostGIS are on different Docker networks, add the external PostGIS network to the Superset stack. Under the relevant superset and db services, add:
networks:
- default
- postgis_network
networks:
postgis_network:
external: true
name: <exact-network-name>
Use docker network ls to find the exact external network name.
Then create the database connection in Superset under Settings -> Database Connections -> + Database using:
postgresql+psycopg2://user:password@<postgis-container-name>:5432/your_db
| File | Purpose |
|---|---|
.env in Superset repo root |
Sets DATABASE_PORT=5433 for Docker Compose port publishing |
docker/.env |
Upstream default container runtime values |
docker/.env-local |
Local ignored overrides such as SUPERSET_SECRET_KEY, TAILSCALE_HOSTNAME, and MCP settings |
docker/local/nginx/superset.conf.template |
Local ignored nginx HTTPS template |
docker/local/certs/ |
Local ignored Tailscale TLS certificate and key files |
docker-compose.override.yml |
Local ignored Docker Compose overrides for HTTPS and MCP |
superset_config.py |
Local ignored Superset runtime config including MCP and security API settings |
# First start with image build
docker compose up --build
# Normal start
docker compose up -d
# Recreate the web layer after local override changes
docker compose up -d --force-recreate --no-deps superset nginx
# Recreate MCP after config or healthcheck changes
docker compose up -d --force-recreate --no-deps mcp
# Stop all services
docker compose down
# Restart only nginx after config changes
docker compose up -d --no-build nginx
# Show running containers and published ports
docker ps --format "table \t"
# Follow logs
docker compose logs -f superset
docker compose logs -f superset-init
docker compose logs -f mcp