简介:对于需要在无互联网环境快速落地数据可视化平台的企业运维与数据分析人员,Superset 4.1.1中文版Docker离线部署包提供了完整解决方案。压缩包共6个文件,约524.2MB,内含3个Docker镜像tar包(Redis、PostgreSQL及Superset中文版),以及分别用于服务编排、环境变量注入、数据库连接与安全配置的YAML、ENV与Python配置文件,可支撑离线环境下的一次性容器编排。已有364人学习下载,适合想借助Docker实现可移植、可重复部署Superset的团队。借助该包,用户无需从公网拉取镜像即可完成容器启动,中文界面显著降低非英文用户的使用门槛;同时,部署前核对这些配置项、定期关注Superset和容器安全更新,可确保长期稳定运行。
1. Superset 4.1.1 离线部署:为什么你必须先搞定镜像方案
Apache Superset 作为目前使用率最高的开源 BI 工具,4.1.1 版本在图表渲染性能、缓存策略和数据源连接器上都做了不少优化。但你真正要面对的问题通常不是 Superset 本身,而是「怎么在内网环境里把 Docker 镜像弄进去」。很多团队在离线部署 Superset 4.1.1 时翻车,翻的不是 Superset 的配置文件,而是 Docker 镜像下载慢、镜像依赖层级不清晰、宿主机架构不匹配这类「看似无关」的环节。
这篇笔记面向的是需要在内网、生产环境或安全隔离区里把 Superset 4.1.1 跑起来的运维和开发。整体思路是:先用一台能联网的机器把镜像准备好,再打包传输到离线宿主机,最后通过 docker-compose 把服务拉起来。整个过程我踩过不少坑,特别是 4.1.1 版本相比旧版在初始化数据库和静态资源处理上有变化,如果不注意,启动后大概率会卡在「Superset 一直 500」或者「登录页样式全丢」这两个问题上。
2. 离线部署前的镜像准备:从 Docker Hub 拉取到 tar 打包
2.1 先用 docker pull 锁定 Superset 4.1.1 的镜像版本
在联网机器上,我一般建议不要直接拉apache/superset:latest,而是指定4.1.1这个明确版本。Superset 官方镜像的更新节奏较快,latest 标签可能在某个时间点变成了 4.1.2 或者 4.2.0,这样你离线环境里跑的和你测试环境里跑的就不是同一个东西。
在联网机器上执行以下命令:
docker pull apache/superset:4.1.1拉取完成后,用docker images确认镜像已经存在于本地。这里需要记住镜像的 IMAGE ID,因为后面打包时用 IMAGE ID 比用repository:tag更保险,不会因为标签覆盖导致导出错版本。
2.2 导出镜像并检查依赖:为什么不能只看一个镜像文件
Superset 4.1.1 的官方镜像基于python:3.11-slim构建,但如果你只执行docker save apache/superset:4.1.1,导出的 tar 包里通常只包含 Superset 这一个层。这样看起来没什么问题,但当你把它导入到离线主机后,如果宿主机本地没有python:3.11-slim的底层层,Docker 会在运行时尝试从网络拉取缺失的层——而这在离线环境里直接失败。
我建议的做法是先把镜像跑起来,然后查看它的实际依赖:
docker run --rm -d --name superset_check apache/superset:4.1.1 sleep 300 docker inspect superset_check --format='{{.Image}}' docker history apache/superset:4.1.1 --no-truncdocker history能看到每一层的构建记录,但你要关注的不是构建内容,而是运行依赖。更稳妥的方式是直接用docker image inspect查看 RootFS 的层数,然后把所有底层镜像也一起保存。
一个实际的打包命令组合:
docker save apache/superset:4.1.1 python:3.11-slim -o superset_offline.tar注意这里把python:3.11-slim也一起打包了。如果你不能确定 Superset 4.1.1 是基于哪个 Python 版本构建的,可以先执行docker inspect apache/superset:4.1.1 | grep -i python看环境变量里的PYTHON_VERSION。
2.3 内网传输与导入:用 md5 校验文件完整性
离线环境里通过 U 盘或者内网 FTP 传输 tar 包,最怕的是文件传输了一半,而你毫不知情。我遇到过一次导入后启动报错,排查了半天发现是 tar 包损坏,重新传输才解决。
导入前做一次 md5 校验:
md5sum superset_offline.tar在联网机器上打包完成后记录这个 md5 值,传输到离线主机后再次计算,两值一致再执行导入:
docker load -i superset_offline.tar加载成功后会输出Loaded image: apache/superset:4.1.1和Loaded image: python:3.11-slim两行信息,确认都出现后再继续。如果只出现了一行,说明底层镜像没打进去,需要回到联网机器重新执行docker save。
3. 用 docker-compose 跑通 Superset 4.1.1 中文版:配置文件与初始化流程拆解
3.1 先解决中文问题:4.1.1 的语言配置方式和历史坑
4.1.1 版本在语言设置上与旧版有差异。旧版本可以直接通过环境变量LANG=zh_CN.UTF-8或者修改 config.py 里的BABEL_DEFAULT_LOCALE来切换界面语言,但 4.1.1 版本需要同时确保系统有中文字体和中文本地化翻译文件。
在离线环境里最容易翻车的是缺字体。Superset 生成的图表如果包含中文,而镜像里没有中文字体,图表里的中文会显示成方块。解决方式有两种,一种是在构建自定义镜像时把中文字体打进去,另一种是用 docker-compose 挂载宿主机的字体目录。
推荐在docker-compose.yml中这样配置:
services: superset: image: apache/superset:4.1.1 container_name: superset environment: - LANG=zh_CN.UTF-8 - LC_ALL=zh_CN.UTF-8 - SUPERSET_LANGUAGES={"zh":{"flag":"cn","name":"Chinese"}} ports: - "8088:8088" volumes: - ./superset_home:/app/superset_home - /usr/share/fonts:/usr/share/fonts:ro这里的SUPERSET_LANGUAGES是 4.x 版本开始支持的语言配置方式,指定了中文语言包。/usr/share/fonts的挂载是让容器直接使用宿主机字体,这样图表中文不会乱码。
3.2 数据库初始化和管理员账号创建:一条命令搞定还是分三步走
Superset 的数据库初始化在 4.1.1 里有两种做法。如果你使用默认的 SQLite,可以执行:
docker exec -it superset superset db upgrade docker exec -it superset superset initsuperset db upgrade负责建表,superset init负责初始化角色和权限。容易忽略的是,superset init执行完后还需要手动创建管理员账号:
docker exec -it superset fab create-admin \ --username admin \ --firstname admin \ --lastname admin \ --email admin@example.com \ --password admin注意这里用的是fab create-admin,不是旧版的superset create-admin。4.1.1 版本切换到了 Flask-AppBuilder 的命令行入口,之前用旧命令会提示 command not found。
如果你的环境要求使用 MySQL 或 PostgreSQL 作为后端数据库,需要在docker-compose.yml里加一个数据库服务,并在 Superset 的环境变量中指定数据库连接串:
environment: - SUPERSET__SQLALCHEMY_DATABASE_URI=mysql://superset:superset@db:3306/superset其中SUPERSET__SQLALCHEMY_DATABASE_URI这个环境变量是 Superset 从 1.4 版本开始支持的配置覆盖机制,双下划线表示配置文件里的层级关系。如果你直接从官方文档复制连接串,注意 MySQL 驱动要写mysql://而不是mysql+pymysql://,因为 4.1.1 默认已经内置了 PyMySQL,不需要额外指定驱动。
3.3 通过 SECRET_KEY 避免登录状态失效的玄学问题
很多离线部署跑起来之后发现一重启容器,所有用户的登录状态全部失效,重新登录后过几分钟又失效。这个问题根源是SECRET_KEY在生产模式下没有稳定设置。
在docker-compose.yml的 environment 中必须增加:
- SUPERSET_SECRET_KEY=your_random_secret_string_here这个SECRET_KEY是用来给 Flask 签名 session cookie 的,如果没有显式指定,Superset 会每次启动时随机生成一个,重启后所有 session 自动失效。生成一个随机字符串的方法:
openssl rand -base64 32把输出结果填到上面环境变量里即可。这个值一旦在用户使用期间改变,也会把所有用户踢下线,所以不要随便更换,最好写入部署文档里让运维团队知晓。
3.4 执行顺序:离线环境首次启动的全流程命令
把上面步骤串起来,在离线宿主机的docker-compose.yml所在目录执行:
docker-compose up -d docker-compose ps等容器状态变为 running 后(第一次可能要等 1-2 分钟,因为 Superset 要加载静态资源和初始化配置),进入容器执行:
docker exec -it superset superset db upgrade docker exec -it superset fab create-admin --username admin --firstname admin --lastname admin --email admin@example.com --password admin docker exec -it superset superset init docker-compose restart superset执行完superset init后重启容器的原因是要让语言配置和权限配置彻底生效。如果你不重启,大概率会出现登录后菜单还是英文、部分功能权限异常的情况。
4. Superset 4.1.1 离线部署避坑:常见问题与排查手段
4.1 容器反复重启或直接退出:先看日志里的数据库连接串
现象:执行docker-compose up -d后,docker ps看到 superset 容器几秒钟就退出,或者一直处于 restarting 状态。手动执行docker logs superset看到类似ModuleNotFoundError: No module named 'MySQLdb'或者sqlalchemy.exc.OperationalError。
原因分析:绝大多数情况是SUPERSET__SQLALCHEMY_DATABASE_URI环境变量配置了 MySQL 连接串,但容器内缺少相应的数据库驱动;或者连接串里的 host 指向了不存在的服务。4.1.1 镜像内置了 PyMySQL,但不包含 PostgreSQL 的 psycopg2 完整版,也没包含 SQL Server 的驱动。如果你要接的是 PostgreSQL,需要在环境变量里把它切换到postgresql+psycopg2://,并且用docker exec进入容器手动安装pip install psycopg2-binary,或者干脆在离线环境里提前准备一个自定义镜像。
解决路径:
docker logs superset 2>&1 | grep -i error先看具体的报错信息,确认是驱动缺失还是连接失败。如果是驱动缺失,最省事的办法是在联网机器上基于apache/superset:4.1.1做一个新镜像,在 Dockerfile 里加上RUN pip install psycopg2-binary,然后推送到内网。如果是连接失败,检查数据库服务是否先于 superset 容器启动,或者在 compose 文件里加depends_on并设置healthcheck。
4.2 登录页能打开但样式全部丢失:静态资源加载失败
现象:浏览器访问http://ip:8088能弹出登录框,但页面没有任何 CSS 样式,只剩纯文本和按钮叠在一起。按 F12 打开开发者工具,能看到大量静态资源请求报 404。
原因分析:Superset 的静态资源默认由 Nginx 或者 Flask 直接服务,在 4.1.1 中,如果之前执行过superset init没有完全成功,static/assets目录下的文件可能没有被正确拷贝到指定位置。另一种常见情况是离线环境下没有执行superset db upgrade,导致系统数据库里缺少存储静态资源配置的表。
解决路径:先执行一次完整的初始化流程。如果问题还在,进入容器查看静态资源目录:
docker exec -it superset bash ls -la /app/superset/static/assets/如果目录不存在或者内容为空,在容器内手动执行:
superset static这个命令会重建静态资源目录。执行完后再重启容器。注意,如果你用的是自定义的 Nginx 反向代理,还需要确认 Nginx 配置里的location /static/指向正确,别把 Superset 自己的静态请求代理到别的服务上。
4.3 图表中文乱码:字体缓存和系统语言都没生效
现象:仪表盘标题、图例、坐标轴的中文显示正常,但图表内部的中文文字全部变成方框或者乱码。
原因分析:Superset 4.1.1 用dominate和d3渲染图表,浏览器端的中文字体来自操作系统或者容器内的 fontconfig 配置。虽然宿主机挂载了字体目录,但如果容器内的 fontconfig 缓存没有更新,即使有字体文件,渲染引擎也识别不到。
解决路径:进入容器并重建字体缓存:
docker exec -it superset bash apt-get update && apt-get install -y fontconfig fc-cache -f -v如果你的离线环境没有 apt 源,这个方案行不通。我一般会在网联机器上做一个自定义镜像,Dockerfile 里加上:
RUN apt-get update && apt-get install -y fonts-wqy-zenhei fonts-wqy-microhei然后把fc-cache也放进构建过程。这样保证进入容器后中文字体一定可用。
4.4 导入 tar 包时报磁盘空间不足:镜像层解压会占用双倍空间
现象:在离线主机上执行docker load -i superset_offline.tar时,进度条走到一半,报no space left on device,但用df -h看磁盘明明还有几十 GB。
原因分析:docker load在解压镜像时会将全部镜像层先写入磁盘临时目录,再写入 Docker 的数据目录。如果 Docker 数据目录所在分区空间不足,或者/var/lib/docker所在分区和临时目录所在分区空间都很紧张,就会触发这个报错。常见的情况是 Docker 数据目录默认在根分区,而根分区往往只有 20-30 GB。
解决路径:先看当前空间:
df -h /var/lib/docker df -h /tmp如果/tmp空间够,可以把 Docker 的临时目录指过去。更直接的做法是把 Docker 数据目录迁移到大分区,但迁移本身比较耗时。我之前在一个 40 GB 根分区的机器上连续踩两次这个坑,最后把/var/lib/docker挂载到了单独的数据盘才彻底解决。如果临时迁移不方便,可以直接把/var/lib/docker软链到有空间的位置,但这仅限应急,不建议长期使用。
4.5 容器内时间与宿主机不一致:影响定时任务和图表刷新
现象:Superset 的定时报表任务执行时间和预期不符,图表缓存刷新也比设定时间晚了几个小时。
原因分析:容器默认使用 UTC 时区,而宿主机可能已经设置了Asia/Shanghai,容器内date命令看到的还是 UTC 时间。Superset 的定时任务(schedule)在计算执行时间时依据的是容器内的系统时间。
解决路径:在 docker-compose 的环境变量中加入:
environment: - TZ=Asia/Shanghai同时把宿主机的/etc/localtime挂载进容器:
volumes: - /etc/localtime:/etc/localtime:ro这样容器内外时间一致。需要注意的是,如果你已经用 Superset 创建了定时任务,改完时区后最好手工重启一次容器,否则已经加载到内存里的调度器可能还是用旧时区计算。
5. 离线部署后的数据源连接:验证从「跑起来」到「可用」
5.1 通过预配置数据源减少上手成本
部署完成后有一个细节值得做:提前在 Superset 的配置里声明目标数据库连接。虽然通过页面操作也能添加数据库,但在离线环境里,操作人员可能不是原来的实施工程师,连接参数和特殊配置容易填错。
修改superset_config.py或者通过环境变量注入SQLALCHEMY_CUSTOM_PASSWORD_STORE和SQLALCHEMY_DATABASE_URI。最常见的做法是在docker-compose.yml里增加:
environment: - SUPERSET__SQLALCHEMY_DATABASE_URI=mysql://superset:superset@db:3306/superset这里只解决了 Superset 自己用的数据库,你还需要在界面上配置业务数据源。如果有多个业务库,建议在一开始就通过 REST API 或者 Python 脚本批量创建数据库记录,避免后续手工录入的麻烦。
5.2 验证部署成功:三个关键检查点
第一个检查点是登录:浏览器访问http://ip:8088,能出现登录页并且样式完整,说明静态资源没问题。第二个检查点是数据源连通性:在 Superset 的 Data 菜单里选择 Databases,点击目标数据库右侧的 Test Connection,能返回 Success 就说明网络和驱动都正常。第三个检查点是图表创建链路:新建一个 Chart,选择数据集,拖拽维度生成一个简单图表,并确认中文显示正常。
下面是我比较常用的一组最小验证命令:
# 检查容器是否持续运行 docker ps --filter name=superset --format "{{.Status}}" # 查看 Superset 是否完成数据库初始化 docker exec -it superset superset db check # 确认 Superset 内部运行时健康 docker exec -it superset superset healthsuperset health是 4.x 新增的命令,直接返回服务状态,不用再额外 curl 接口。
5.3 日志持久化:离线环境里排障的后悔药
很多人部署成功后就把容器晾在那里,直到某天图表不出数据才想起来查日志,但容器已经重启过,日志早就丢了。我在离线部署的经验是,从第一天开始就把日志挂载到宿主机目录。
在docker-compose.yml里增加:
logging: driver: json-file options: max-size: "50m" max-file: "5"同时把 Superset 的应用日志目录挂出来:
volumes: - ./superset_logs:/app/logs在容器里 Superset 的日志默认输出到控制台,但某些子进程的日志写到了/app/logs目录,如果不挂载,重启后全丢。挂载之后,即使容器崩了,也可以到superset_logs目录下翻日志分析原因。
5.4 关于升级路径的一个提醒
离线部署最怕的是版本升级。如果后续要从 4.1.1 升级到 4.1.2 或者 4.2.x,一定要先备份 Superset 的后端数据库(尤其是slices、dashboards、databases这几张表),然后拉取新镜像测试,不能直接在生产上执行superset db upgrade。我见过升级后仪表盘图标全部错位的案例,原因是前端静态资源缓存没清。升级完成后让用户强制刷新浏览器并清理缓存,能规避大部分类似问题。
6. 生产环境下的三个额外配置:让你的 Superset 离线部署更靠谱
6.1 配置反向代理:不要直接把 Superset 的端口暴露给所有内网机器
在实际的内网环境里,我通常不建议直接访问ip:8088。通过 Nginx 加一层反向代理,一方面是为了统一入口,另一方面也方便后续加访问控制。一个最常见的配置是:
server { listen 80; server_name superset.example.local; location / { proxy_pass http://127.0.0.1:8088; proxy_set_header Host $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 $scheme; } }注意 Superset 是 Flask 应用,如果你在 Nginx 层开启了 HTTPS,需要同时设置X-Forwarded-Proto,否则 Superset 生成的一些内部链接会变成 http 协议,导致页面跳转异常。
6.2 关闭 Superset 的定时报表或显式配置时间
对于大多数内网环境,Superset 自带的定时报表功能依赖 Celery Beat,默认并没有启动。如果你用不上这个功能,就不要启动。启动的方式是在docker-compose.yml里新增一个 worker 服务,需要指定SUPERSET__CELERY_BROKER_URL和SUPERSET__CELERY_RESULT_BACKEND为 Redis 连接串。
如果事先没有准备 Redis,不建议在生产环境上临时把 Celery 跑起来,因为它会引入额外的调度依赖。我在一个项目里吃过这个亏:以为加了一个 worker 服务就能按月发报表,结果 Redis 配置错误,整个 superset 服务也被带崩了。
6.3 定期备份方案:离线环境比在线环境更容易丢数据
在线环境有各种云备份服务,离线环境往往只依赖机器上的一块磁盘。Superset 里的核心数据是dashboards、slices和相关表。备份的最简方式是直接备份 SQLite 文件或者 MySQL 的库:
docker exec superset superset export-dashboards -f /app/superset_home/dashboards_export.zipexport-dashboards会把当前所有仪表盘导出为一个 zip 包,放到挂载目录后拷贝到宿主机即可。数据库本身可以用sqlite3 .backup或者mysqldump备份。我在多个项目里坚持一个习惯:每次修改配置或者升级前,先导出一份仪表盘备份,再动数据库。这个习惯让我避免过两次彻底返工。
如果你做的是生产级的离线部署,建议把备份脚本写到 cron 里,每天把导出文件和数据库备份文件存到单独的数据盘。别看操作简单,真到要恢复的时候你就知道这步有多值钱了。希望上面这些从镜像打包到日志排查的踩坑经验能帮到你,让你的 Superset 离线部署少走弯路。
本文还有配套的精品资源,点击获取