Deploiement Apache Superset sur Ouranos¶
Presentation¶
Apache Superset est un outil de BI open-source avec des visualisations avancees incluant des cartes deck.gl (scatter, heatmap, polygon). Il est deploye sur le VPS Ouranos pour completer Metabase avec des visualisations geographiques et un cloisonnement fin des donnees par utilisateur (Row-Level Security).
Prerequis¶
- Acces SSH au VPS Ouranos
- Portainer operationnel
- Reseau Docker
shared-networkexistant - Token Mapbox : https://account.mapbox.com/
- SECRET_KEY generee :
openssl rand -base64 42
Etape 1 — Fichier de configuration sur le VPS¶
Ce fichier est monte en lecture seule dans chaque conteneur Superset. Il lit les variables d'environnement au demarrage.
sudo mkdir -p /opt/superset-config
sudo tee /opt/superset-config/superset_config.py > /dev/null <<'EOF'
import os
SECRET_KEY = os.environ.get("SUPERSET_SECRET_KEY", "CHANGE_ME")
SQLALCHEMY_DATABASE_URI = (
f"postgresql+psycopg2://"
f"{os.environ.get('DATABASE_USER', 'superset')}:"
f"{os.environ.get('DATABASE_PASSWORD', 'superset')}@"
f"{os.environ.get('DATABASE_HOST', 'superset-db')}:"
f"{os.environ.get('DATABASE_PORT', '5432')}/"
f"{os.environ.get('DATABASE_DB', 'superset')}"
)
class CeleryConfig:
broker_url = f"redis://{os.environ.get('REDIS_HOST', 'superset-redis')}:{os.environ.get('REDIS_PORT', '6379')}/0"
result_backend = f"redis://{os.environ.get('REDIS_HOST', 'superset-redis')}:{os.environ.get('REDIS_PORT', '6379')}/0"
CELERY_CONFIG = CeleryConfig
MAPBOX_API_KEY = os.environ.get("MAPBOX_API_KEY", "")
WTF_CSRF_ENABLED = True
# Langue par defaut : francais
BABEL_DEFAULT_LOCALE = "fr"
# Langues disponibles dans le menu
LANGUAGES = {
"fr": {"flag": "fr", "name": "Français"},
"en": {"flag": "us", "name": "English"},
}
EOF
Verifier :
sudo file /opt/superset-config/superset_config.py
# Doit afficher : "Python script" ou "ASCII text"
Bind mount Docker
Si le fichier n'existe pas au moment du deploiement, Docker cree un dossier a la place. Toujours creer le fichier AVANT de deployer la stack.
Etape 2 — Variables d'environnement Portainer¶
| Variable | Description |
|---|---|
SUPERSET_SECRET_KEY |
Cle de chiffrement (resultat de openssl rand -base64 42) |
SUPERSET_DB_PASSWORD |
Mot de passe BDD interne Superset |
SUPERSET_ADMIN_USERNAME |
Username admin (defaut : admin) |
SUPERSET_ADMIN_EMAIL |
Email admin |
SUPERSET_ADMIN_PASSWORD |
Mot de passe admin |
MAPBOX_TOKEN |
Token API Mapbox pour les cartes deck.gl |
Etape 3 — Docker Compose¶
Portainer → Stacks → Add Stack → Nom : superset → coller le compose → ajouter les variables → Deploy.
version: "3.8"
x-superset-env: &superset-env
SUPERSET_SECRET_KEY: ${SUPERSET_SECRET_KEY}
SUPERSET_CONFIG_PATH: /app/superset_config.py
DATABASE_DB: superset
DATABASE_HOST: superset-db
DATABASE_USER: superset
DATABASE_PASSWORD: ${SUPERSET_DB_PASSWORD}
DATABASE_PORT: "5432"
REDIS_HOST: superset-redis
REDIS_PORT: "6379"
MAPBOX_API_KEY: ${MAPBOX_TOKEN}
x-superset-volumes: &superset-volumes
- superset_home:/app/superset_home
- /opt/superset-config/superset_config.py:/app/superset_config.py:ro
services:
superset-redis:
image: redis:7
container_name: superset_cache
restart: unless-stopped
volumes:
- superset_redis_data:/data
networks:
- superset-net
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
superset-db:
image: postgres:16-alpine
container_name: superset_db
restart: unless-stopped
labels:
- "com.centurylinklabs.watchtower.enable=false"
environment:
POSTGRES_DB: superset
POSTGRES_USER: superset
POSTGRES_PASSWORD: ${SUPERSET_DB_PASSWORD}
volumes:
- superset_db_data:/var/lib/postgresql/data
networks:
- superset-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U superset -d superset"]
interval: 10s
timeout: 5s
retries: 5
superset-init:
image: apache/superset:latest-dev
container_name: superset_init
depends_on:
superset-db:
condition: service_healthy
superset-redis:
condition: service_healthy
environment:
<<: *superset-env
user: root
volumes: *superset-volumes
networks:
- superset-net
entrypoint: /bin/bash
command:
- -c
- |
superset db upgrade
superset fab create-admin --username ${SUPERSET_ADMIN_USERNAME:-admin} --firstname Admin --lastname User --email ${SUPERSET_ADMIN_EMAIL:-admin@superset.com} --password ${SUPERSET_ADMIN_PASSWORD} || true
superset init
restart: "no"
superset-app:
image: apache/superset:latest-dev
container_name: superset_app
restart: unless-stopped
depends_on:
superset-init:
condition: service_completed_successfully
environment:
<<: *superset-env
user: root
ports:
- "8088:8088"
volumes: *superset-volumes
networks:
- superset-net
- shared-network
command: ["gunicorn", "--bind", "0.0.0.0:8088", "--workers", "4", "--timeout", "120", "superset.app:create_app()"]
superset-worker:
image: apache/superset:latest-dev
container_name: superset_worker
restart: unless-stopped
depends_on:
superset-init:
condition: service_completed_successfully
environment:
<<: *superset-env
user: root
volumes: *superset-volumes
networks:
- superset-net
- shared-network
command: ["celery", "--app=superset.tasks.celery_app:app", "worker", "--loglevel=info"]
volumes:
superset_redis_data:
superset_db_data:
superset_home:
networks:
superset-net:
driver: bridge
shared-network:
external: true
Image latest-dev
L'image apache/superset:latest-dev inclut psycopg2 et tous les drivers BDD. L'image latest (lean) ne les inclut pas.
Etape 4 — Verifier le demarrage¶
sudo docker logs superset_init
# "Admin User admin created." + pas d'erreur
sudo docker logs superset_app
# "Listening at: http://0.0.0.0:8088"
Etape 5 — Se connecter¶
- URL :
http://IP_VPS:8088 - Login :
admin/ mot de passe defini dansSUPERSET_ADMIN_PASSWORD
Etape 6 — Route Cloudflare tunnel¶
Dashboard Cloudflare Zero Trust → Tunnels → Public Hostname :
| Champ | Valeur |
|---|---|
| Subdomain | superset |
| Service | http://superset_app:8088 |
Etape 7 — Connecter la BDD de donnees BI¶
La BDD interne Superset ne contient que les metadata (users, dashboards). Les donnees BI sont dans la BDD Metabase.
- Settings (engrenage) → Database Connections → + Database → PostgreSQL
- Remplir :
| Champ | Valeur |
|---|---|
| Host | metabase-postgres |
| Port | 5432 |
| Database | metabase |
| Username | user PostgreSQL Metabase |
| Password | password PostgreSQL Metabase |
| Display Name | Donnees BI |
- Test Connection → doit etre vert
- Connect
Pourquoi metabase-postgres ?
Le nom d'hote metabase-postgres est le nom du conteneur PostgreSQL de la stack Metabase. superset_app y accede via le reseau Docker shared-network.
Etape 8 — Creer une carte deck.gl¶
- Charts → + Chart
- Dataset : ta vue PostgreSQL (ex:
vue_commandes_geo) - Chart type : deck.gl Scatterplot
- Configurer :
| Parametre | Colonne |
|---|---|
| Longitude | longitude |
| Latitude | latitude |
| Color | societe (categoriel) |
| Point Size | quantite |
- Run Query → la carte s'affiche
- Save → choisir ou creer un dashboard
Mises a jour¶
Watchtower met a jour apache/superset:latest-dev automatiquement (dimanche 00h30).
Pour forcer une MAJ :
sudo docker pull apache/superset:latest-dev
# Puis redemarrer la stack dans Portainer
Pour figer une version :
- Remplacer latest-dev par un tag fixe (ex: 4.0.2-dev)
- Ajouter le label com.centurylinklabs.watchtower.enable=false sur superset-app et superset-worker
Row-Level Security — Cloisonnement par utilisateur¶
- Settings → List Roles → + → creer un role (ex: "Commercial Dupont")
- Settings → List Users → + → assigner le role
- Settings → Row Level Security → + Rule :
| Champ | Valeur |
|---|---|
| Table | vue_commandes_geo |
| Roles | Commercial Dupont |
| Clause | societe = 'Dupont et Fils' |
L'utilisateur ne voit que les commandes de sa societe sur la carte. L'admin voit tout.
Depannage¶
| Probleme | Cause | Solution |
|---|---|---|
| "Refusing to start due to insecure SECRET_KEY" | Fichier config non monte ou variable vide | Verifier /opt/superset-config/superset_config.py et SUPERSET_SECRET_KEY dans Portainer |
| "No module named psycopg2" | Image latest au lieu de latest-dev |
Changer le tag image |
| "IsADirectoryError: /app/superset_config.py" | Fichier n'existait pas au premier deploy | sudo rm -rf /opt/superset-config/superset_config.py puis recreer |
| "Invalid credentials" au login | Admin cree avec ancien mot de passe | sudo docker exec -it superset_app superset fab reset-password --username admin --password NouveauMDP |
| Superset ne voit pas metabase-postgres | Reseau shared-network non connecte | Verifier sudo docker network inspect shared-network |