
简介这份资源面向需要在无外网环境下搭建数据可视化平台的企业运维与开发者提供 Superset 4.1.1 中文版的 Docker 离线部署方案解决内网环境无法拉取镜像、部署流程繁琐的问题。压缩包共 6 个文件约 524.2MB包含 3 个 tar 镜像文件Superset 中文版、PostgreSQL 14、Redis 7、1 个 docker-compose.yml 服务编排文件、1 个 superset_config.py 配置文件和 1 个 .env 环境变量文件覆盖镜像、编排与配置三类核心内容。目前已有 368 人学习。通过该资源读者可一次性获得离线镜像与配套编排配置直接导入本地后即可启动多容器服务省去逐一下载依赖的步骤同时可参考配置文件中的数据库连接、端口映射与安全认证等参数快速完成中文界面的初始化与调优适合具备基础 Docker 使用经验、希望在内网快速落地数据探索与可视化平台的读者。1. 从一台没外网的机器说起Superset 4.1.1 中文版离线部署到底难在哪上周帮一个朋友处理他实验室内网的一台数据可视化服务器机器是 CentOS 7.9网卡能通内网但出不了公网连 yum 源都是内网镜像。他之前照着网上教程docker pull apache/superset:4.1.1结果卡在拉取镜像那一步整整一下午终端里全是dial tcp: i/o timeout。这不是个例Superset 4.1.1 中文版 Docker 离线部署这件事坑基本都集中在「镜像怎么进去」「中文怎么生效」「元数据库怎么初始化」这三段。它适合两类人一类是内网、专网、隔离环境里必须把 BI 平台跑起来的运维另一类是本地想复现一套干净环境、不想被网络波动干扰的开发者。装不好会怎样最典型的就是容器起来了但登录页 500或者界面全是英文、中文包根本没加载。这篇就按我实际装的那一遍把版本、镜像、配置、验证和翻车点全列清楚。2. 环境先列清Superset 4.1.1 的版本组合与离线物料准备2.1 为什么版本组合比单个版本号更重要Superset 4.1.1 不是一个能单独拎出来装的二进制它是一套 Python 应用加前端静态资源跑在容器里时还依赖 PostgreSQL 或 MySQL 做元数据库、Redis 做缓存。离线部署最怕的就是「Superset 版本对了但 Python 基础镜像或数据库镜像版本不对」。我一般会先把组合固定死再去找对应的离线包而不是装到哪算哪。下面这套是我这次实际用到的组合Superset 4.1.1 官方镜像基于 Python 3.10元数据库用 PostgreSQL 14缓存用 Redis 7。这三个版本在离线环境里互相兼容没有出现驱动编译问题。组件版本作用离线物料形式Superset4.1.1BI 主应用docker save 导出的 tarPostgreSQL14.x元数据库docker save 导出的 tarRedis7.x缓存与 Celery brokerdocker save 导出的 tarDocker Engine20.10容器运行时内网 yum/apt 源或离线 rpmDocker Composev2.x编排单二进制文件提示Superset 4.x 已经不再推荐 SQLite 做生产元数据库离线环境里如果只用 SQLiteCelery 和并发查询会出各种玄学问题我建议直接上 PostgreSQL。2.2 离线物料的获取与打包离线部署的核心动作是「在有网的机器上把镜像拉下来导出成 tar再拷进内网」。这一步必须在能出公网的机器上做而且要注意架构一致内网机器是 x86_64导出镜像的机器也必须是 x86_64ARM 和 x86 的镜像不通用。# 在有外网的机器上执行拉取三个镜像 docker pull apache/superset:4.1.1 docker pull postgres:14 docker pull redis:7 # 分别导出为 tar 文件方便拷贝 docker save -o superset-4.1.1.tar apache/superset:4.1.1 docker save -o postgres-14.tar postgres:14 docker save -o redis-7.tar redis:7 # 打包成一个压缩包减少拷贝体积 tar -czvf superset-offline-bundle.tar.gz \ superset-4.1.1.tar postgres-14.tar redis-7.tardocker save会把镜像的所有层打成一个 tar-o指定输出文件名。这里没有用docker export因为export导的是容器文件系统会丢镜像元数据再import回来跑 compose 会缺 entrypoint。tar -czvf只是把三个 tar 再压一层方便一次性拷进内网。拷贝方式按内网实际情况走U 盘、内网文件服务器、scp 都行这一步不涉及任何外网通道。2.3 内网机器的 Docker 运行时检查镜像拷进去之前先确认内网机器的 Docker 能正常工作。很多内网机器装的是老版本 Dockerdocker compose子命令还不存在只有docker-compose。# 检查 Docker 版本要求 20.10 以上 docker version --format {{.Server.Version}} # 检查 compose 是 v2 插件还是 v1 独立命令 docker compose version 2/dev/null || docker-compose version如果输出的是Docker version 19.03这种Superset 4.1.1 的 compose 文件里有些字段会不认常见做法是先升级 Docker。内网升级 Docker 就用离线 rpm 包rpm -Uvh依次装 containerd、docker-ce、docker-ce-cli、docker-compose-plugin。装完systemctl enable --now docker再docker info看一遍存储驱动Overlay2 是正常状态。3. 镜像导入与目录规划把离线包变成能跑的容器3.1 导入镜像并核对标签离线包拷到内网机器后先解压再逐个导入。导入完必须核对镜像标签因为docker load有时候会因为 tar 里的 repo tag 丢失导致镜像变成none。# 解压离线包 tar -xzvf superset-offline-bundle.tar.gz # 依次导入三个镜像 docker load -i superset-4.1.1.tar docker load -i postgres-14.tar docker load -i redis-7.tar # 核对镜像列表确认标签完整 docker images | grep -E superset|postgres|redis正常输出里应该能看到apache/superset 4.1.1、postgres 14、redis 7三行。如果 Superset 那行显示的是none说明 tar 里的标签丢了常见做法是重新docker tag一下docker tag IMAGE_ID apache/superset:4.1.1。这一步不做后面 compose 里写image: apache/superset:4.1.1会直接报找不到镜像。3.2 目录结构规划Superset 容器里需要持久化的东西有三块元数据库数据、Redis 数据、Superset 的superset_config.py。我一般会在宿主机上建一个统一目录挂载进去这样容器删了数据还在。# 创建部署目录 mkdir -p /opt/superset/{postgres-data,redis-data,config} # 目录说明 # postgres-data 挂给 PostgreSQL 的 /var/lib/postgresql/data # redis-data 挂给 Redis 的 /data # config 放 superset_config.py挂到容器 /app/pythonpath/opt/superset这个路径按自己习惯改但三个子目录的用途要分清。postgres-data权限要注意PostgreSQL 容器里跑的是 uid 999宿主机目录如果权限不对容器启动会报initdb: could not change permissions。常见做法是chown -R 999:999 /opt/superset/postgres-data。3.3 编写 docker-compose.yml离线环境里 compose 文件不能写build只能写image因为构建需要联网拉基础镜像。下面这份是我改过的版本去掉了官方 compose 里一些离线用不到的服务。version: 3.8 services: postgres: image: postgres:14 container_name: superset-db environment: POSTGRES_USER: superset POSTGRES_PASSWORD: superset123 POSTGRES_DB: superset volumes: - /opt/superset/postgres-data:/var/lib/postgresql/data restart: unless-stopped redis: image: redis:7 container_name: superset-redis volumes: - /opt/superset/redis-data:/data restart: unless-stopped superset: image: apache/superset:4.1.1 container_name: superset-app depends_on: - postgres - redis environment: SUPERSET_SECRET_KEY: change_this_to_a_random_string DATABASE_HOST: postgres DATABASE_PASSWORD: superset123 REDIS_HOST: redis volumes: - /opt/superset/config:/app/pythonpath ports: - 8088:8088 restart: unless-stoppedSUPERSET_SECRET_KEY必须改官方镜像默认值不安全而且多个容器共用同一个 key 会出 session 串号。DATABASE_HOST和REDIS_HOST写的是 compose 服务名Docker 内部 DNS 会解析不用写 IP。/app/pythonpath是 Superset 读取superset_config.py的默认路径挂载进去后容器启动会自动加载。4. 中文配置与元数据库初始化让界面和登录都正常4.1 superset_config.py 的关键参数Superset 4.1.1 的中文生效分两层一层是前端语言包一层是后端配置里的默认语言和时区。前端语言包官方镜像里已经带了zh不需要额外装但要在配置里把默认语言指过去。# /opt/superset/config/superset_config.py import os # 元数据库连接指向 compose 里的 postgres 服务 SQLALCHEMY_DATABASE_URI ( postgresqlpsycopg2://superset:superset123postgres:5432/superset ) # Redis 缓存配置 CACHE_CONFIG { CACHE_TYPE: RedisCache, CACHE_DEFAULT_TIMEOUT: 300, CACHE_KEY_PREFIX: superset_, CACHE_REDIS_HOST: redis, CACHE_REDIS_PORT: 6379, CACHE_REDIS_DB: 1, } # 默认语言设为简体中文 BABEL_DEFAULT_LOCALE zh LANGUAGES { en: {flag: us, name: English}, zh: {flag: cn, name: 简体中文}, } # 时区避免图表时间偏移 DEFAULT_TIMEZONE Asia/Shanghai # 关闭示例数据加载离线环境没必要 SUPERSET_LOAD_EXAMPLES FalseBABEL_DEFAULT_LOCALE设成zh后新登录用户默认就是中文界面。LANGUAGES里保留 en 和 zh 两个选项用户还能自己切。DEFAULT_TIMEZONE不设的话图表时间会比北京时间少 8 小时这个坑我踩过排查了半天以为是数据库时区问题。SUPERSET_LOAD_EXAMPLES关掉能省掉初始化时的一堆示例数据集离线环境里那些数据也用不上。4.2 初始化元数据库配置挂好之后不要急着docker compose upSuperset 第一次启动需要先初始化元数据库否则登录页会报relation ab_user does not exist。# 先只启动 postgres 和 redis docker compose up -d postgres redis # 等 postgres 健康后执行元数据库初始化 docker compose run --rm superset superset db upgrade # 创建管理员账号 docker compose run --rm superset superset fab create-admin \ --username admin \ --firstname Admin \ --lastname User \ --email adminexample.com \ --password admin123 # 初始化角色和权限 docker compose run --rm superset superset initsuperset db upgrade会按 SQLAlchemy 迁移脚本建表这一步必须在 Superset 主服务启动前做。fab create-admin是 Flask-AppBuilder 的命令创建的是 Superset 登录账号。superset init会同步权限和角色不做这一步管理员登录后看不到菜单。三条命令都用run --rm跑完容器自动删不占资源。4.3 启动主服务并验证中文初始化完成后再启动 superset 服务。# 启动全部服务 docker compose up -d # 查看 superset 日志确认没有报错 docker compose logs -f superset日志里看到Running on http://0.0.0.0:8088就说明起来了。浏览器访问http://内网IP:8088用刚才创建的 admin 账号登录。登录后右上角头像菜单里能看到语言切换默认已经是简体中文。如果界面还是英文先检查superset_config.py是否真的挂载进去了docker exec -it superset-app cat /app/pythonpath/superset_config.py能看到内容说明挂载正常看不到就是路径写错了。5. 避坑与排查离线部署 Superset 4.1.1 最常见的五个翻车点5.1 现象容器启动后立即退出日志显示数据库连接拒绝原因depends_on只保证容器启动顺序不保证 PostgreSQL 已经准备好接受连接。Superset 启动时如果连不上数据库会直接退出。解决在 compose 里给 postgres 加 healthchecksuperset 的depends_on改成带条件的形式。postgres: # ... 其他配置 healthcheck: test: [CMD-SHELL, pg_isready -U superset] interval: 5s timeout: 5s retries: 10 superset: depends_on: postgres: condition: service_healthy redis: condition: service_started5.2 现象登录页能打开但输入账号密码后报 500原因SUPERSET_SECRET_KEY没设或者设成了默认值Flask session 加密失败。解决在 compose 的 superset 环境变量里设一个足够长的随机字符串然后重启容器。已经产生的 session 会失效重新登录即可。5.3 现象中文界面部分菜单还是英文原因Superset 4.1.1 的前端语言包对某些插件菜单的翻译不完整这是版本本身的问题不是配置错误。解决核心菜单已经是中文个别插件名保留英文不影响使用。如果一定要全中文可以在superset_config.py里加BABEL_DEFAULT_LOCALE zh后重新superset init但不要期待 100% 覆盖。5.4 现象docker load 后镜像标签是 none原因导出镜像的机器和导入镜像的机器 Docker 版本差异过大tar 里的 manifest 解析不一致。解决重新docker tag打上正确标签或者在有网机器上用相同大版本 Docker 重新docker save。5.5 现象Celery 相关功能报错异步查询不执行原因离线 compose 里只起了 superset 主服务没有起 celery worker 和 beat。解决如果用到异步查询或定时报表需要在 compose 里补上 worker 和 beat 服务镜像还是apache/superset:4.1.1启动命令分别是celery --appsuperset.tasks.celery_app:app worker和celery --appsuperset.tasks.celery_app:app beat。离线环境里这两个服务不占额外镜像直接复用主镜像即可。6. 装完怎么验证从登录到跑通第一张图表的检查清单验证一套离线 Superset 是不是真的可用不能只看登录页打不打得开。我一般会按下面这个顺序走一遍每一步都过了才算交付。检查项操作预期结果容器状态docker compose ps三个服务都是 Up元数据库表docker exec superset-db psql -U superset -c \dt能看到 ab_user 等表中文界面登录后看右上角语言显示简体中文数据源连接新建 SQLite 数据源测试连接成功图表渲染建一张简单表格图正常出图时区图表时间轴与北京时间一致数据源连接这一步离线环境里可以先用 Superset 自带的 SQLite 测试库路径填sqlite:////app/superset_home/test.db不用额外装驱动。图表渲染选一个最简单的Table类型维度拖一列、指标拖一个 count保存后能出数就说明前后端链路通了。时区检查容易被忽略建图时把时间列拖到维度里看显示的小时数是不是和数据库里存的一致差 8 小时就是DEFAULT_TIMEZONE没生效。还有一个我每次都会做的动作把superset_config.py里的SUPERSET_SECRET_KEY和数据库密码单独记到密码管理里然后docker compose down再up -d一次确认重启后数据还在、登录还能进。离线环境最怕的就是重启后元数据库挂载丢了所有仪表盘配置归零。从那以后我每次交付前都强制走一遍「down 再 up」的验证确认持久化目录真的生效希望帮到你。本文还有配套的精品资源点击获取