资讯动态

Superset 4.1.1离线部署指南:从镜像到内网BI看板

发布时间:2026/10/16 22:33:31 来源:尧图企业网站定制
简介面向需要在隔离网络、内网或离线环境中部署数据可视化平台的运维与开发人员Superset 4.1.1 中文版 Docker 离线部署包提供了一套开箱即用的完整方案。压缩包共6个文件包含3个预打包的Docker镜像tar文件涵盖Superset应用、PostgreSQL数据库、Redis缓存等核心组件、1个docker-compose.yml编排文件、1个superset_config.py配置文件和1个.env环境变量文件整体约524.2MB用户无需外网即可导入镜像并一键启动服务。目前已有368人学习下载适合具备基础Docker操作能力、希望快速搭建企业内网数据探索平台的中高级工程师。下载后可获得整合好的中文版Superset环境及配套配置借助Compose命令完成多容器编排同时保留数据库连接、安全认证等关键配置示例大幅降低部署门槛提升数据分析交付效率。该包尤其适合需要内网交付、数据私有化部署的企业用户。1. Superset 4.1.1 离线部署内网环境的一次完整交付某公司的数据团队要搭一套内部 BI 看板上游是几个业务库的只读账号。环境在隔离内网没有外网docker pull 和 pip install 全部不可用。选型落到 Superset 4.1.1开源、能连多类数据库、看板功能够用。原本以为标准 Docker 部署拉起来就行真正落地时才发现离线场景的坑全部藏在镜像导出、compose 编排、初始化顺序和中文化里。这篇把整套流程拆成可复现步骤从镜像搬运、元数据库持久化、管理员创建到数据库驱动插件安装和中文界面切换适合要给内网交付 BI 工具的从业者也适合第一次接触 Superset 的开发者照着完整跑一遍。2. 镜像收集与导出把依赖镜像完整搬到隔离网络2.1 先盘清镜像依赖关系Superset 4.1.1 不是孤立容器官方 compose 部署至少包含三个服务superset 主应用、postgres保存报表元数据和 redis缓存与异步任务。离线部署第一步不是 docker pull而是先列清单哪些镜像必须导出、每个镜像的 tag 是什么、宿主机架构是 amd64 还是 arm64。常见的坑是有人只导出主应用镜像遗漏 redis 和 postgres到内网 docker compose up 时直接报 pull access denied。另一个更隐蔽的坑是 tag 含含糊糊比如导出时用了 latestload 到内网后又换了内容回滚都没得回滚。我一般会在联网机器上先写一个版本清单文件记录镜像名、tag、镜像 ID 和用途再批量拉取。这一步只花几分钟却能让后面节省大量时间。还有个细节arm64 和 amd64 的镜像 ID 完全不同导出前用 docker images --format 确认平台避免把 amd64 的包灌进 arm 机器否则容器能 load 但启动时可能直接 segfault。注意离线部署前先确认所有镜像都已经在联网机器上docker run过一次避免遗漏启动时才拉取的辅助镜像。2.2 拉取并导出 tar 包批量拉取命令很简单docker pull apache/superset:4.1.1 docker pull postgres:16-alpine docker pull redis:7-alpine如果联网机器有镜像仓库代理可以先把代理配置好再拉但这里重点是拉下来之后的导出。导出的核心命令是 docker savemkdir -p /data/offline-images docker save -o /data/offline-images/superset-4.1.1.tar apache/superset:4.1.1 docker save -o /data/offline-images/postgres-16.tar postgres:16-alpine docker save -o /data/offline-images/redis-7.tar redis:7-alpine-o 参数指定输出文件镜像名必须带完整 tag不建议用 IMAGE ID因为用 ID 导出的包在内网 load 后容易产生同名镜像 ID 冲突排查起来很折腾。docker save 会把镜像的所有层连同元数据打成一个 tar 包Superset 主镜像通常在 1.5GB 到 2GB 之间。如果通过 U 盘或内网共享搬运建议先压缩gzip -k superset-4.1.1.targzip 之后体积能压缩一半左右内网端解压再 load。tar 包超过 2GB 时用 split 切成多个分片split -b 2G -d superset-4.1.1.tar superset-part- cat superset-part-* superset-4.1.1.tarsplit 的 -b 2G 表示每个分片 2GB-d 表示用数字后缀命名合并时 cat 的顺序不能乱所以分片文件名要按顺序保留。实际传输中我试过 U 盘、内网共享和移动硬盘三种方式核心原则只有一个传输后先做一致性校验不要直接 load。2.3 内网导入与校验在内网机器上把 tar 传过去之后导入不能直接 docker load 就完事先做 md5 校验md5sum superset-4.1.1.tar checksum.txt md5sum -c checksum.txtmd5 校验在离线场景里特别重要。tar 文件在传输过程中只要损坏一个字节docker load 可能不报错但容器启动到某一层时会出现莫名其妙的 tar: Unexpected EOF 或运行时崩溃。这类问题排起来非常耗时校验是最便宜的后悔药。校验通过后导入docker load -i superset-4.1.1.tar docker load -i postgres-16.tar docker load -i redis-7.tarload 完成后用 docker images 检查。正常情况下应该看到三行 REPOSITORY 和 TAG且镜像 ID 与联网机器一致。如果某个镜像 TAG 变成none说明 save 时用了短 ID 或者中间层被打包处理办法在第五章展开。2.4 把数据库驱动插件打进镜像官方镜像内置的数据库驱动只有 PostgreSQL、SQLite 等少数几种实际业务常常要连 MySQL、ClickHouse 或 SQL Server。隔离内网里没法 pip install最稳的做法是在联网机器上准备 Python wheel 包写一个自定义镜像FROM apache/superset:4.1.1 USER root COPY ./wheels /tmp/wheels RUN pip install --no-index --find-links/tmp/wheels \ clickhouse-driver0.2.8 \ pymysql1.1.1 USER superset这段 Dockerfile 做了三件事切换到 root 安装系统级依赖用 --no-index 强制不走网络--find-links 指定本地 wheel 目录装完切回 superset 用户避免容器以 root 运行产生权限风险。wheel 打包这一步在联网机器上执行pip download --only-binary:all: --python-version 3.11 --platform manylinux2014_x86_64 \ --dest ./wheels clickhouse-driver pymysql这里指定 Python 版本和平台是为了和 Superset 4.1.1 镜像内的 Python 环境匹配。镜像的 Python 版本可以用docker run --rm apache/superset:4.1.1 python --version查看先记下来再决定 --python-version 参数。平台、版本、glibc 三个要素只要错一个内网 pip install 时会直接报找不到版本而且 --no-index 模式下错误信息更晦涩。实际项目里见过有人图省事直接进容器 pip install配好数据源后容器一重启所有驱动全丢。重新构建镜像虽然多花几分钟但内网交付时只需要这一个自包含镜像后面运维不用重复踩这个坑。3. Compose 编排与持久化让三个容器按要求启动3.1 离线环境的 docker-compose.yml 怎么写镜像准备好之后内网部署的入口是 docker-compose.yml。为什么不用 docker run 一条条执行三个容器之间有依赖关系用 docker run 只能靠脚本控制启动顺序出问题不好回滚。compose 把网络、环境变量、数据卷和健康检查都声明在一个文件里离线环境同样适用前提是镜像全部 load 到本机。下面这份是排过坑的版本version: 3.8 services: superset-db: image: postgres:16-alpine restart: always environment: POSTGRES_USER: superset POSTGRES_PASSWORD: superset POSTGRES_DB: superset volumes: - ./pgdata:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U superset] interval: 10s timeout: 5s retries: 5 superset-cache: image: redis:7-alpine restart: always superset: image: apache/superset:4.1.1 restart: always environment: SUPERSET_ADMIN_USERNAME: admin SUPERSET_ADMIN_PASSWORD: admin123 SUPERSET_ADMIN_EMAIL: adminexample.local SUPERSET_ADMIN_FIRSTNAME: Admin SUPERSET_ADMIN_LASTNAME: User volumes: - ./superset_config.py:/app/pythonpath/superset_config.py - ./superset_home:/app/superset_home ports: - 8088:8088 depends_on: superset-db: condition: service_healthy superset-cache: condition: service_started healthcheck: test: [CMD-SHELL, python -c \import urllib.request; urllib.request.urlopen(http://localhost:8088/health)\] interval: 30s timeout: 10s retries: 3这份 compose 的关键点postgres 服务用 healthcheck 里的 pg_isready 告诉 superset 数据库已就绪superset 的 depends_on 用了 condition 形式而不是简单启动顺序。如果没有 healthcheck容器起来只代表进程活着不代表端口能接受连接superset 启动时 SQLAlchemy 连不上 postgres 就会抛 connection refused 并退出。superset 镜像默认不是 root 用户挂载./superset_config.py时要注意宿主机文件权限。我一般把配置文件放到 compose 同目录并 chmod 644superset_home 目录给当前用户可写权限否则容器内写 /app/superset_home 会报 PermissionError。这类权限问题逻辑上不复杂但排查时容易被归到玄学范畴实际就是权限位没对齐。3.2 superset_config.py元数据库、缓存与安全密钥配置文件是整个部署的核心内容不长每个参数都直接影响运行行为import os SECRET_KEY a-very-long-random-string-please-change-in-production SQLALCHEMY_DATABASE_URI os.environ.get( SQLALCHEMY_DATABASE_URI, postgresql://superset:supersetsuperset-db:5432/superset ) REDIS_HOST os.environ.get(REDIS_HOST, superset-cache) REDIS_PORT 6379 REDIS_CELERY_DB 1 REDIS_CACHE_DB 0 REDIS_CELERY_BROKER_URL fredis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CELERY_DB} REDIS_CELERY_RESULT_BACKEND fredis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CELERY_DB} BABEL_DEFAULT_LOCALE zh LANGUAGES { en: {flag: us, name: English}, zh: {flag: cn, name: 中文}, }SECRET_KEY 必须固定成一个随机长字符串不要用默认值否则容器重启后所有会话失效、CSRF 校验频繁报错。SQLALCHEMY_DATABASE_URI 里的主机名写成 compose 服务名 superset-db容器在同一个 compose 网络里通过服务名互通不能写 localhost。REDIS 配置把缓存和 Celery broker 分成两个 db实际部署中经常有人省掉这两行结果缓存和异步任务共用同一个 db数据混乱后界面行为变得不可预期。BABEL_DEFAULT_LOCALE 设为 zhLANGUAGES 里保留 en 作为回退。Superset 的翻译文件如果不存在界面会退回英文而不是报错所以设置语言后要检查容器内翻译文件是否存在这个放到第六章讲。配置文件通过 volume 挂载到 /app/pythonpath/superset_config.py这是 Superset 读取配置的默认路径。改完配置后只需要重启容器docker compose restart superset不需要重新 build因为挂载的是文件restart 后进程会重新读取。3.3 数据卷与启动顺序数据卷分三类postgres 的 pgdata 目录保存元数据库里面是所有报表、图表、仪表盘的定义备份就看这个目录superset_home 里存上传文件、导出的 CSV、暂存查询结果配置文件单独挂载。三个目录都应该放在非系统盘最好单独做定期备份策略。启动顺序上depends_on 加了 condition 之后compose 会等 superset-db 的 healthcheck 通过再启动 superset。但 healthcheck 只是端口存活检测postgres 刚启动但还没完成初始化时 pg_isready 会失败重试 5 次、间隔 10 秒的设计就是为了覆盖这个窗口。redis 没有健康检查是因为它启动快且失败影响小所以条件只设为 service_started。第一次执行完整启动命令docker compose up -d之后查看状态docker compose ps注意如果宿主机 8088 已被其他服务占用superset 会起不来端口映射改成18088:8088即可。端口冲突看起来小团队共用服务器时很常见先ss -lntp | grep 8088确认再改映射能少走一段弯路。4. 初始化 Superset数据库迁移与管理员创建4.1 先执行 db upgrade别急着开浏览器容器起来后直接访问 8088最常见的画面是 500 报错或提示数据库表不存在。原因是 Superset 的元数据库仍然是空的还没有任何业务表。容器启动只把进程拉起来初始化工作要手动触发。离线环境下这一步没有额外下载成本迁移脚本都封装在镜像内部直接执行docker compose exec superset superset db upgradedb upgrade 的本质是把内置迁移脚本逐个应用。执行过程会打印大量日志结尾出现 OK 才代表迁移完成。整个流程通常几十秒如果卡住不动先怀疑是不是 postgres 连接出问题回到 superset_config.py 检查 SQLALCHEMY_DATABASE_URI。迁移完成后可以验证表结构docker compose exec superset-db psql -U superset -c \dt | wc -l注意psql 在 postgres 容器里执行看到的行数包含标题行。核心表应该包括 ab_user、ab_permission、ab_role、tables、dashboards 这些。如果表数量明显偏少几乎可以断定连错了数据库常见错误是连到默认 postgres 库而不是 compose 里指定的 superset 库。4.2 用环境变量或命令创建管理员Superset 官方脚本支持通过环境变量自动创建管理员compose 里配置的 SUPERSET_ADMIN_USERNAME 和 SUPERSET_ADMIN_PASSWORD 就是给这个机制用的。不过自动创建依赖入口脚本的版本行为不同 tag 对这套变量的实现不完全一致有的版本只在数据库为空时生效有的版本会重复执行导致冲突。建议不要把命运交给黑匣子手动创建更可控docker compose exec superset superset fab create-admin \ --username admin \ --password admin123 \ --firstname Admin \ --lastname User \ --email adminexample.local参数说明--username 是登录账号--password 是登录密码生产环境务必换成强密码--email 会用在找回密码和邮件通知里。这条命令由 Flask-AppBuilder 框架提供执行成功后会输出 Admin User admin created 之类的提示。创建完管理员后还有一步经常被漏掉docker compose exec superset superset initinit 负责初始化角色、权限点和菜单。漏掉它的问题不会立刻爆发一般出现在登录之后菜单缺项、SQL Lab 报权限不足、无法新建数据源。如果你在 compose 环境变量里已经配置了管理员账号容器首次启动可能已经自动建过手动 create-admin 会提示用户存在不影响后续流程直接执行 init 即可。4.3 首次登录与基础验证浏览器访问http://内网IP:8088/login用 admin 登录。登录后首先要去的不是建图表而是打开 Settings 确认账号信息和语言设置。4.1.1 默认可能带一个示例数据库离线环境下没有初始化示例数据时这个列表为空属于正常现象不要以为部署失败。第一次验证建议先连一个真实业务库。PostgreSQL 可以直接用因为官方镜像内置 psycopg2MySQL 如果报找不到 pymysql说明镜像里没有对应驱动这正是第五章要讲的插件问题。先不追求复杂图表SQL Lab 里跑一条 select 1能出结果说明元数据库、缓存、数据库驱动三层链路都通了。这个阶段完成后有一件很重要的事马上给 postgres 打一个初始快照docker compose exec superset-db pg_dump -U superset superset init_backup.sql这个快照是整个离线部署的基准点。后边调配置、装插件、改权限一旦改出问题把数据清空后恢复这份备份就能回到刚初始化完成的状态。离线环境里没有后悔药手动备份就是唯一的后悔药。5. 离线部署常见问题排查五个实际翻车点5.1 docker load 后镜像 TAG 变成none现象内网 load 完docker images 看不到 apache/superset:4.1.1只有一堆 REPOSITORY 为none的镜像。原因导出时用了 IMAGE ID 而不是完整 tag或者 docker save 前手工改过 tagtar 里记录的名称和期望不一致。解决在联网机器上先用docker tag把镜像名固定成标准格式再 saveload 后如果已出现none用docker tag IMAGE_ID apache/superset:4.1.1重新打 tag。检查镜像 IMAGE ID 是否和源一致这个对比最可靠不要只看 REPOSITORY 列。5.2 postgres 起来了但 Superset 一直连不上现象superset 容器日志反复出现psycopg2.OperationalError或Connection refused superset-db。原因常见是 postgres 还没初始化好或 SQLALCHEMY_DATABASE_URI 的密码、库名不一致甚至是 compose 网络被重建导致主机名解析失败。解决先docker compose logs superset-db | tail -20看 postgres 是否接受连接再用docker compose exec superset python -c import socket; socket.create_connection((superset-db, 5432))验证容器间连通性。确认 URI 中的用户、密码、库名与 compose 里 POSTGRES_USER、POSTGRES_PASSWORD、POSTGRES_DB 完全一致。我踩过一次compose 里改了 postgres 密码但 superset_config.py 里连接串还是旧密码服务名和网络都对唯独密码不一致排查了快一小时才定位。5.3 8088 端口能通但页面白屏现象curl 返回 200但浏览器打开白屏或控制台报静态资源 404。原因前端静态资源路径在 4.1.1 里是 /static/assets如果宿主机 8088 被反向代理接管或者浏览器缓存了旧的 index.html就会出现资源加载不全。解决先用无痕模式访问排除缓存再用docker compose logs superset看有没有 asset 相关报错。如果走了 Nginx 反向代理Nginx 要把 /static、/health 等路径都转发到 superset 容器不能只把 / 转发过去。离线部署一般直接暴露 8088 给内网使用白屏的多数场景其实是浏览器缓存或代理配置而不是 Superset 本身。5.4 配置文件挂载了但没生效现象在 superset_config.py 里改了 BABEL_DEFAULT_LOCALE 或 SECRET_KEY重启后界面语言没变化日志里看不到任何配置加载痕迹。原因挂载文件权限不对superset 进程读不到或者挂载路径写错默认镜像是 /app/pythonpath/superset_config.py如果挂到 /app/superset_config.py 就完全不生效。解决先在宿主机上用ls -l superset_config.py确认文件权限再进入容器验证docker compose exec superset python -c \ from superset_config import BABEL_DEFAULT_LOCALE; print(BABEL_DEFAULT_LOCALE)这条命令会直接打印配置读取结果。如果报 ImportError说明容器内读的根本不是宿主机挂载的文件检查 volume 路径。配置生效问题是黑匣子高发区用这一行命令验证比重启十次容器都管用。5.5 新建数据库连接时提示缺少驱动插件现象在 Data Databases 里填 PyMySQL 连接串时测试连接报ModuleNotFoundError: No module named pymysql。原因官方镜像只打包了基础驱动PyMySQL、pyodbc、clickhouse-driver 都属于额外插件离线没装就没有。解决不要进容器现场 pip install那样重启即丢。回到第二章把 wheels 目录准备好Dockerfile 里装好插件重新构建镜像内网 load 后替换 superset 镜像 tag再重新 compose up。如果已经用旧镜像起了容器可以临时进容器装一次保持业务继续随后立刻安排镜像重新构建否则下一次 recreate 就会打回原形。6. 汉化与维护收尾中文界面与交付前检查6.1 检查中文翻译并切换到完整中文界面config 里设置 BABEL_DEFAULT_LOCALE zh 只是第一步真正的中文界面依赖翻译文件。先检查容器内是否存在docker compose exec superset ls /app/superset/translations/zh/LC_MESSAGES/正常情况下能看到 messages.mo 文件。如果目录为空界面语言会部分回退到英文。离线环境下有两个解决方向一是确认镜像 tag 是否来自官方完整版部分第三方精简镜像会删掉 translations 目录二是从内部源码库拿到翻译文件编译后挂载进容器。官方镜像 apache/superset:4.1.1 内置 zh 翻译只要 tag 没选错上面 ls 就能看到文件。如果个别菜单仍是英文到 Settings 里确认当前语言确实是 zh再强制刷新浏览器。4.1.1 的中文翻译覆盖率一般在八成以上剩下的通常是用户自定义菜单或第三方插件属于正常现象。6.2 交付前的三点检查习惯每次离线交付我最后会强制做三件事docker compose config校验编排语法、md5sum 校验传输文件、pg_dump 备份初始化数据。这套动作已经成了固定习惯从那以后省掉了很多半夜被叫起来处理的返工。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑