ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Superset 4.1.1 Docker离线部署实战与避坑指南

Superset 4.1.1 Docker离线部署实战与避坑指南 简介这一份基于 Docker 离线部署 Superset 4.1.1 中文版的完整资源包面向需要内网或离线环境快速搭建数据可视化平台的企业运维人员、数据分析师和开发者。包内包含 6 个文件涵盖 3 个 Docker 镜像压缩包、容器编排文件、Superset 配置文件与 .env 环境变量模板用户在无外网条件下也可直接拉起 Superset 服务。压缩包约 524.2MB镜像涵盖 Superset、PostgreSQL 与 Redis配置与编排文件帮助理解容器化部署的关键环节降低初学者的上手门槛。目前已有 364 人学习下载。借助这份资料可掌握 Docker Compose 多容器编排、环境变量配置、Superset 中文界面启用等核心操作并可直接复用镜像与配置减少从零搭建与排错时间适合需要快速交付数据探索与可视化能力的中小型团队。1. 为什么值得折腾 Superset 4.1.1 的 Docker 离线部署Superset 4.1.1 的 Docker 离线部署是我今年做过最「省心又闹心」的一件事。省心的是一旦把镜像和 compose 文件准备好内网机器上只要装好 Docker十分钟左右就能把 BI 平台跑起来闹心的是Superset 官方镜像默认不带完整中文字体元数据库默认 SQLite根本不适合真实生产场景。这套资源解决的不是「如何 pip install superset」而是「如何在完全没有外网的环境里把 4.1.1 中文版稳定运行起来」包括离线镜像导出导入、PostgreSQL Redis 持久化、初始化脚本和常见坑的规避。适合内网运维、数据分析工程师以及所有需要在政务云或企业内网交付 BI 平台的人。2. 离线镜像构建与迁移两步走避免在 Docker Hub 上碰壁2.1 为什么不能直接拉官方镜像官方apache/superset:4.1.1是基于 Debian 的镜像里面同时跑了 gunicorn、Flask 和 Celery worker体量不小。4.1.1 相比 4.0 的改进主要在图表渲染速度和 SQL Lab 的查询体验上但底子没变镜像里没有中文字体默认语言配置是空的元数据库是 SQLite连superset_config.py都没有主动提供一个克隆模板。你可能觉得进容器后再补配置就行但问题是离线环境里 apt 源都连不上想现装字体和 Python 依赖根本不可能。我见过一个团队把官方镜像直接docker save到内网结果启动后图表中文全变方块想去容器里装fonts-wqy-zenheiapt update 直接超时。最后只能重新在有网机器上做镜像来回折腾了两天。所以离线部署第一件事就是提前把所有运行时依赖打进镜像里而不是指望内网环境能临时补救。2.2 构建私有镜像Dockerfile 关键层拆解先看一份完整可用的 Dockerfile我基于apache/superset:4.1.1做了四件事装中文字体、覆盖配置、放初始化脚本、替换默认启动命令。FROM apache/superset:4.1.1 # 安装中文字体避免图表和导出 PDF 出现方块 USER root RUN apt-get update apt-get install -y --no-install-recommends \ fonts-wqy-zenhei fonts-wqy-microhei \ rm -rf /var/lib/apt/lists/* # 把自定义配置拷进镜像同时也作为 compose 挂载的备份 COPY superset_config.py /app/superset_config.py ENV SUPERSET_CONFIG_PATH/app/superset_config.py ENV LANGUAGES{zh: {flag: cn, name: Chinese}} # 初始化脚本启动前执行 db upgrade 和 init COPY init_superset.sh /app/init_superset.sh RUN chmod x /app/init_superset.sh USER superset CMD [/app/init_superset.sh]这里有几个关键层要拆开看。fonts-wqy-zenhei是文泉驿正黑比 Noto CJK 体积小覆盖常用汉字足够fonts-wqy-microhei补充小字号显示避免 PDF 导出时锯齿明显。--no-install-recommends是为了不拉字体相关的推荐包否则镜像体积会多出两三百 MB。USER root只在安装字体阶段需要装完立刻切回superset用户保证容器进程不是 root 权限这条对生产环境很重要。superset_config.py里至少要定义这些内容import os SECRET_KEY os.environ.get(SECRET_KEY, please_change_me) SQLALCHEMY_DATABASE_URI os.environ.get( SQLALCHEMY_DATABASE_URI, postgresqlpsycopg2://superset:superset_pwdpostgres:5432/superset ) REDIS_HOST os.environ.get(REDIS_HOST, redis) REDIS_PORT int(os.environ.get(REDIS_PORT, 6379)) REDIS_CELERY_BROKER_URL fredis://{REDIS_HOST}:{REDIS_PORT}/0SECRET_KEY不能写死在配置文件里要允许 compose 环境变量覆盖不然每次改动配置都要重建镜像。SQLALCHEMY_DATABASE_URI默认指向 compose 里的postgres服务名这个技巧会让容器在 Docker 网络中自动解析到数据库地址。REDIS_CELERY_BROKER_URL是给 Celery 用的Superset 的异步导出和图表缓存依赖它。init_superset.sh也不能写得太粗暴#!/bin/bash set -e superset db upgrade superset init exec gunicorn --bind 0.0.0.0:8088 \ --workers 4 \ --timeout 120 \ superset.app:create_app()db upgrade负责把元数据库表结构同步到当前版本init会创建默认角色和权限。每次容器启动都执行这两条命令在数据表已经存在时不会重复建表属于幂等操作。但如果你想严格控制可以在脚本里加一个标志文件判断是否已初始化。这里用exec是为了让 gunicorn 直接接管 PID 1docker stop时能正确收到 SIGTERM否则容器会等超时才退出。2.3 导出与导入docker save 与 docker load 的正确姿势镜像构建完成后在有网机器上执行以下命令docker build -t superset-cn:4.1.1 . docker tag superset-cn:4.1.1 registry.internal/superset-cn:4.1.1 docker save registry.internal/superset-cn:4.1.1 | gzip superset-cn-4.1.1.tar.gzdocker save后面必须跟镜像名加标签不能跟容器 ID。通常我会先docker tag一个带内网仓库地址的名比如registry.internal/superset-cn:4.1.1这样镜像传到离线机器后compose 文件里写同一个镜像名Docker 就能精准匹配不会出现「明明本地有镜像却因为 tag 对不上而尝试 pull 外网」的尴尬。gzip 压缩后1.6GB 的镜像大概能缩到 700MB 左右U 盘或者内网共享目录都能轻松传输。离线机器上执行导入docker load -i superset-cn-4.1.1.tar.gz docker images | grep superset看到registry.internal/superset-cn:4.1.1的 repository 和 tag 就是你导入成功的标志。注意docker load之后镜像就已经在本地 Docker 守护进程里了不需要再执行docker pull。如果你用的docker-compose.yml里没有特殊写pull_policycompose 启动时会优先用本地镜像不会去外网拉取。这里我踩过一个教训第一次离线部署时我把镜像 tag 成了superset:latest结果内网机器上以前刚好有个同名镜像占着导致docker load被覆盖。从那以后我所有离线镜像都会带上版本号和一个内部仓库前缀绝不裸用latest。2.4 离线机器上的校验与误用导入完成后别急着启动先校验一下镜像内容docker inspect --format {{.Config.Cmd}} registry.internal/superset-cn:4.1.1 docker run --rm registry.internal/superset-cn:4.1.1 fc-list | grep wqy第一条命令确认启动命令是我们的init_superset.sh而不是官方默认的 gunicorn 入口。第二条命令确认字体已经装进系统层如果没输出wqy-zenhei相关路径说明 Dockerfile 里 apt 安装步骤被跳过或者基础镜像源有问题需要回炉重建。常见的误用是把docker save和docker export搞混。docker export导出的是容器文件系统会丢失镜像的层历史、标签、Entrypoint 和 CMD哪怕是同一个容器docker import之后也无法用 compose 按原配置启动。离线迁移镜像永远是docker savedocker load。3. docker-compose 编排与持久化一份配置文件把 4.1.1 伺候好3.1 为什么用 compose 而不是裸 docker runSuperset 虽然可以单容器跑但真实使用中至少要同时拉起 PostgreSQL 和 Redis。用docker run一条条命令拼环境变量、端口、挂载卷全混在 shell 历史里换台机器就要重敲一遍非常容易漏。我习惯用 docker-compose 把服务依赖、健康检查、数据卷都声明在同一个文件里这样离线交付时只需要提供两个东西一个docker-compose.yml一个.env文件。运维同事拿到手docker compose up -d就能跑不用问任何问题。3.2 完整的 docker-compose 配置先看我的 compose 文件核心部分version: 3.8 services: superset: image: registry.internal/superset-cn:4.1.1 container_name: superset environment: SUPERSET_CONFIG_PATH: /app/superset_config.py SECRET_KEY: ${SECRET_KEY} LANGUAGES: {zh: {flag: cn, name: Chinese}} ports: - 8088:8088 volumes: - ./superset_home:/app/superset_home depends_on: postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped postgres: image: postgres:15 container_name: superset_postgres environment: POSTGRES_DB: superset POSTGRES_USER: superset POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - pg_data:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U superset] interval: 5s timeout: 3s retries: 5 redis: image: redis:7-alpine container_name: superset_redis volumes: - redis_data:/data healthcheck: test: [CMD, redis-cli, ping] interval: 5s timeout: 3s retries: 5 volumes: pg_data: redis_data:参数说明如下服务关键配置用途supersetdepends_oncondition确保数据库和缓存健康后再启动避免 500supersetSECRET_KEY会话签名必须固定否则重启就掉登录postgrespg_data命名卷元数据库持久化容器重建数据不丢redisredis_data命名卷缓存和 Celery broker 持久化healthcheckpg_isready/redis-cli pingcompose 等待依赖时用还能做容器状态感知depends_on不能只写服务名要写成带condition的字典形式。如果只写depends_on: [postgres]compose 只会等容器启动不会等 PostgreSQL 真正准备好Superset 起来后数据库连接会失败然后自动退出。用service_healthy是等健康检查通过这个模式在离线部署里特别有用。3.3 superset_config.py 与环境变量的配合compose 里设置的SECRET_KEY会作为环境变量传进容器而容器里的superset_config.py恰好用os.environ.get(SECRET_KEY)读取。这样配置的优先级就变成了环境变量 配置文件默认值。生产环境换一台机器时只需要修改.env文件不用动镜像和代码。.env文件内容大致是SECRET_KEYcf5a0d2c-4a6e-4f27-8e5f-2b6f9c1d7a23 POSTGRES_PASSWORDsuperset_pwd_strong然后 compose 里用${SECRET_KEY}引用。注意.env文件不要提交到 git 仓库否则密钥和密码会曝光。3.4 初始化数据库与创建管理员账号首次启动我建议分三步走而不是直接docker compose up -d。先拉起数据库和缓存docker compose up -d postgres redis等两个容器都进入 healthy 状态后执行初始化docker compose run --rm superset superset db upgrade docker compose run --rm superset superset initdb upgrade会把 Superset 的元数据表建到 PostgreSQL 里init会创建默认权限角色、管理员角色和一些基础配置。这两条命令执行完再启动全部服务docker compose up -d创建你自己的管理员账号时不要用默认 admin 登录而是手动创建一个docker compose exec superset superset fab create-admin \ --username bi_admin \ --firstname BI \ --lastname Admin \ --email adminexample.com \ --password admin123 \ --no-autoconfig--no-autoconfig表示不走环境变量里的自动配置避免不小心把密码暴露在 shell 历史里。创建完这个账号原默认 admin 即使存在也建议立即改密或禁用。3.5 启用中文界面与验证如果你的LANGUAGES环境变量包含了zhSuperset 登录后右上角用户菜单里会出现语言下拉框切到 Chinese 即可。如果下拉框里的中文选项是灰的说明LANGUAGES里的 JSON 字符串格式有问题比如用了单引号而不是双引号包裹外层。可以这样验证docker compose exec superset python -c from superset.config import *; print(zh in LANGUAGES)输出True说明语言包已加载。如果输出False大概率是环境变量里的 JSON 被转义成了字符串需要检查 compose 文件里是否少了一层转义。同时确认中文字体已生效docker compose exec superset fc-list | grep wqy这条命令能看到 wqy 字体路径有输出就放心用。没有输出时先确认镜像构建阶段是否真的执行了 apt 安装而不是被 Docker BuildKit 缓存跳过。4. 避坑离线部署 Superset 的五个翻车现场4.1 现象docker load 完成后 compose 依然去拉远程仓库现象镜像明明已经在本地docker compose up -d却一直在 pull最终超时失败日志里能看到error while pulling image之类的内容。原因compose 文件里的image字段和docker load进去的镜像 tag 不完全一致。最常见的是 compose 写apache/superset:4.1.1而 load 进去的私有 tag 是registry.internal/superset-cn:4.1.1。Docker 在本地找不到精确 tag 匹配时会尝试去 registry 拉取同名镜像。解决每次写 compose 前先执行docker images把 repository 和 tag 完整复制到 compose 里。另外在 compose 服务定义中显式加上pull_policy: never这会让 Docker 只使用本地镜像拉取失败直接报错而不是默默去外网。对离线环境来说pull_policy: never是保险中的保险。4.2 现象容器起来了但页面 500日志里报 database connection failed现象Superset 容器状态是 Up但访问http://服务器IP:8088出现 500docker compose logs superset里出现could not connect to server: Connection refused。原因superset_config.py里的数据库连接串写了localhost:5432。在容器内部localhost指向 Superset 容器自己而 PostgreSQL 跑到另一个容器的网络命名空间里去了。宿主机、Redis 容器、Superset 容器的localhost是完全不同的三个地址。解决把SQLALCHEMY_DATABASE_URI中的主机名改成 compose 服务名postgresSQLALCHEMY_DATABASE_URI postgresqlpsycopg2://superset:superset_pwdpostgres:5432/superset同时确认depends_on的condition: service_healthy是否生效。如果仍在报错单独检查 postgres 是否真的 healthydocker compose ps查看状态列。4.3 现象登录后频繁掉线几乎每次刷新都要重登现象管理员账号登录后操作两三分钟页面跳回登录页刷新后又得输密码多台浏览器都这样。原因SECRET_KEY没有固定。Superset 使用 Flask-Login 的签名 cookie这个签名依赖SECRET_KEY。默认情况下每次容器重启都会重新生成一个随机密钥导致之前签发的会话失效。如果SECRET_KEY环境变量为空Superset 进程每次重启都会换新。解决用 openssl 生成一个固定密钥写进.env文件openssl rand -base64 42把输出粘贴到.env的SECRET_KEY后面。然后docker compose up -d让 superset 容器重新读取环境变量。修复后即使容器重启只要密钥没变会话依然有效。4.4 现象图表能打开但刷新后数据源配置丢失现象明明在 Superset 里配置好了数据库连接和仪表盘第二天打开页面发现连接列表空了或者之前创建的图表消失。原因PostgreSQL 没有做持久化。compose 里的 postgres 服务如果没有声明 volume数据存储在容器可写层容器一旦用docker compose down删除或重建数据全部丢失。docker compose down默认不删卷但如果你没有先定义卷数据就在容器里重建容器等于清空。解决检查 compose 里 postgres 是否声明了pg_data:/var/lib/postgresql/data。再补一条验证命令docker volume ls | grep pg_data如果找不到卷说明之前没有正确挂载。修复后重新创建卷并重新执行db upgrade和init。另外所有重要的数据库连接配置都在 PostgreSQL 里所以这个卷的备份优先级最高。4.5 现象内网装 Python 插件失败pip install 直接卡死现象需要在 Superset 里接一个第三方数据库驱动登录到容器执行pip install xxx然后一直卡在Retrying最终超时。原因离线容器的默认 pip 源指向 PyPI内网没有出网权限连接被拒或超时。这是离线部署里最常见的次生问题Superset 镜像本身没问题但你想扩展插件时才发现环境是封闭的。解决在有网机器上预先下载所有 wheel 包pip download -r requirements.txt -d ./wheels --no-deps然后把wheels目录一起带到内网挂载进容器或放入镜像。容器内安装时指定本地源pip install --no-index --find-links/app/wheels psycopg2-binary更一劳永逸的做法是把这类插件依赖提前写进 Dockerfile 的pip install步骤构建镜像时就把驱动装完。这样离线交付的镜像本身就包含插件能力内网不需要再碰 pip。5. 验证与维护一条命令确认版本两个习惯降低后期翻车率部署完成不能直接交付先跑一遍验证流程。我的习惯是这样docker compose exec superset superset version正常会输出4.1.1。接着探活curl -s http://localhost:8088/health返回OK说明 Flask 应用活着。再到仪表盘随便渲染一个图表确认 PostgreSQL 连接和 Redis 缓存都正常。图表加载慢时先看 Redis 内存占用而不是怀疑服务器配置docker compose exec redis redis-cli info memory离线环境最难的是事后补救所以备份要前置。我一般用pg_dump做定时备份docker compose exec postgres pg_dump -U superset superset backup_$(date %F).sql恢复时先停掉 superset 服务再执行psql -U superset superset backup.sql避免写入冲突。这条命令可以放进 crontab每周跑一次备份文件异地存放。另一个习惯是把密钥和密码全部提取到.envcompose 文件里只留${SECRET_KEY}这种引用。这样共享 compose 文件不会泄漏敏感信息换环境也只需要改一个文件。我甚至会在.env里写SUPERSET_WEBSERVER_TIMEOUT120用环境变量覆盖 Flask 的超时值避免大查询长时间运行导致前端 504。说到教训中文字体这件事我吃亏最大。第一次离线交付时忘了验证字体领导要导出 PDF 报表图表标题全是方块场面非常尴尬。从那以后我每次做完镜像都会强制跑一遍fc-list | grep wqy确认无误才打包。这套流程里的很多细节都是这么一点点补进去的。希望你也别在同一个地方第二次翻车这份离线部署资源能帮你把这些前置工作一次性做对。本文还有配套的精品资源点击获取
返回列表