Superset 4.1.1中文版Docker离线部署:内网BI可视化的最佳实践
简介面向需要在无外网或内网隔离环境中部署数据可视化平台的企业与开发者这份 Superset 4.1.1 中文版 Docker 离线部署资源包提供了从镜像到编排配置的一整套可直接使用的部署文件解决离线条件下拉取不到镜像、配置复杂等难题。压缩包共 6 个文件包括 3 个镜像压缩包含 Redis、PostgreSQL 与中文版应用镜像、1 个容器编排脚本、1 个应用配置文件和 1 个环境变量文件整体大小约 524.2MB。镜像压缩包用于本地导入容器镜像编排脚本定义服务依赖配置文件管理安全与连接参数环境变量文件设置端口等运行环境用户按序使用即可在局域网内完成部署。资源涵盖了数据库连接、端口映射、应用配置参数、容器启动顺序等关键环节尤其适合有一定容器基础、希望快速落地中文版数据看板的中高级运维或数据工程师。已有 364 人学习下载。1. Superset 4.1.1 中文版 Docker 离线部署内网环境里的 BI 落地方式内网环境想搭一套 BI 可视化平台最拖进度的往往不是功能配置而是安装环节的依赖地狱。Superset 4.1.1 中文版 Docker 离线部署就是把 Apache Superset 这个开源 BI 平台连同 Python 运行时、前端构建产物和中文翻译资源一起封装进 Docker 镜像在能联网的机器上导出再导入到没有外网的生产或内网环境启动。它解决的核心问题是机器不联网也能源源不断提供数据看板、SQL 查询和图表制作能力。适合等保合规要求不能直连外网的团队也适合要给客户做私有化交付的实施工程师。下面按选型、打包、启动、避坑四步走完整个交付链路。2. 部署方案对比为什么离线场景把 Docker 镜像作为首选2.1 pip 安装的离线困境依赖树太长C 扩展难匹配最先被想到的常见做法是在联网机器上用 pip download 把依赖包全部拉下来再拷贝进内网 pip install --no-index --find-links 安装。Superset 4.x 的依赖树非常庞大顶层依赖就有几十个包每个包背后还有传递依赖手动收集齐全基本不可能靠肉眼检查。真正翻车的点在 C 扩展。pandas、cryptography、sqlalchemy 这些包在 PyPI 上提供的是 manylinux 平台 wheel但不同 Linux 发行版的 glibc 版本和 Python 小版本直接影响 wheel 能否加载。最常见的现象是同一份 wheel 包在 CentOS 7 上能装在 Ubuntu 22.04 上安装时直接报非法指令或段错误。没有编译工具链的话源码编译又会卡在缺少 libssl-dev、libffi-dev 这类系统库上离线的系统库补齐又是一轮新的依赖地狱。即使安装成功后续维护也是问题。Superset 升级某个传递依赖时pip 会重新解析整棵依赖树可能把环境里另一个项目的依赖顶掉。对于交付场景这不是一次性的安装成本是持续的环境管理成本。2.2 Docker 镜像在离线环境的真正优势Docker 镜像从根本上绕开了上面两层问题。镜像内部已经把操作系统用户态、Python 解释器、全部 pip 依赖、前端编译产物打包成完整运行时。镜像里某个 C 扩展针对哪个 glibc 编译的、依赖哪个系统库都是镜像构建时确定好的目标机器完全不感知。交付物也简单就是一个 tar 文件。对方不需要理解 Python 虚拟环境不需要准备 wheelhouse只需要机器上有 Docker 引擎。导入后 docker run 即可。目标机器上即使跑着其它 Python 应用也互不干扰——依赖隔离由容器边界完成而不是靠 virtualenv 的路径约定。离线运维同样简单。镜像层是只读的容器内写入的数据都落在挂载卷里。升级时拉新镜像、换 tag、重建容器回滚时切回旧 tag整个过程可预期。这在给客户交付时尤其重要客户自己也能看懂这套操作不至于你离场后没人敢碰。路线离线安装难度交付规范性运行隔离日常维护成本pip download高依赖树和C扩展难控制低每台机器环境不同无高Docker 镜像低tar 导入即用高产物标准有低二进制 bundle中仍需匹配系统库中无中2.3 镜像里的进程结构与配置入口理解容器里跑着什么排障才不慌。Superset 官方镜像的启动入口是一个 shell 脚本负责初始化目录权限、执行初始化检查最终拉起 gunicorn 作为 WSGI 服务器监听 8088 端口。前端页面是构建好的 React 静态资源由同一个 Flask 应用直接 serve不需要单独跑 Nginx。容器内元数据库默认是 SQLite文件存放在 /app/superset_home 下。如果连接外部 MySQL 或 PostgreSQL则需要在配置里改 SQLALCHEMY_DATABASE_URI。配置文件的注入点是挂载一个 superset_config.py 到容器内 /app/pythonpath/superset_config.py这个路径是镜像启动时自动加载的改配置不需要重新构建镜像挂载卷更新后重启容器即可生效。版本选型层面4.1.1 是目前稳定版本线中较新的大版本前端交互完整多语言框架成熟中文翻译资源在镜像内已经携带只需要在配置里显式开启语言选项不需要像老版本那样手动替换翻译文件。这一点对中文部署很重要后面第 4 章会展开讲实际配置。3. 离线部署前置准备从镜像导出到内网导入的完整链路3.1 联网机器上下载镜像先配置加速器再拉取离线包的第一步是在一台能够访问外网的 Linux 机器上拉取官方镜像。如果拉取速度很慢先在 /etc/docker/daemon.json 里配置镜像加速器再重启 Docker 服务。这一步值得优先做否则几个 GB 的镜像可能挂在半路。{ registry-mirrors: [ https://docker.m.daocloud.io, https://dockerproxy.com ] }sudo systemctl restart docker docker pull apache/superset:4.1.1daemon.json 是 Docker 守护进程的全局配置修改后必须重启 daemon 才会生效。这里有一个容易忽略的坑JSON 格式写错多了逗号、引号不匹配Docker 服务会直接起不来。重启后立刻执行 docker info 检查能看到 Registry Mirrors 列表是否生效再执行 pull。实际拉取时如果镜像分层较多建议保留终端输出确认每一层都下载完成再离开。3.2 导出与导入Docker 与 containerd 两种传输姿势镜像拉取完成后先重新打一个明确的 tag再导出为 tar 文件。之所以先打 tag是为了防止导入端镜像名混乱这一步在后文避坑章节会再次提到。docker tag apache/superset:4.1.1 superset-offline:4.1.1 docker save -o superset-4.1.1.tar superset-offline:4.1.1 ls -lh superset-4.1.1.tardocker save 导出的是完整的镜像层数据包含所有历史层所以 tar 文件体积通常比镜像仓库里显示的大小更大这正常。把 tar 文件通过 U 盘或内网传输工具拷到目标机器后执行导入。docker load -i superset-4.1.1.tar docker imagesdocker load 会把镜像层导入本地镜像仓库导入完成后 docker images 应该能看到 superset-offline:4.1.1。如果目标机器是 Kubernetes 节点容器运行时是 containerd 而不是 Docker则导入命令不同ctr -n k8s.io images import superset-4.1.1.tarctr 是 containerd 的原生客户端-n 指定命名空间K8s 节点通常使用 k8s.io 命名空间导入后 kubelet 才能拉取到该镜像。这里很容易踩坑在 containerd 环境下用 docker load 操作会提示找不到 Docker socket因为该节点根本没有 Docker daemon。3.3 离线部署文件清单与校验交付时建议把下面这些文件整理成一个目录一并移交。如果直接给客户文件清单能让对方清楚每一份文件的用途避免现场手忙脚乱。文件用途说明superset-4.1.1.tar镜像本体docker load 或 ctr images import 导入docker-compose.yml容器编排定义端口、卷、环境变量superset_config.py中文与数据源配置挂载到容器 /app/pythonpath中文字体文件导出图表字体挂载到容器字体目录内网传输文件后先做一次校验再导入。镜像 tar 几个 GB 大小U 盘拷贝或网络传输都可能出现损坏损坏的 tar 导入时 docker load 不会报错但启动容器时会出现镜像层校验失败。校验方式很简单md5sum superset-4.1.1.tar在联网机器上记录 md5 值目标机器上重新计算并对比。数字一致再继续不一致就重新传输。这一步看着多余实际交付中能省下大量远程排障时间属于典型的低成本高收益动作。4. 容器启动与中文界面compose 配置和初始化细节4.1 中文界面如何开启不是魔改镜像是配置问题很多人在内网部署 Superset 后发现界面是英文就以为是镜像版本不对到处找“中文专用镜像”。实际上 Superset 官方镜像本身包含多语言翻译资源中文支持是通过 Babel 机制实现的翻译文件位于镜像内 /app/superset/translations/zh/LC_MESSAGES/ 目录运行时会根据请求中的 Accept-Language 头或用户在界面里的语言偏好动态输出中文文案。所谓“中文版”在 4.1.1 这个版本上的正确做法是挂载一份 superset_config.py 配置把 LANGUAGES 变量显式声明为包含中文然后通过浏览器或用户设置切换语言。不需要重新构建镜像也不需要替换翻译文件。config 文件最小可用版如下# 固定密钥避免容器重启导致 session 失效 SECRET_KEY YourFixedSecretKeyChangeMe123! # 开启中文与英文两种语言选项 LANGUAGES { zh: {flag: cn, name: Chinese}, en: {flag: us, name: English}, } # 查询返回行数上限防止看板加载过慢 ROW_LIMIT 5000SECRET_KEY 是 Flask 应用签名 session 和 CSRF token 的密钥如果留空Superset 每次启动会生成随机值导致重启后用户登录态失效。LANGUAGES 的键名在不同版本有细微差异4.1.x 以官方源码中 superset/config.py 的 LANGUAGES 定义为准挂载前可以在容器里查一下默认配置确认键名。ROW_LIMIT 影响 SQL Lab 和图表查询的默认返回行数内网数据量大时建议按实际调整。4.2 用 docker-compose 定义容器而不是裸 docker run单条 docker run 命令也能启动容器但参数一多后续改动很容易出错。我建议用 docker-compose 管理配置可版本化回滚也方便。services: superset: image: apache/superset:4.1.1 container_name: superset restart: always ports: - 8088:8088 environment: - TZAsia/Shanghai volumes: - ./superset_config.py:/app/pythonpath/superset_config.py - ./superset_home:/app/superset_home - ./fonts:/usr/share/fonts/chinese healthcheck: test: [CMD, curl, -f, http://localhost:8088/health] interval: 30s timeout: 10s retries: 3volumes 里三行分别对应配置文件、元数据库数据目录、中文字体目录。superset_home 目录是 SQLite 元数据库和上传资源的存放位置必须挂载到宿主机否则容器删除后数据全部丢失。fonts 目录提前放好一个中文字体 ttf 文件用于后续图表导出中文渲染。healthcheck 依赖容器内有 curl官方镜像自带不需要额外安装。启动命令docker compose up -d如果目标机器上安装的是旧版 docker-compose 独立命令则用docker-compose up -d。启动后先看日志确认 gunicorn 正常监听docker logs -f superset看到类似 “Listening at: http://0.0.0.0:8088” 的输出说明服务已经起来。这里有个判断点日志里如果出现 bind 到 127.0.0.1 的情况说明配置被覆盖外部无法访问需要检查配置文件中是否有 SERVER_HOST 相关设置。4.3 初始化顺序先建账号再升级数据库最后 init容器第一次启动后还需要做一次初始化。顺序有讲究先创建管理员账号再执行数据库升级最后执行 init。如果先跑 initinit 内部会尝试创建默认 admin 账号之后再执行 create-admin 会因为用户名已存在而失败。docker exec -it superset flask fab create-admin \ --username admin \ --firstname Admin \ --lastname User \ --email adminexample.com \ --password Admin123! \ --appbuilder docker exec -it superset superset db upgrade docker exec -it superset superset initcreate-admin 通过 Flask-AppBuilder 创建登录账号密码里建议包含大小写和特殊字符满足常见等保要求。db upgrade 会把元数据库迁移到当前版本 schema如果跳过后续 init 可能报错。init 执行初始化角色、权限、默认看板数据等日志中看到 “Admin user already present” 之类输出说明账号创建成功且未被覆盖。4.4 验证中文界面是否生效初始化完成后浏览器访问 http://内网IP:8088用创建的 admin 账号登录。登录后右上角用户菜单进入 Settings在 Language 下拉里选择 Chinese界面会立即切换为中文。如果下拉里只有 English说明 LANGUAGES 配置没有生效按下面命令检查挂载是否正确docker exec -it superset cat /app/pythonpath/superset_config.py docker exec -it superset bash -c ls /app/superset/translations/zh/LC_MESSAGES/第一条确认 config 文件内容确实在容器内且包含 LANGUAGES 配置第二条确认翻译文件存在。两个条件都满足但界面仍没有中文选项最常见的原因是浏览器请求头 Accept-Language 强制优先英文此时直接修改用户设置里的语言项即可不需要改动服务器配置。5. 避坑离线部署 Superset 常见的 5 个翻车现场5.1 现象docker load 之后镜像名变成一串 hash 或 none导入完成后 docker images 看不到预期的 apache/superset:4.1.1而是显示none:nonedocker compose up 直接报找不到镜像。原因docker save 导出的是镜像的 repository 和 tag 信息如果导出前没有统一打 tag或者导入端 Docker 版本较旧导致 tag 信息解析异常镜像会以悬空镜像的形式存在。解决不用重新传输直接根据镜像 ID 重新打 tagdocker images --no-trunc | grep none docker tag IMAGE_ID apache/superset:4.1.1 docker compose up -d这个坑的根治办法是在导出前就执行 docker tag 统一命名并在交付清单里写明目标机器需要导入的镜像名。第一次交付时没注意这一点现场多花了一个小时排查镜像 ID后来所有镜像导出前都先加 tag。5.2 现象宿主机能访问 8088局域网其它机器访问不通浏览器在服务器本机 curl localhost:8088 能返回页面但换成内网 IP 就超时或者完全无法访问。原因Docker 端口映射已生效但宿主机防火墙没有放行 8088或者在容器内 gunicorn 绑定地址不是 0.0.0.0。排查顺序是先看端口映射是否生效docker ps | grep superset curl -I http://localhost:8088/health映射没问题再看防火墙firewall-cmd --zonepublic --add-port8088/tcp --permanent firewall-cmd --reload如果目标机器是云主机还需要同步检查安全组规则。很多内网部署环境还有额外的网络策略比如只允许特定网段访问需要提前跟网络管理员确认。这一条看着基础实际上交付现场最常见的“连不上”问题就是防火墙和安全组遗漏。5.3 现象配置了中文但界面仍然英文切换语言刷新后失效登录后 Settings 语言下拉里能看到 Chinese选中后当前页面变中文但刷新后回到英文界面。原因浏览器请求头 Accept-Language 比用户设置优先级更高每次刷新页面时Superset 优先按浏览器语言偏好返回文案。解决在浏览器设置里把中文语言移到首选位置或者安装 Superset 后让用户统一固定浏览器语言。如果希望服务端强制走中文不考虑浏览器偏好可以在 superset_config.py 里通过 BABEL_DEFAULT_LOCALE 强制默认语言BABEL_DEFAULT_LOCALE zh这个配置的作用是设置默认翻译语言用户未主动选择语言时服务端默认返回中文。需要注意这不会完全禁止用户切换到英文但能保证绝大多数场景下打开页面就是中文适合统一交付给客户的情况。5.4 现象容器重启后用户全部掉线CSRF 校验失败docker compose restart 之后所有登录用户被踢出重新登录时提示 CSRF token invalid 或 session 过期。原因SECRET_KEY 没有固定。Superset 启动时如果环境变量和配置文件中都没有设置会生成随机密钥Flask 用它签名 session。容器重启后密钥变化旧的 session 签名全部失效。解决在 superset_config.py 或环境变量里固定 SECRET_KEY。如果已经在跑修改配置后重启容器docker compose down docker compose up -d这个坑隐蔽性很强因为不是每次重启都立刻暴露如果用户量少甚至可能没注意到。我第一次给客户交付时第二天客户反馈全员登录失效跑到现场才发现是密钥漂移问题。后来每次交付前都会确认 SECRET_KEY 已固定并在交接文档里写明这一项。5.5 现象docker 命令报 permission denied 或 Docker 服务启动失败执行 docker ps 报 permission denied while trying to connect to the docker api at unix:///var/run/docker.sock或者 systemctl start docker 报 Failed to start docker application container engine。原因当前用户不在 docker 用户组Docker daemon 的 socket 默认只允许 root 和 docker 组用户访问如果 daemon 起不来更常见的原因是 daemon.json 配置格式错误或磁盘空间不足。解决权限问题把用户加入 docker 组重新登录会话生效sudo usermod -aG docker $USER newgrp dockerdaemon 起不来的情况先看日志定位journalctl -u docker --no-pager | tail -50 df -h日志里如果指向 daemon.json 解析错误按第 3 章的方法重新检查 JSON 格式。磁盘满的话清理旧镜像和日志docker system prune 可以清理悬空资源但执行前确认没有正在使用的容器。6. 进阶自定义镜像补齐 MySQL 驱动与中文字体验证6.1 用继承方式构建带 MySQL 驱动的镜像官方镜像预装的数据库驱动以 PostgreSQL 和 SQLite 为主MySQL 支持在不同版本镜像中并不一致。生产环境多数用 MySQL 做元数据库或业务数据源需要补装驱动。常见做法是写一个自定义 Dockerfile继承官方镜像再离线安装驱动包。FROM apache/superset:4.1.1 COPY pymysql-1.1.1-py3-none-any.whl /tmp/ RUN pip install --no-index --find-links/tmp pymysqldocker build -t superset-4.1.1-mysql .联网环境把 pymysql 的 wheel 包下载好后一并传入内网。pip install 使用 --no-index 强制离线安装避免构建时访问外网导致失败。构建完成后使用这个新镜像替换原镜像配置文件里连接串写法SQLALCHEMY_DATABASE_URI mysqlpymysql://superset:passwordmysql-host:3306/superset6.2 中文字体挂载与首次验证图表导出成图片时中文经常显示成方块。这不是 Superset 的 bug而是容器内没有中文字体。在 compose 配置里已经挂载了 ./fonts 到 /usr/share/fonts/chinese把任意一个 ttf 中文字体放进去重启容器后刷新字体缓存docker exec -it superset fc-cache -f验证时登录系统进入 SQL Lab 执行 SELECT 1确认数据库连接正常再创建一个简单图表导出图片观察中文是否正常渲染。最后用 curl 检查健康接口确认交付状态curl -I http://内网IP:8088/health每次交付我都会先跑一遍这个验证流程再移交操作简单但能拦截大部分基础配置问题。希望帮到你。本文还有配套的精品资源点击获取