这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

应用

使用 Docker 拉起应用软件模板,使用 Pigsty Grafana & Echarts 工具箱进行数据分析与可视化

Applet的结构

Applet,是一种自包含的,运行于Pigsty基础设施中的数据小应用。

一个Pigsty应用通常包括以下内容中的至少一样或全部:

  • 图形界面(Grafana Dashboard定义) 放置于ui目录
  • 数据定义(PostgreSQL DDL File),放置于 sql 目录
  • 数据文件(各类资源,需要下载的文件),放置于data目录
  • 逻辑脚本(执行各类逻辑),放置于bin目录

Pigsty默认提供了几个样例应用:

  • pglog, 分析PostgreSQL CSV日志样本。
  • covid, 可视化WHO COVID-19数据,查阅各国疫情数据。
  • pglog, NOAA ISD,可以查询全球30000个地表气象站从1901年来的气象观测记录。

应用的结构

一个Pigsty应用会在应用根目录提供一个安装脚本:install或相关快捷方式。您需要使用管理用户在 管理节点 执行安装。安装脚本会检测当前的环境(获取 METADB_URLPIGSTY_HOMEGRAFANA_ENDPOINT等信息以执行安装)

通常,带有APP标签的面板会被列入Pigsty Grafana首页导航中App下拉菜单中,带有APPOverview标签的面板则会列入首页面板导航中。

您可以从 https://github.com/Vonng/pigsty/releases/download/v1.5.1/app.tgz 下载带有基础数据的应用进行安装。

1 - Supabase 企业级自建

使用 Pigsty 自托管企业级 supabase,带有监控,高可用,PITR,IaC 以及 400+ PG扩展。

Supabase 很好,拥有属于你自己的 supabase 则好上加好。 Pigsty 可以帮助您在自己的服务器上(物理机/虚拟机/云服务器),一键自建企业级 supabase —— 更多扩展,更好性能,更深入的控制,更合算的成本。

Pigsty 是 Supabase 官网文档上列举的三种自建部署之一:Self-hosting: Third-Party Guides


简短版本

准备 Linux,执行 Pigsty 标准安装 流程,选择 supabase 配置模板,依次执行:

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty
./configure -c supabase    # 使用 supabase 配置(请在 pigsty.yml 中更改凭据)
vi pigsty.yml              # 编辑域名、密码、密钥...
./deploy.yml               # 安装 pigsty
./docker.yml               # 安装 docker compose 组件
./app.yml                  # 使用 docker 启动 supabase 无状态部分(可能较慢)

安装完毕后,使用浏览器访问 8000 端口造访 Supa Studio,用户名 supabase,密码 pigsty


目录


Supabase是什么?

Supabase 是一个 BaaS (Backend as Service),开源的 Firebase,是 AI Agent 时代最火爆的数据库 + 后端解决方案。 Supabase 对 PostgreSQL 进行了封装,并提供了身份认证,消息传递,边缘函数,对象存储,并基于 PG 数据库模式自动生成 REST API 与 GraphQL API。

Supabase 旨在为开发者提供一条龙式的后端解决方案,减少开发和维护后端基础设施的复杂性。 它能让开发者告别绝大部分后端开发的工作,只需要懂数据库设计与前端即可快速出活! 开发者只要用 Vibe Coding 糊个前端与数据库模式设计,就可以快速完成一个完整的应用。

目前,Supabase 是 PostgreSQL 开源生态 中人气最高的开源项目,在 GitHub 上已有 八万 Star。 Supabase 还为小微创业者提供了"慷慨"的免费云服务额度 —— 免费的 500 MB 空间,对于存个用户表,浏览数之类的东西绰绰有余。


为什么要自建?

既然 Supabase 云服务这么香,为什么要自建呢?

最直观的原因是是我们在《云数据库是智商税吗?》中提到过的:当你的数据/计算规模超出云计算适用光谱(Supabase:4C/8G/500MB免费存储),成本很容易出现爆炸式增长。 而且在当下,足够可靠的 本地企业级 NVMe SSD 在性价比上与 云端存储 有着三到四个数量级的优势,而自建能更好地利用这一点。

另一个重要的原因是 功能, Supabase 云服务的功能受限 —— 很多强力PG扩展因为多租户安全挑战与许可证的原因无法以云服务的形式。 故而尽管 扩展是 PostgreSQL 的核心特色,在 Supabase 云服务上也依然只有 64 个扩展可用。 而通过 Pigsty 自建的 Supabase 则提供了多达 437 个开箱即用的 PG 扩展。

此外,自主可控与规避供应商锁定也是自建的重要原因 —— 尽管 Supabase 虽然旨在提供一个无供应商锁定的 Google Firebase 开源替代,但实际上自建高标准企业级的 Supabase 门槛并不低。 Supabase 内置了一系列由他们自己开发维护的 PG 扩展插件,并计划将原生的 PostgreSQL 内核替换为收购的 OrioleDB,而这些内核与扩展在 PGDG 官方仓库中并没有提供。

这实际上是某种隐性的供应商锁定,阻止了用户使用除了 supabase/postgres Docker 镜像之外的方式自建,Pigsty 则提供开源,透明,通用的方案解决这个问题。 我们将所有 Supabase 自研与用到的 10 个缺失的扩展打成开箱即用的 RPM/DEB 包,确保它们在所有 主流Linux操作系统发行版 上都可用:

扩展说明
pg_graphql提供PG内的GraphQL支持 (RUST),Rust扩展,由PIGSTY提供
pg_jsonschema提供JSON Schema校验能力,Rust扩展,由PIGSTY提供
wrappersSupabase提供的外部数据源包装器捆绑包,,Rust扩展,由PIGSTY提供
index_advisor查询索引建议器,SQL扩展,由PIGSTY提供
pg_net用 SQL 进行异步非阻塞HTTP/HTTPS 请求的扩展 (supabase),C扩展,由PIGSTY提供
vault在 Vault 中存储加密凭证的扩展 (supabase),C扩展,由PIGSTY提供
pgjwtJSON Web Token API 的PG实现 (supabase),SQL扩展,由PIGSTY提供
pgsodium表数据加密存储 TDE,扩展,由PIGSTY提供
supautils用于在云环境中确保数据库集群的安全,C扩展,由PIGSTY提供
pg_plan_filter使用执行计划代价过滤阻止特定查询语句,C扩展,由PIGSTY提供

同时,我们在 Supabase 自建部署中默认 安装绝大多数扩展,您可以参考可用扩展列表按需 启用

同时,Pigsty 还会负责好底层 高可用 PostgreSQL 数据库集群,高可用 MinIO 对象存储集群的自动搭建,甚至是 Docker 容器底座的部署与 Nginx 反向代理,域名配置HTTPS证书签发。 您可以使用 Docker Compose 拉起任意数量的无状态 Supabase 容器集群,并将状态存储在外部 Pigsty 自托管数据库服务中。

在这一自建部署架构中,您获得了使用不同内核的自由(PG 15-18,OrioleDB),加装 437 个扩展的自由,扩容与伸缩 Supabase / Postgres / MinIO 的自由, 免于数据库运维杂务的自由,以及免于供应商锁定,本地运行到地老天荒的自由。 而相比于使用云服务需要付出的代价,不过是准备服务器和多敲几行命令而已。


单节点自建快速上手

让我们先从单节点 Supabase 部署开始,我们会在后面进一步介绍多节点高可用部署的方法。

准备 一台全新 Linux 服务器,使用 Pigsty 提供的 supabase 配置模板执行 标准安装, 然后额外运行 docker.ymlapp.yml 拉起无状态部分的 Supabase 容器即可(默认端口 8000/8433)。

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty
./configure -c supabase    # 使用 supabase 配置(请在 pigsty.yml 中更改凭据)
vi pigsty.yml              # 编辑域名、密码、密钥...
./deploy.yml               # 安装 pigsty
./docker.yml               # 安装 docker compose 组件
./app.yml                  # 使用 docker 启动 supabase 无状态部分

在部署 Supabase 前请根据实际情况修改自动生成的 pigsty.yml 配置文件中的参数(域名与密码) 如果只是本地开发测试,可以先跳过,我们将在后面介绍如何通过修改配置文件来进一步定制。

如果配置无误,大约十分钟后,就可以在本地网络通过 http://<your_ip_address>:8000 访问到 Supabase Studio 图形管理界面了。 默认的用户名与密码分别是: supabasepigsty

注意事项:

  • 在中国大陆地区,Pigsty 默认使用 1Panel 与 1ms 提供的 DockerHub 镜像站点下载 Supabase 相关镜像,可能会较慢。你也可以自行配置 代理镜像站cd /opt/supabase; docker compose pull 手动拉取镜像。我们亦提供包含完整离线安装方案的 Supabase 自建专家咨询服务。
  • 如果你需要使用的对象存储功能,那么需要通过域名与 HTTPS 访问 Supabase,否则会出现报错。
  • 对于严肃的生产部署,请 务必 修改所有默认密码!

自建关键技术决策

以下是一些自建 Supabase 会涉及到的关键技术决策,供您参考:

使用默认的单节点部署 Supabase 无法享受到 PostgreSQL / MinIO 的高可用能力。 尽管如此,单节点部署相比官方纯 Docker Compose 方案依然要有显著优势: 例如开箱即用的监控系统,自由安装扩展的能力,各个组件的扩缩容能力,以及提供兜底数据库时间点恢复能力等。

如果您只有一台服务器,或者选择在云服务器上自建,Pigsty 建议您使用外部的 S3 替代本地的 MinIO 作为对象存储,存放 PostgreSQL 的备份,并承载 Supabase Storage 服务。 这样的部署在故障时可以在单机部署条件下,提供一个兜底级别的 RTO (小时级恢复时长)/ RPO (MB级数据损失)容灾水平。

在严肃的生产部署中,Pigsty 建议使用至少3~4个节点的部署策略,确保 MinIO 与 PostgreSQL 都使用满足企业级高可用要求的多节点部署。 在这种情况下,您需要相应准备更多节点与磁盘,并相应调整 pigsty.yml 配置清单中的集群配置,以及 supabase 集群配置中的接入信息,使用高可用接入点访问服务。

Supabase 的部分功能需要发送邮件,所以要用到 SMTP 服务。除非单纯用于内网,否则对于严肃的生产部署,建议使用 SMTP 云服务。自建的邮件服务器发送的邮件容易被标记为垃圾邮件导致拒收。

如果您的服务直接向公网暴露,我们强烈建议您使用真正的域名与 HTTPS 证书,并通过 Nginx 门户 访问。

接下来,我们会依次讨论一些进阶主题。如何在单节点部署的基础上,进一步提升 Supabase 的安全性、可用性与性能。


进阶主题:安全加固

Pigsty基础组件

对于严肃的生产部署,我们强烈建议您修改 Pigsty 基础组件的密码。因为这些默认值是公开且众所周知的,不改密码上生产无异于裸奔:

以上密码为 Pigsty 组件模块的密码,强烈建议在安装部署前就设置完毕。

Supabase密钥

除了 Pigsty 组件的密码,你还需要 修改 Supabase 的密钥,包括

这里请您务必参照 Supabase教程:保护你的服务 里的说明:

  • 生成一个长度超过 40 个字符的 JWT_SECRET,并使用教程中的工具签发 ANON_KEYSERVICE_ROLE_KEY 两个 JWT。
  • 使用教程中提供的工具,根据 JWT_SECRET 以及过期时间等属性,生成一个 ANON_KEY JWT,这是匿名用户的身份凭据。
  • 使用教程中提供的工具,根据 JWT_SECRET 以及过期时间等属性,生成一个 SERVICE_ROLE_KEY,这是权限更高服务角色的身份凭据。
  • 指定一个32个字符以上的随机字符串密钥 PG_META_CRYPTO_KEY,用于加密 Studio UI 与 meta 服务的交互
  • 如果您使用的 PostgreSQL 业务用户使用了不同于默认值的密码,请相应修改 `POSTGRES_PASSWORD`` 的值
  • 如果您的对象存储使用了不同于默认值的密码,请相应修改 S3_ACCESS_KEY``](https://github.com/pgsty/pigsty/blob/main/conf/supabase.yml#L154) 与 [S3_SECRET_KEY`` 的值

Supabase 部分的凭据修改后,您可以重启 Docker Compose 容器以应用新的配置:

./app.yml -t app_config,app_launch   # 使用剧本
cd /opt/supabase; make up            # 手工执行

进阶主题:域名接入

如果你在本机或局域网内使用 Supabase,那么可以选择 IP:Port 直连 Kong 对外暴露的 HTTP 8000 端口访问 Supabase。

你可以使用一个内网静态解析的域名,但对于严肃的生产部署,我们建议您使用真域名 + HTTPS 来访问 Supabase。 在这种情况下,您的服务器应当有一个公网 IP 地址,你应当拥有一个域名,使用云/DNS/CDN 供应商提供的 DNS 解析服务,将其指向安装节点的公网 IP(可选默认下位替代:本地 /etc/hosts 静态解析)。

比较简单的做法是,直接批量替换占位域名(supa.pigsty)为你的实际域名,假设为 supa.pigsty.cc

sed -ie 's/supa.pigsty.cc/supa.pigsty/g' ~/pigsty/pigsty.yml

如果你没有事先配置好,那么重载 Nginx 和 Supabase 的配置生效即可:

make nginx      # 重载 nginx 配置
make cert       # 申请 certbot 免费 HTTPS 证书
./app.yml       # 重载 Supabase 配置

修改后的配置应当类似下面的片段:

all:
  vars:
    infra_portal:
      supa :
        domain: supa.pigsty.cc        # 替换为你的域名!
        endpoint: "10.10.10.10:8000"
        websocket: true
        certbot: supa.pigsty.cc       # 证书名称,通常与域名一致即可

  children:
    supabase:
      vars:
          supabase:                                       # the definition of supabase app
            conf:                                         # override /opt/supabase/.env
              SITE_URL: https://supa.pigsty                # <------- Change This to your external domain name
              API_EXTERNAL_URL: https://supa.pigsty        # <------- Otherwise the storage api may not work!
              SUPABASE_PUBLIC_URL: https://supa.pigsty     # <------- DO NOT FORGET TO PUT IT IN infra_portal!

完整的域名/HTTPS 配置可以参考 证书管理 教程,您也可以使用 Pigsty 自带的本地静态解析与自签发 HTTPS 证书作为下位替代。


进阶主题:外部对象存储

您可以使用 S3 或 S3 兼容的服务,来作为 PGSQL 备份与 Supabase 使用的对象存储。这里我们使用一个 阿里云 OSS 对象存储作为例子。

Pigsty 提供了一个 terraform/spec/aliyun-meta-s3.tf 模板, 可以用于在阿里云上拉起一台服务器,以及一个 OSS 存储桶。

首先,我们修改 all.children.supa.vars.apps.[supabase].conf 中 S3 相关的配置,将其指向阿里云 OSS 存储桶:

# if using s3/minio as file storage
S3_BUCKET: data                       # 替换为 S3 兼容服务的连接信息
S3_ENDPOINT: https://sss.pigsty:9000  # 替换为 S3 兼容服务的连接信息
S3_ACCESS_KEY: s3user_data            # 替换为 S3 兼容服务的连接信息
S3_SECRET_KEY: S3User.Data            # 替换为 S3 兼容服务的连接信息
S3_FORCE_PATH_STYLE: true             # 替换为 S3 兼容服务的连接信息
S3_REGION: stub                       # 替换为 S3 兼容服务的连接信息
S3_PROTOCOL: https                    # 替换为 S3 兼容服务的连接信息

同样使用以下命令重载 Supabase 配置:

./app.yml -t app_config,app_launch

您同样可以使用 S3 作为 PostgreSQL 的备份仓库,在 all.vars.pgbackrest_repo 新增一个 aliyun 备份仓库的定义:

all:
  vars:
    pgbackrest_method: aliyun          # pgbackrest 备份方法:local,minio,[其他用户定义的仓库...],本例中将备份存储到 MinIO 上
    pgbackrest_repo:                   # pgbackrest 备份仓库: https://pgbackrest.org/configuration.html#section-repository
      aliyun:                          # 定义一个新的备份仓库 aliyun
        type: s3                       # 阿里云 oss 是 s3-兼容的对象存储
        s3_endpoint: oss-cn-beijing-internal.aliyuncs.com
        s3_region: oss-cn-beijing
        s3_bucket: pigsty-oss
        s3_key: xxxxxxxxxxxxxx
        s3_key_secret: xxxxxxxx
        s3_uri_style: host
        path: /pgbackrest
        bundle: y                         # bundle small files into a single file
        bundle_limit: 20MiB               # Limit for file bundles, 20MiB for object storage
        bundle_size: 128MiB               # Target size for file bundles, 128MiB for object storage
        cipher_type: aes-256-cbc          # enable AES encryption for remote backup repo
        cipher_pass: pgBackRest.MyPass    # 设置一个加密密码,pgBackRest 备份仓库的加密密码
        retention_full_type: time         # retention full backup by time on minio repo
        retention_full: 14                # keep full backup for the last 14 days

然后在 all.vars.pgbackrest_mehod 中指定使用 aliyun 备份仓库,重置 pgBackrest 备份:

./pgsql.yml -t pgbackrest

Pigsty 会将备份仓库切换到外部对象存储上,更多备份配置可以参考 PostgreSQL 备份 文档。


进阶主题:使用SMTP

你可以使用 SMTP 来发送邮件,修改 supabase 应用配置,添加 SMTP 信息:

all:
  children:
    supabase:        # supa group
      vars:          # supa group vars
        apps:        # supa group app list
          supabase:  # the supabase app
            conf:    # the supabase app conf entries
              SMTP_HOST: smtpdm.aliyun.com:80
              SMTP_PORT: 80
              SMTP_USER: no_reply@mail.your.domain.com
              SMTP_PASS: your_email_user_password
              SMTP_SENDER_NAME: MySupabase
              SMTP_ADMIN_EMAIL: adminxxx@mail.your.domain.com
              ENABLE_ANONYMOUS_USERS: false

不要忘了使用 app.yml 来重载配置


进阶主题:真·高可用

经过这些配置,您拥有了一个带公网域名,HTTPS 证书,SMTP,PITR 备份,监控,IaC,以及 400+ 扩展的企业级 Supabase (基础单机版)。 高可用的配置请参考 Pigsty 其他部份的文档,如果您懒得阅读学习,我们提供手把手扶上马的 Supabase 自建专家咨询服务 —— ¥2000 元免去折腾与下载的烦恼。

单节点的 RTO / RPO 依赖外部对象存储服务提供兜底,如果您的这个节点挂了,外部 S3 存储中保留了备份,您可以在新的节点上重新部署 Supabase,然后从备份中恢复。 这样的部署在故障时可以提供一个最低标准的 RTO (小时级恢复时长)/ RPO (MB级数据损失)兜底容灾水平 兜底。

如果想要达到 RTO < 30s ,切换零数据丢失,那么需要使用多节点进行高可用部署,这涉及到:

  • ETCD: DCS 需要使用三个节点或以上,才能容忍一个节点的故障。
  • PGSQL: PGSQL 同步提交不丢数据模式,建议使用至少三个节点。
  • INFRA:监控基础设施故障影响稍小,建议生产环境使用双副本
  • Supabase 无状态容器本身也可以是多节点的副本,可以实现高可用。

在这种情况下,您还需要修改 PostgreSQL 与 MinIO 的接入点,使用 DNS / L2 VIP / HAProxy 等 高可用接入点 关于这些部分,您只需参考 Pigsty 中各个模块的文档进行配置部署即可。 建议您参考 conf/ha/trio.ymlconf/ha/safe.yml 中的配置,将集群规模升级到三节点或以上。

2 - Odoo:自建开源 ERP

如何拉起开箱即用的企业级应用全家桶 Odoo,并使用 Pigsty 管理其后端 PostgreSQL 数据库。

Odoo 是一个开源企业资源规划 (ERP) 软件,提供一整套业务应用程序,包括 CRM、销售、采购、库存、生产、会计和其他管理功能。Odoo 是一个典型的 Web 应用程序,使用 PostgreSQL 作为底层数据库。

您的所有业务,都在一个平台上,简单、高效且实惠

公开演示(不一定开放):http://odoo.pigsty.io, 用户名: test@pigsty.io, 密码: pigsty


快速开始

在运行兼容操作系统的全新 Linux x86 / ARM 服务器上执行:

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty
./bootstrap                # 安装 ansible
./configure -c app/odoo    # 使用 odoo 配置(请在 pigsty.yml 中更改凭据)
./deploy.yml               # 安装 pigsty
./docker.yml               # 安装 docker compose
./app.yml                  # 使用 docker 启动 odoo 无状态部分

Odoo 默认监听在 8069 端口,您可以通过浏览器访问 http://<ip>:8069。默认的用户名和密码都是 admin

您可以在浏览器所在主机(/etc/hosts)添加一条解析记录 odoo.pigsty 指向您的服务器,这样您就可以通过 http://odoo.pigsty 访问 Odoo 网络界面了。

如果您想要通过 SSL/HTTPS 访问 Odoo,您需要使用真正的 SSL 证书,或者信任 Pigsty 自动生成的自签名 CA 证书。(当然,在 Chrome 浏览器中,您也可以使用敲击键入 thisisunsafe 来绕过证书验证)


配置模板

conf/app/odoo.yml 定义了一个模板配置文件,包含单个 Odoo 实例所需的资源。

all:
  children:

    # odoo 应用程序(默认用户名和密码:admin/admin)
    odoo:
      hosts: { 10.10.10.10: {} }
      vars:
        app: odoo   # 指定要安装的应用程序名称(在 apps 中)
        apps:       # 定义所有应用程序
          odoo:     # 应用程序名称应该有对应的 ~/app/odoo 文件夹
            file:   # 要创建的可选目录
              - { path: /data/odoo         ,state: directory, owner: 100, group: 101 }
              - { path: /data/odoo/webdata ,state: directory, owner: 100, group: 101 }
              - { path: /data/odoo/addons  ,state: directory, owner: 100, group: 101 }
            conf:   # 覆盖 /opt/<app>/.env 配置文件
              PG_HOST: 10.10.10.10            # postgres 主机
              PG_PORT: 5432                   # postgres 端口
              PG_USERNAME: odoo               # postgres 用户
              PG_PASSWORD: DBUser.Odoo        # postgres 密码
              ODOO_PORT: 8069                 # odoo 应用程序端口
              ODOO_DATA: /data/odoo/webdata   # odoo webdata
              ODOO_ADDONS: /data/odoo/addons  # odoo 插件
              ODOO_DBNAME: odoo               # odoo 数据库名称
              ODOO_VERSION: 19.0              # odoo 镜像版本

    # odoo 数据库
    pg-odoo:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-odoo
        pg_users:
          - { name: odoo    ,password: DBUser.Odoo ,pgbouncer: true ,roles: [ dbrole_admin ] ,createdb: true ,comment: admin user for odoo service }
          - { name: odoo_ro ,password: DBUser.Odoo ,pgbouncer: true ,roles: [ dbrole_readonly ]  ,comment: read only user for odoo service  }
          - { name: odoo_rw ,password: DBUser.Odoo ,pgbouncer: true ,roles: [ dbrole_readwrite ] ,comment: read write user for odoo service }
        pg_databases:
          - { name: odoo ,owner: odoo ,revokeconn: true ,comment: odoo main database  }
        pg_hba_rules:
          - { user: all ,db: all ,addr: 172.17.0.0/16  ,auth: pwd ,title: 'allow access from local docker network' }
          - { user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes' }

    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }

  vars:                               # 全局变量
    version: v3.7.0                   # pigsty 版本字符串
    admin_ip: 10.10.10.10             # 管理节点 ip 地址
    region: default                   # 上游镜像区域:default|china|europe
    node_tune: oltp                   # 节点调优规格:oltp,olap,tiny,crit
    pg_conf: oltp.yml                 # pgsql 调优规格:{oltp,olap,tiny,crit}.yml

    docker_enabled: true              # 在应用程序组上启用 docker
    #docker_registry_mirrors: ["https://docker.m.daocloud.io"] # 在中国大陆使用道云镜像
    proxy_env:                        # 下载包和拉取 docker 镜像时的全局代理环境
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.tsinghua.edu.cn"
      #http_proxy:  127.0.0.1:12345 # 在此处添加代理环境以下载包或拉取镜像
      #https_proxy: 127.0.0.1:12345 # 通常代理格式为 http://user:pass@proxy.xxx.com
      #all_proxy:   127.0.0.1:12345

    infra_portal: # 域名和上游服务器
      home         : { domain: h.pigsty }
      grafana      : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
      prometheus   : { domain: p.pigsty ,endpoint: "${admin_ip}:9058" }
      alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9059" }
      blackbox     : { endpoint: "${admin_ip}:9115" }
      loki         : { endpoint: "${admin_ip}:3100" }
      minio        : { domain: m.pigsty    ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
      odoo         : { domain: odoo.pigsty, endpoint: "127.0.0.1:8069"   ,websocket: true }  #cert: /path/to/crt ,key: /path/to/key
      # 在这里设置您自己的域名 ^^^,或使用默认域名,或 ip + 8069 端口直接访问
      # certbot --nginx --agree-tos --email your@email.com -n -d odoo.your.domain    # 替换为您的邮箱和 odoo 域名

    #----------------------------------#
    # 凭据:更改这些密码
    #----------------------------------#
    #grafana_admin_username: admin
    grafana_admin_password: pigsty
    #pg_admin_username: dbuser_dba
    pg_admin_password: DBUser.DBA
    #pg_monitor_username: dbuser_monitor
    pg_monitor_password: DBUser.Monitor
    #pg_replication_username: replicator
    pg_replication_password: DBUser.Replicator
    #patroni_username: postgres
    patroni_password: Patroni.API
    #haproxy_admin_username: admin
    haproxy_admin_password: pigsty

    repo_modules: infra,node,pgsql,docker
    repo_packages: [ node-bootstrap, infra-package, infra-addons, node-package1, node-package2, pgsql-utility, docker ]
    repo_extra_packages: [ pg18-main ]
    pg_version: 18

基础

检查 .env 文件中的可配置环境变量:

# https://hub.docker.com/_/odoo#
PG_HOST=10.10.10.10
PG_PORT=5432
PG_USER=dbuser_odoo
PG_PASS=DBUser.Odoo
ODOO_PORT=8069

然后使用以下命令启动 odoo:

make up  # docker compose up

访问 http://ddl.pigsty 或 http://10.10.10.10:8887

Makefile

make up         # 在最小模式下使用 docker compose 启动 odoo
make run        # 使用 docker 启动 odoo,本地数据目录和外部 PostgreSQL
make view       # 打印 odoo 访问点
make log        # tail -f odoo 日志
make info       # 使用 jq 检查 odoo
make stop       # 停止 odoo 容器
make clean      # 移除 odoo 容器
make pull       # 拉取最新的 odoo 镜像
make rmi        # 移除 odoo 镜像
make save       # 保存 odoo 镜像到 /tmp/docker/odoo.tgz
make load       # 从 /tmp/docker/odoo.tgz 加载 odoo 镜像

使用外部 PostgreSQL

您可以为 Odoo 使用外部 PostgreSQL。Odoo 将在设置期间创建自己的数据库,因此您不需要这样做

pg_users: [ { name: dbuser_odoo ,password: DBUser.Odoo ,pgbouncer: true ,roles: [ dbrole_admin ]    ,comment: admin user for odoo database } ]
pg_databases: [ { name: odoo ,owner: dbuser_odoo ,revokeconn: true ,comment: odoo primary database } ]

并使用以下命令创建业务用户和数据库:

bin/pgsql-user  pg-meta  dbuser_odoo
#bin/pgsql-db    pg-meta  odoo     # odoo 将在设置期间创建数据库

检查连接性:

psql postgres://dbuser_odoo:DBUser.Odoo@10.10.10.10:5432/odoo

暴露 Odoo 服务

通过 nginx 门户 暴露 odoo Web 服务:

    infra_portal:                     # 域名和上游服务器
      home         : { domain: h.pigsty }
      grafana      : { domain: g.pigsty    ,endpoint: "${admin_ip}:3000" , websocket: true }
      prometheus   : { domain: p.pigsty    ,endpoint: "${admin_ip}:9058" }
      alertmanager : { domain: a.pigsty    ,endpoint: "${admin_ip}:9059" }
      blackbox     : { endpoint: "${admin_ip}:9115" }
      loki         : { endpoint: "${admin_ip}:3100" }
      odoo         : { domain: odoo.pigsty, endpoint: "127.0.0.1:8069", websocket: true }  # <------ 添加这一行
./infra.yml -t nginx   # 设置 nginx 基础设施门户

Odoo 插件

社区中有很多 Odoo 模块可用,您可以通过下载并将它们放在 addons 文件夹中来安装它们。

volumes:
  - ./addons:/mnt/extra-addons

您可以将 ./addons 目录挂载到容器中的 /mnt/extra-addons,然后下载并解压到 addons 文件夹,

要启用插件模块,首先进入 开发者模式

设置 -> 通用设置 -> 开发者工具 -> 激活开发者模式

然后转到 > 应用程序 -> 更新应用程序列表,然后您可以找到额外的插件并从面板安装。

常用的 免费 插件:会计套件


演示

查看公共演示:http://odoo.pigsty.io,用户名:test@pigsty.io,密码:pigsty

如果您想通过 SSL 访问 odoo,您必须在浏览器中信任 files/pki/ca/ca.crt(或在 chrome 中使用肮脏的黑客 thisisunsafe

3 - Dify:AI 工作流平台

如何使用 Pigsty 自建 AI Workflow LLMOps 平台 —— Dify,并使用外部 PostgreSQL,PGVector,Redis 作为存储?

Dify 是一个生成式 AI 应用创新引擎和开源 LLM 应用开发平台。它提供从 Agent 构建到 AI 工作流编排、RAG 检索和模型管理的能力,帮助用户轻松构建和运营生成式 AI 原生应用程序。

Pigsty 提供对自托管 Dify 的支持,允许您使用单个命令部署 Dify,同时将关键状态存储在外部管理的 PostgreSQL 中。您可以在同一个 PostgreSQL 实例中使用 pgvector 作为向量数据库,进一步简化部署。

当前 Pigsty v3.4 支持 Dify 版本:v1.1.3


快速开始

在运行 兼容操作系统 的全新 Linux x86 / ARM 服务器上执行:

curl -fsSL https://repo.pigsty.cc/get | bash; cd ~/pigsty
./bootstrap                # 安装 Pigsty 依赖
./configure -c app/dify    # 使用 Dify 配置模板
vi pigsty.yml              # 编辑密码、域名、密钥等

./deploy.yml               # 安装 Pigsty
./docker.yml               # 安装 Docker 和 Compose
./app.yml                  # 安装 Dify

Dify 默认监听端口 5001。您可以通过浏览器访问 http://<ip>:5001 并设置您的初始用户凭据来登录。

Dify 启动后,您可以安装各种扩展、配置系统模型并开始使用它!


为什么要自托管

自托管 Dify 有很多原因,但主要动机是数据安全。Dify 提供的 DockerCompose 模板使用基本的默认数据库镜像,缺乏企业级功能,如高可用性、灾难恢复、监控、IaC 和 PITR 能力。

Pigsty 为 Dify 优雅地解决了这些问题,基于配置文件使用单个命令部署所有组件,并使用镜像解决中国地区访问挑战。这使得 Dify 部署和交付变得非常顺畅。它一次性处理 PostgreSQL 主数据库、PGVector 向量数据库、MinIO 对象存储、Redis、Prometheus 监控、Grafana 可视化、Nginx 反向代理和免费 HTTPS 证书。

Pigsty 确保所有 Dify 状态都存储在外部管理的服务中,包括 PostgreSQL 中的元数据和文件系统中的其他数据。通过 Docker Compose 启动的 Dify 实例成为可以随时销毁和重建的无状态应用程序,大大简化了运维。


安装

让我们从单节点 Dify 部署开始。我们稍后将介绍生产高可用部署方法。

首先,使用 Pigsty 的 标准安装过程 安装 Dify 所需的 PostgreSQL 实例:

curl -fsSL https://repo.pigsty.cc/get | bash; cd ~/pigsty
./bootstrap               # 准备 Pigsty 依赖
./configure -c app/dify   # 使用 Dify 应用程序模板
vi pigsty.yml             # 编辑配置文件,修改域名和密码
./deploy.yml              # 安装 Pigsty 和各种数据库

当您使用 ./configure -c app/dify 命令时,Pigsty 会根据 conf/app/dify.yml 模板和您当前的环境自动生成配置文件。 您应该根据实际需要在生成的 pigsty.yml 配置文件中修改密码、域名和其他相关参数,然后使用 ./deploy.yml 执行标准安装过程。

接下来,运行 docker.yml 安装 Docker 和 Docker Compose,然后使用 app.yml 完成 Dify 部署:

./docker.yml              # 安装 Docker 和 Docker Compose
./app.yml                 # 使用 Docker 部署 Dify 无状态组件

您可以在本地网络上通过 http://<your_ip_address>:5001 访问 Dify Web 管理界面。

首次登录时会提示设置默认用户名、邮箱和密码。

您也可以使用本地解析的占位符域名 dify.pigsty,或按照下面的配置使用带有 HTTPS 证书的真实域名。


配置

当您使用 ./configure -c app/dify 命令进行配置时,Pigsty 会根据 conf/app/dify.yml 模板和您当前的环境自动生成配置文件。以下是默认配置的详细说明:

all:
  children:

    # dify 应用程序
    dify:
      hosts: { 10.10.10.10: {} }
      vars:
        app: dify   # 指定要安装的应用程序名称(在 apps 中)
        apps:       # 定义所有应用程序
          dify:     # 应用程序名称,应该有对应的 ~/pigsty/app/dify 文件夹
            file:   # 要创建的数据目录
              - { path: /data/dify ,state: directory ,mode: 0755 }
            conf:   # 覆盖 /opt/dify/.env 配置文件

              # 更改域名、镜像、代理、密钥
              NGINX_SERVER_NAME: dify.pigsty
              # 用于签名和加密的密钥,使用 `openssl rand -base64 42` 生成(更改密码!)
              SECRET_KEY: sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U
              # 默认使用端口 5001 暴露 DIFY nginx 服务
              DIFY_PORT: 5001
              # dify 文件存储位置?默认是 ./volume,我们将使用上面创建的另一个卷
              DIFY_DATA: /data/dify

              # 代理和镜像设置
              #PIP_MIRROR_URL: https://pypi.tuna.tsinghua.edu.cn/simple
              #SANDBOX_HTTP_PROXY: http://10.10.10.10:12345
              #SANDBOX_HTTPS_PROXY: http://10.10.10.10:12345

              # 数据库凭据
              DB_USERNAME: dify
              DB_PASSWORD: difyai123456
              DB_HOST: 10.10.10.10
              DB_PORT: 5432
              DB_DATABASE: dify
              VECTOR_STORE: pgvector
              PGVECTOR_HOST: 10.10.10.10
              PGVECTOR_PORT: 5432
              PGVECTOR_USER: dify
              PGVECTOR_PASSWORD: difyai123456
              PGVECTOR_DATABASE: dify
              PGVECTOR_MIN_CONNECTION: 2
              PGVECTOR_MAX_CONNECTION: 10

    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        pg_users:
          - { name: dify ,password: difyai123456 ,pgbouncer: true ,roles: [ dbrole_admin ] ,superuser: true ,comment: dify superuser }
        pg_databases:
          - { name: dify ,owner: dify ,revokeconn: true ,comment: dify main database  }
        pg_hba_rules:
          - { user: dify ,db: all ,addr: 172.17.0.0/16  ,auth: pwd ,title: 'allow dify access from local docker network' }
        node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ] # 每天凌晨 1 点进行完整备份

    infra: { hosts: { 10.10.10.10: { infra_seq: 1 } } }
    etcd:  { hosts: { 10.10.10.10: { etcd_seq: 1 } }, vars: { etcd_cluster: etcd } }
    #minio: { hosts: { 10.10.10.10: { minio_seq: 1 } }, vars: { minio_cluster: minio } }

  vars:                               # 全局变量
    version: v3.4.1                   # pigsty 版本字符串
    admin_ip: 10.10.10.10             # 管理节点 ip 地址
    region: default                   # 上游镜像区域:default|china|europe
    node_tune: oltp                   # 节点调优规格:oltp,olap,tiny,crit
    pg_conf: oltp.yml                 # pgsql 调优规格:{oltp,olap,tiny,crit}.yml

    docker_enabled: true              # 在应用程序组上启用 docker
    #docker_registry_mirrors: ["https://docker.1ms.run"] # 在中国大陆使用镜像

    proxy_env:                        # 下载包和拉取 docker 镜像时的全局代理环境
      no_proxy: "localhost,127.0.0.1,10.0.0.0/8,192.168.0.0/16,*.pigsty,*.aliyun.com,mirrors.*,*.tsinghua.edu.cn"
      #http_proxy:  127.0.0.1:12345 # 在此处添加代理环境以下载包或拉取镜像
      #https_proxy: 127.0.0.1:12345 # 通常代理格式为 http://user:pass@proxy.xxx.com
      #all_proxy:   127.0.0.1:12345

    infra_portal: # 域名和上游服务器
      home         : { domain: h.pigsty }
      grafana      : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
      prometheus   : { domain: p.pigsty ,endpoint: "${admin_ip}:9058" }
      alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9059" }
      blackbox     : { endpoint: "${admin_ip}:9115" }
      loki         : { endpoint: "${admin_ip}:3100" }
      #minio        : { domain: m.pigsty    ,endpoint: "${admin_ip}:9001" ,scheme: https ,websocket: true }
      dify:                            # dify 的 nginx 服务器配置
        domain: dify.pigsty            # 替换为您自己的域名!
        endpoint: "10.10.10.10:5001"   # dify 服务端点:IP:PORT
        websocket: true                # 添加 websocket 支持
        certbot: dify.pigsty           # certbot 证书名称,使用 `make cert` 申请

    #----------------------------------#
    # 凭据:更改这些密码
    #----------------------------------#
    #grafana_admin_username: admin
    grafana_admin_password: pigsty
    #pg_admin_username: dbuser_dba
    pg_admin_password: DBUser.DBA
    #pg_monitor_username: dbuser_monitor
    pg_monitor_password: DBUser.Monitor
    #pg_replication_username: replicator
    pg_replication_password: DBUser.Replicator
    #patroni_username: postgres
    patroni_password: Patroni.API
    #haproxy_admin_username: admin
    haproxy_admin_password: pigsty
    #minio_access_key: minioadmin
    minio_secret_key: minioadmin      # minio root 密钥,默认为 `minioadmin`

    repo_extra_packages: [ pg17-main ]
    pg_version: 17

检查清单

以下是您需要关注的配置项检查清单:

  • 硬件/软件:准备所需的机器资源:Linux x86_64/arm64 服务器,主流 Linux 操作系统 的全新安装
  • 网络/权限:SSH 免密登录访问权限,用户具有 免密 sudo 权限
  • 确保机器在内网中有静态 IPv4 网络地址且可访问互联网
  • 如果通过公网访问,确保您有可用的域名指向当前节点的 公网 IP 地址
  • 确保使用 app/dify 配置模板并根据需要修改参数
    • configure -c app/dify,并输入节点的内网主 IP 地址,或通过 -i <primary_ip> 命令行参数指定
  • 您是否修改了所有密码相关的配置参数?【可选】
  • 您是否修改了 PostgreSQL 集群业务用户密码和使用这些密码的应用程序配置?
    • 默认用户名 dify 和密码 difyai123456 是 Pigsty 为 Dify 生成的,请根据实际情况修改
    • 在 Dify 的配置块中,请相应修改 DB_USERNAMEDB_PASSWORDPGVECTOR_USERPGVECTOR_PASSWORD 等参数
  • 您是否修改了 Dify 的默认加密密钥?
    • 您可以使用 openssl rand -base64 42 随机生成密码字符串并填入 SECRET_KEY 参数
  • 您是否修改了 Dify 使用的域名?
    • 将占位符域名 dify.pigsty 替换为您的实际域名,例如 dify.pigsty.cc
    • 您可以使用 sed -ie 's/dify.pigsty/dify.pigsty.cc/g' pigsty.yml 修改 Dify 的域名

域名和 SSL

如果您想使用带有 HTTPS 证书的真实域名,需要在 pigsty.yml 配置文件中修改:

  • infra_portal 参数的 dify 域名
  • 最好指定一个邮箱地址 certbot_email 用于接收证书过期通知
  • 配置 Dify 的 NGINX_SERVER_NAME 参数来指定您的实际域名
all:
  children:                            # 集群定义
    dify:                              # Dify 组
      vars:                            # Dify 组变量
        apps:                          # 应用程序配置
          dify:                        # Dify 应用程序定义
            conf:                      # Dify 应用程序配置
              NGINX_SERVER_NAME: dify.pigsty

  vars:                                # 全局参数
    #certbot_sign: true                # 使用 Certbot 申请免费 HTTPS 证书
    certbot_email: your@email.com      # 证书申请邮箱,用于过期通知,可选
    infra_portal:                      # 配置 Nginx 服务器
      dify:                            # Dify 服务器定义
        domain: dify.pigsty            # 请在此处替换为您自己的域名!
        endpoint: "10.10.10.10:5001"   # 请在此处指定 Dify 的 IP 和端口(默认自动配置)
        websocket: true                # Dify 需要启用 websocket
        certbot: dify.pigsty           # 指定 Certbot 证书名称

使用以下命令申请 Nginx 证书:

# 申请证书,也可以手动执行 /etc/nginx/sign-cert 脚本
make cert

# 上述 Makefile 快捷命令实际执行以下剧本任务:
./infra.yml -t nginx_certbot,nginx_reload -e certbot_sign=true

执行 app.yml 剧本重新部署 Dify 服务以使 NGINX_SERVER_NAME 配置生效。

./app.yml

文件备份

您可以使用 restic 备份 Dify 的文件存储(默认位于 /data/dify 目录),使用以下命令进行备份:

export RESTIC_REPOSITORY=/data/backups/dify   # 指定 dify 备份目录
export RESTIC_PASSWORD=some-strong-password   # 指定备份加密密码
mkdir -p ${RESTIC_REPOSITORY}                 # 创建 dify 备份目录
restic init

创建 Restic 备份仓库后,您可以使用以下命令备份 Dify:

export RESTIC_REPOSITORY=/data/backups/dify   # 指定 dify 备份目录
export RESTIC_PASSWORD=some-strong-password   # 指定备份加密密码

restic backup /data/dify                      # 将 /dify 数据目录备份到仓库
restic snapshots                              # 查看备份快照列表
restic restore -t /data/dify 0b11f778         # 将快照 xxxxxx 恢复到 /data/dify
restic check                                  # 定期检查仓库完整性

另一种更可靠的方法是使用 JuiceFS 将 MinIO 对象存储挂载到 /data/dify 目录,这样您就可以使用 MinIO/S3 存储文件状态。

如果您想将所有数据存储在 PostgreSQL 中,请考虑"使用 JuiceFS 将文件系统数据存储在 PostgreSQL 中"

例如,您可以创建另一个 dify_fs 数据库并将其用作 JuiceFS 的元数据存储:

METAURL=postgres://dify:difyai123456@:5432/dify_fs
OPTIONS=(
  --storage postgres
  --bucket :5432/dify_fs
  --access-key dify
  --secret-key difyai123456
  ${METAURL}
  jfs
)
juicefs format "${OPTIONS[@]}"         # 创建 PG 文件系统
juicefs mount ${METAURL} /data/dify -d # 后台挂载到 /data/dify 目录
juicefs bench /data/dify               # 测试性能
juicefs umount /data/dify              # 停止挂载

参考

Dify 自托管常见问题

4 - 业务软件

企业级开源软件模板

5 - NocoDB:开源 Airtable

使用 NocoDB 将 PostgreSQL 数据库转变为智能电子表格,无代码数据库应用平台。

NocoDB 是一个开源的 Airtable 替代方案,可以将任何数据库转变为智能电子表格。

它提供了丰富的用户界面,让您无需编写代码即可创建强大的数据库应用。NocoDB 支持 PostgreSQL、MySQL、SQL Server 等多种数据库,是构建内部工具和数据管理系统的理想选择。

快速开始

在 Pigsty 软件模板目录中提供了 NocoDB 的 Docker Compose 配置文件:

cd ~/pigsty/app/nocodb

检查并修改 .env 配置文件(根据需要调整数据库连接等配置)。

启动服务:

make up     # 使用 Docker Compose 启动 NocoDB

访问 NocoDB:

  • 默认地址: http://nocodb.pigsty
  • 备用地址: http://10.10.10.10:8080
  • 首次访问需要创建管理员账户

管理命令

Pigsty 提供了便捷的 Makefile 命令来管理 NocoDB 服务:

make up      # 启动 NocoDB 服务
make run     # 使用 Docker 启动(连接外部 PostgreSQL)
make view    # 显示 NocoDB 访问地址
make log     # 查看容器日志
make info    # 查看服务详细信息
make stop    # 停止服务
make clean   # 停止并移除容器
make pull    # 拉取最新镜像
make rmi     # 移除 NocoDB 镜像
make save    # 保存镜像到 /tmp/nocodb.tgz
make load    # 从 /tmp/nocodb.tgz 加载镜像

连接 PostgreSQL

NocoDB 可以连接到 Pigsty 管理的 PostgreSQL 数据库。

在 NocoDB 界面中添加新项目时,选择「External Database」,然后输入 PostgreSQL 连接信息:

主机:10.10.10.10
端口:5432
数据库名:your_database
用户名:your_username
密码:your_password
SSL:禁用(或根据实际情况启用)

连接成功后,NocoDB 会自动读取数据库的表结构,您可以通过可视化界面进行数据管理。

功能特性

  • 智能电子表格界面:类似 Excel/Airtable 的用户体验
  • 多种视图:网格、表单、看板、日历、画廊视图
  • 协作功能:团队协作、权限管理、评论
  • API 支持:自动生成 REST API
  • 集成能力:支持 Webhook、Zapier 等集成
  • 数据导入导出:支持 CSV、Excel 等格式
  • 公式和验证:支持复杂的数据计算和验证规则

配置说明

NocoDB 的配置在 .env 文件中:

# 数据库连接(NocoDB 元数据存储)
NC_DB=pg://postgres:DBUser.Postgres@10.10.10.10:5432/nocodb

# JWT 密钥(建议修改)
NC_AUTH_JWT_SECRET=your-secret-key

# 其他配置
NC_PUBLIC_URL=http://nocodb.pigsty
NC_DISABLE_TELE=true

数据持久化

NocoDB 的元数据默认存储在外部 PostgreSQL 数据库中,应用数据也可以存储在 PostgreSQL 中。

如果使用本地存储,数据会保存在 /data/nocodb 目录中。

安全建议

  1. 修改默认密钥:在 .env 文件中修改 NC_AUTH_JWT_SECRET
  2. 使用强密码:为管理员账户设置强密码
  3. 配置 HTTPS:生产环境建议启用 HTTPS
  4. 限制访问:通过防火墙或 Nginx 限制访问权限
  5. 定期备份:定期备份 NocoDB 元数据库

相关链接

6 - Teable:AI 无代码数据库

使用 Teable 构建 AI 驱动的无代码数据库应用,提升团队生产力。

Teable 是一个 AI 驱动的无代码数据库平台,专为团队协作和自动化而设计。

Teable 将数据库的强大功能与电子表格的易用性完美结合,并集成 AI 能力,帮助团队高效地生成、自动化和协作处理数据。

快速开始

Teable 需要完整的 Pigsty 环境支持(包括 PostgreSQL、Redis、MinIO)。

准备环境

cd ~/pigsty
./bootstrap                # 准备本地源与 Ansible
./configure -c app/teable  # 重要:修改默认凭据!
./deploy.yml               # 安装 Pigsty、PostgreSQL、MinIO
./redis.yml                # 安装 Redis 实例
./docker.yml               # 安装 Docker 与 Docker Compose
./app.yml                  # 使用 Docker Compose 安装 Teable

访问服务

  • 默认地址: http://teable.pigsty
  • 备用地址: http://10.10.10.10:3000
  • 首次访问需要注册管理员账户

管理命令

在 Pigsty 软件模板目录中管理 Teable:

cd ~/pigsty/app/teable

make up      # 启动 Teable 服务
make down    # 停止 Teable 服务
make log     # 查看容器日志
make clean   # 清理容器和数据

架构说明

Teable 依赖以下组件:

  • PostgreSQL:存储应用数据和元数据
  • Redis:缓存和会话管理
  • MinIO:对象存储(文件、图片等)
  • Docker:容器运行环境

确保这些服务在部署 Teable 前已正确安装。

功能特性

  • AI 集成:内置 AI 助手,自动生成数据、公式和工作流
  • 智能表格:强大的表格功能,支持多种字段类型
  • 自动化工作流:无代码自动化,提升团队效率
  • 多视图支持:网格、表单、看板、日历等多种视图
  • 团队协作:实时协作、权限管理、评论
  • API 和集成:自动生成 API,支持 Webhook 集成
  • 模板库:丰富的应用模板,快速启动项目

配置说明

Teable 的配置通过环境变量管理,主要配置在 docker-compose.yml 中:

# PostgreSQL 连接
POSTGRES_HOST=10.10.10.10
POSTGRES_PORT=5432
POSTGRES_DB=teable
POSTGRES_USER=dbuser_teable
POSTGRES_PASSWORD=DBUser.Teable

# Redis 连接
REDIS_HOST=10.10.10.10
REDIS_PORT=6379
REDIS_DB=0

# MinIO 连接
MINIO_ENDPOINT=http://10.10.10.10:9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin

# 应用配置
BACKEND_URL=http://teable.pigsty
PUBLIC_ORIGIN=http://teable.pigsty

重要:在生产环境中,请修改所有默认密码和密钥!

数据持久化

Teable 的数据持久化依赖:

  • PostgreSQL:所有结构化数据存储在 PostgreSQL 中
  • MinIO:文件、图片等非结构化数据存储在 MinIO 中
  • Redis:缓存数据(可选持久化)

定期备份 PostgreSQL 数据库和 MinIO 存储桶以确保数据安全。

安全建议

  1. 修改默认凭据:在配置文件中修改所有默认用户名和密码
  2. 启用 HTTPS:生产环境建议配置 SSL 证书
  3. 配置防火墙:限制对服务的访问
  4. 定期备份:定期备份 PostgreSQL 和 MinIO 数据
  5. 更新组件:及时更新 Teable 和依赖组件的版本

相关链接

7 - Gitea:自建简易代码托管平台

使用Docker拉起Gitea,并使用Pigsty的PG作为外部的元数据库

公开Demo地址:http://git.pigsty.cc

太长;不看

cd ~/pigsty/app/gitea; make up

在本例中,Gitea 默认使用 8889 端口,您可以访问以下位置:

http://git.pigsty 或 http://10.10.10.10:8889

make up      # pull up gitea with docker-compose in minimal mode
make run     # launch gitea with docker , local data dir and external PostgreSQL
make view    # print gitea access point
make log     # tail -f gitea logs
make info    # introspect gitea with jq
make stop    # stop gitea container
make clean   # remove gitea container
make pull    # pull latest gitea image
make rmi     # remove gitea image
make save    # save gitea image to /tmp/gitea.tgz
make load    # load gitea image from /tmp

使用外部的PostgreSQL

Pigsty默认使用容器内的 Sqlite 作为元数据存储,您可以让 Gitea 通过连接串环境变量使用外部的PostgreSQL

# postgres://dbuser_gitea:DBUser.gitea@10.10.10.10:5432/gitea
db:   { name: gitea, owner: dbuser_gitea, comment: gitea primary database }
user: { name: dbuser_gitea , password: DBUser.gitea, roles: [ dbrole_admin ] }

8 - Wiki.js:维基百科站

如何使用 Wiki.js 搭建你自己的开源维基百科,并使用 Pigsty 管理的PG作为持久数据存储

公开Demo地址:http://wiki.pigsty.cc

太长;不看

cd app/wiki ; docker-compose up -d

准备数据库

# postgres://dbuser_wiki:DBUser.Wiki@10.10.10.10:5432/wiki
- { name: wiki, owner: dbuser_wiki, revokeconn: true , comment: wiki the api gateway database }
- { name: dbuser_wiki, password: DBUser.Wiki , pgbouncer: true , roles: [ dbrole_admin ] }
bin/createuser pg-meta dbuser_wiki
bin/createdb   pg-meta wiki

容器配置

version: "3"
services:
  wiki:
    container_name: wiki
    image: requarks/wiki:2
    environment:
      DB_TYPE: postgres
      DB_HOST: 10.10.10.10
      DB_PORT: 5432
      DB_USER: dbuser_wiki
      DB_PASS: DBUser.Wiki
      DB_NAME: wiki
    restart: unless-stopped
    ports:
      - "9002:3000"

Access

  • Default Port for wiki: 9002
# add to nginx_upstream
- { name: wiki  , domain: wiki.pigsty.cc , endpoint: "127.0.0.1:9002"   }
./infra.yml -t nginx_config
ansible all -b -a 'nginx -s reload'

9 - Mattermost:开源 IM

使用 Mattermost 构建私有化的团队协作平台,开源的 Slack 替代方案。

Mattermost 是一个开源的团队协作和消息平台。

Mattermost 提供即时消息、文件共享、音视频通话等功能,是 Slack 和 Microsoft Teams 的开源替代方案,特别适合需要私有化部署的企业。

快速开始

cd ~/pigsty/app/mattermost
make up     # 使用 Docker Compose 启动 Mattermost

访问地址: http://mattermost.pigsty 或 http://10.10.10.10:8065

首次访问需要创建管理员账户。

功能特性

  • 即时消息:个人和群组聊天
  • 频道管理:公开和私有频道
  • 文件共享:安全的文件存储和共享
  • 音视频通话:内置通话功能
  • 集成能力:支持 Webhook、Bot、插件
  • 移动应用:iOS 和 Android 客户端
  • 企业级:SSO、LDAP、合规性功能

连接 PostgreSQL

Mattermost 使用 PostgreSQL 存储数据,在配置中指定连接信息:

MM_SQLSETTINGS_DRIVERNAME=postgres
MM_SQLSETTINGS_DATASOURCE=postgres://dbuser_mm:DBUser.MM@10.10.10.10:5432/mattermost

相关链接

10 - Maybe:个人财务管理

使用 Maybe 管理个人财务,开源的 Mint/Personal Capital 替代方案。

Maybe 是一个开源的个人财务管理应用。

Maybe 提供财务跟踪、预算管理、投资分析等功能,是 Mint 和 Personal Capital 的开源替代方案,让您完全掌控自己的财务数据。

快速开始

cd ~/pigsty/app/maybe
cp .env.example .env
vim .env                    # 必须修改 SECRET_KEY_BASE
make up                      # 启动 Maybe 服务

访问地址: http://maybe.pigsty 或 http://10.10.10.10:5002

配置说明

.env 文件中配置:

SECRET_KEY_BASE=your-secret-key-here    # 必须修改!
DATABASE_URL=postgresql://...

重要:首次部署前必须修改 SECRET_KEY_BASE

功能特性

  • 账户管理:追踪多个银行账户和信用卡
  • 预算规划:设置和跟踪预算
  • 投资分析:监控投资组合表现
  • 账单提醒:自动提醒即将到期的账单
  • 隐私优先:数据完全在您的控制之下

相关链接

11 - Metabase:BI 分析工具

使用 Metabase 进行快速的商业智能分析,友好的用户界面让团队自主探索数据。

Metabase 是一个快速、易用的开源商业智能工具,让您的团队无需 SQL 知识即可探索和可视化数据。

Metabase 提供友好的用户界面和丰富的图表类型,支持连接多种数据库,是企业数据分析的理想选择。

快速开始

在 Pigsty 软件模板目录中提供了 Metabase 的 Docker Compose 配置文件:

cd ~/pigsty/app/metabase

检查并修改 .env 配置文件:

vim .env    # 检查配置,建议修改默认凭据

启动服务:

make up     # 使用 Docker Compose 启动 Metabase

访问 Metabase:

  • 默认地址: http://metabase.pigsty
  • 备用地址: http://10.10.10.10:3001
  • 首次访问需要完成初始化设置

管理命令

Pigsty 提供了便捷的 Makefile 命令来管理 Metabase 服务:

make up      # 启动 Metabase 服务
make run     # 使用 Docker 启动(连接外部 PostgreSQL)
make view    # 显示 Metabase 访问地址
make log     # 查看容器日志
make info    # 查看服务详细信息
make stop    # 停止服务
make clean   # 停止并移除容器
make pull    # 拉取最新镜像
make rmi     # 移除 Metabase 镜像
make save    # 保存镜像到文件
make load    # 从文件加载镜像

连接 PostgreSQL

Metabase 可以连接到 Pigsty 管理的 PostgreSQL 数据库。

在 Metabase 初始化或添加数据库时,选择「PostgreSQL」,然后输入连接信息:

数据库类型:PostgreSQL
名称:自定义名称(如 "生产数据库")
主机:10.10.10.10
端口:5432
数据库名:your_database
用户名:dbuser_meta
密码:DBUser.Meta

连接成功后,Metabase 会自动扫描数据库结构,您可以开始创建问题和仪表板。

功能特性

  • 无需 SQL:通过可视化界面构建查询
  • 丰富的图表类型:折线图、柱状图、饼图、地图等
  • 交互式仪表板:创建美观的数据仪表板
  • 自动刷新:定时更新数据和仪表板
  • 权限管理:精细的用户和数据访问控制
  • SQL 模式:高级用户可以直接编写 SQL
  • 嵌入功能:将图表嵌入到其他应用
  • 告警功能:数据变化自动通知

配置说明

Metabase 的配置在 .env 文件中:

# Metabase 元数据库(建议使用 PostgreSQL)
MB_DB_TYPE=postgres
MB_DB_DBNAME=metabase
MB_DB_PORT=5432
MB_DB_USER=dbuser_metabase
MB_DB_PASS=DBUser.Metabase
MB_DB_HOST=10.10.10.10

# 应用配置
JAVA_OPTS=-Xmx2g

建议:为 Metabase 使用独立的 PostgreSQL 数据库存储元数据。

数据持久化

Metabase 的元数据(用户、问题、仪表板等)存储在配置的数据库中。

如果使用 H2 数据库(默认),数据会保存在 /data/metabase 目录。强烈建议在生产环境中使用 PostgreSQL 作为元数据库。

性能优化

  • 使用 PostgreSQL:替代默认的 H2 数据库
  • 增加内存:通过 JAVA_OPTS=-Xmx4g 增加 JVM 内存
  • 数据库索引:为常查询的字段创建索引
  • 结果缓存:启用 Metabase 的查询结果缓存
  • 定时更新:合理设置仪表板的自动刷新频率

安全建议

  1. 修改默认凭据:修改元数据库的用户名和密码
  2. 启用 HTTPS:生产环境配置 SSL 证书
  3. 配置认证:启用 SSO 或 LDAP 认证
  4. 限制访问:通过防火墙限制访问
  5. 定期备份:备份 Metabase 元数据库

相关链接

12 - Kong:API 网关

拉起基于 Nginx 与 OpenResty 的强力开源 API 网关,并使用 PostgreSQL 与 Redis 作为其后端状态存储

TL;DR

cd app/kong ; docker-compose up -d
make up         # pull up kong with docker-compose
make ui         # run swagger ui container
make log        # tail -f kong logs
make info       # introspect kong with jq
make stop       # stop kong container
make clean      # remove kong container
make rmui       # remove swagger ui container
make pull       # pull latest kong image
make rmi        # remove kong image
make save       # save kong image to /tmp/kong.tgz
make load       # load kong image from /tmp

Scripts

  • Default Port: 8000
  • Default SSL Port: 8443
  • Default Admin Port: 8001
  • Default Postgres Database: postgres://dbuser_kong:DBUser.Kong@10.10.10.10:5432/kong
# postgres://dbuser_kong:DBUser.Kong@10.10.10.10:5432/kong
- { name: kong, owner: dbuser_kong, revokeconn: true , comment: kong the api gateway database }
- { name: dbuser_kong, password: DBUser.Kong , pgbouncer: true , roles: [ dbrole_admin ] }

13 - Registry:容器镜像仓库

部署 Docker Registry 镜像服务,加速 Docker 镜像拉取,特别适合中国用户。

Docker Registry 镜像服务用于缓存 Docker Hub 和其他镜像仓库的镜像。

特别适合中国用户或访问 Docker Hub 速度较慢的地区,显著减少镜像拉取时间。

快速开始

cd ~/pigsty/app/registry
make up     # 启动 Registry 镜像服务

访问地址: http://registry.pigsty 或 http://10.10.10.10:5000

功能特性

  • 镜像缓存:缓存 Docker Hub 和其他仓库的镜像
  • Web 界面:可选的镜像管理界面
  • 高性能:本地缓存大幅提升拉取速度
  • 存储管理:可配置的清理和管理策略
  • 健康检查:内置健康检查端点

配置 Docker

配置 Docker 使用本地镜像:

# 编辑 /etc/docker/daemon.json
{
  "registry-mirrors": ["http://10.10.10.10:5000"]
}

# 重启 Docker
systemctl restart docker

存储管理

镜像数据存储在 /data/registry 目录,建议预留至少 100GB 空间。

相关链接

14 - 数据库工具

数据库管理与开发工具

15 - ByteBase:模式迁移

使用Docker拉起Bytebase,对PG的模式进行版本化管理

ByteBase

ByteBase是一个进行数据库模式变更的工具,以下命令将在元节点 8887 端口启动一个ByteBase。

mkdir -p /data/bytebase/data;
docker run --init --name bytebase --restart always --detach --publish 8887:8887 --volume /data/bytebase/data:/var/opt/bytebase \
    bytebase/bytebase:1.0.4 --data /var/opt/bytebase --host http://ddl.pigsty --port 8887

访问 http://10.10.10.10:8887/ 或 http://ddl.pigsty 即可使用 ByteBase,您需要依次创建项目、环境、实例、数据库,即可开始进行模式变更。 公开Demo地址: http://ddl.pigsty.cc

公开Demo地址:http://ddl.pigsty.cc

默认用户名与密码: admin / pigsty

Bytebase概览

Schema Migrator for PostgreSQL

cd app/bytebase; make up

Visit http://ddl.pigsty or http://10.10.10.10:8887

make up         # pull up bytebase with docker-compose in minimal mode
make run        # launch bytebase with docker , local data dir and external PostgreSQL
make view       # print bytebase access point
make log        # tail -f bytebase logs
make info       # introspect bytebase with jq
make stop       # stop bytebase container
make clean      # remove bytebase container
make pull       # pull latest bytebase image
make rmi        # remove bytebase image
make save       # save bytebase image to /tmp/bytebase.tgz
make load       # load bytebase image from /tmp

使用外部的PostgreSQL

Bytebase use its internal PostgreSQL database by default, You can use external PostgreSQL for higher durability.

# postgres://dbuser_bytebase:DBUser.Bytebase@10.10.10.10:5432/bytebase
db:   { name: bytebase, owner: dbuser_bytebase, comment: bytebase primary database }
user: { name: dbuser_bytebase , password: DBUser.Bytebase, roles: [ dbrole_admin ] }

if you wish to user an external PostgreSQL, drop monitor extensions and views & pg_repack

DROP SCHEMA monitor CASCADE;
DROP EXTENSION pg_repack;

After bytebase initialized, you can create them back with /pg/tmp/pg-init-template.sql

psql bytebase < /pg/tmp/pg-init-template.sql

16 - PGAdmin:GUI 工具

使用Docker拉起PgAdmin4,并加载Pigsty服务器列表

pgAdmin 是最受欢迎且功能丰富的 PostgreSQL 开源管理和开发平台,PostgreSQL 是世界上最先进的开源数据库。


快速开始

Pigsty 内置(但可选)支持 pgAdmin,它使用 Docker Compose 启动 pgadmin:

./docker.yml
./app.yml -e app=pgadmin

pgadmin 的默认端口是 8885,您可以通过 IP:端口访问它:http://10.10.10.10:8885

默认凭据在 .env 中定义,用户名:admin@pigsty.cc,密码:pigsty


自定义

/opt/pgadmin/.env 中自定义 pgadmin 配置并使用 docker compose 管理它。

您还可以自定义 apps 参数并使用以下方式覆盖默认 .env 配置:

all:
  children:

    infra:
      hosts:
        10.10.10.10: { infra_seq: 1 }
      vars:
        docker_enabled: true
        app: pgadmin  # 指定要安装的应用程序名称(pgadmin)(在 apps 中)
        apps:         # 定义所有应用程序
          pgadmin:    # pgadmin 应用程序的定义
            conf:     # 覆盖 /opt/pgadmin/.env

              PGADMIN_DEFAULT_EMAIL: your@email.com
              PGADMIN_DEFAULT_PASSWORD: yourPassword

              PGADMIN_LISTEN_ADDRESS: 0.0.0.0
              PGADMIN_PORT: 8885
              PGADMIN_SERVER_JSON_FILE: /pgadmin4/servers.json
              PGADMIN_REPLACE_SERVERS_ON_STARTUP: true

要启动应用程序,运行:

./app.yml -l infra

域名和证书

要通过 nginx(而不是直接访问端口 8885)访问 pgadmin,请使用以下方式配置 基础设施门户

all:
  vars:
    infra_portal:
      home         : { domain: h.pigsty }
      grafana      : { domain: g.pigsty ,endpoint: "${admin_ip}:3000" , websocket: true }
      prometheus   : { domain: p.pigsty ,endpoint: "${admin_ip}:9058" }
      alertmanager : { domain: a.pigsty ,endpoint: "${admin_ip}:9059" }
      blackbox     : { endpoint: "${admin_ip}:9115" }
      loki         : { endpoint: "${admin_ip}:3100" }

      # 在此处添加 pgadmin 上游服务器定义
      pgadmin      : { domain: adm.pigsty  ,endpoint: "127.0.0.1:8885" }

然后运行 make nginx 更新 nginx 配置,并在 /etc/hosts本地 / 公共 DNS 服务器中配置 本地静态 DNS 记录 <your_ip_address> adm.pigsty

Pigsty 将自动为 infra_portal 中列出的域名签发自签名 SSL 证书。 如果您想使用真实域名,请定义 certbot 条目并运行 make cert,查看 SSL 证书 了解详情。

all:
  vars:        # 确保您的域名(adm.pigsty.cc)解析到您的公网 IP
    certbot_sign: true   # 使用 certbot 签发真实 HTTPS 证书(需要互联网访问!)
    infra_portal:
      pgadmin : { domain: adm.pigsty.cc  ,endpoint: "127.0.0.1:8885", certbot: adm.pigsty.cc }

使用方法

Pigsty 的 Pgadmin 应用模板默认使用 8885 端口,您可以通过以下地址访问:

http://adm.pigsty 或 http://10.10.10.10:8885

默认用户名与密码: admin@pigsty.cc / pigsty

make up         # 使用 docker compose 启动 pgadmin
make run        # 使用 docker 启动 pgadmin
make view       # 打印 pgadmin 访问点
make log        # tail -f pgadmin 日志
make info       # 使用 jq 检查 pgadmin
make stop       # 停止 pgadmin 容器
make clean      # 移除 pgadmin 容器
make conf       # 使用 pigsty pg 服务器列表配置 pgadmin
make dump       # 从 pgadmin 容器导出 servers.json
make pull       # 拉取最新的 pgadmin 镜像
make rmi        # 移除 pgadmin 镜像
make save       # 保存 pgadmin 镜像到 /tmp/pgadmin.tgz
make load       # 从 /tmp 加载 pgadmin 镜像

Demo

公开 Demo 地址:http://adm.pigsty.cc

默认用户名与密码: admin@pigsty.cc / pigsty

17 - PGWeb:网页客户端

使用Docker拉起PGWEB,以便从浏览器进行小批量在线数据查询

PGWeb客户端工具

PGWeb是一款基于浏览器的PG客户端工具,使用以下命令,在元节点上拉起PGWEB服务,默认为主机8886端口。可使用域名: http://cli.pigsty 访问,公开Demo:http://cli.pigsty.cc。

# docker stop pgweb; docker rm pgweb
docker run --init --name pgweb --restart always --detach --publish 8886:8081 sosedoff/pgweb

用户需要自行填写数据库连接串,例如默认CMDB的连接串:

postgres://dbuser_dba:DBUser.DBA@10.10.10.10:5432/meta?sslmode=disable

公开Demo地址:http://cli.pigsty.cc

使用Docker Compose拉起PGWEB容器:

cd ~/pigsty/app/pgweb ; docker-compose up -d

接下来,访问您本机的 8886 端口,即可看到 PGWEB 的UI界面: http://10.10.10.10:8886

您可以尝试使用下面的URL连接串,通过 PGWEB 连接至数据库实例并进行探索。

postgres://dbuser_meta:DBUser.Meta@10.10.10.10:5432/meta?sslmode=disable
postgres://test:test@10.10.10.11:5432/test?sslmode=disable

快捷方式

make up         # pull up pgweb with docker-compose
make run        # launch pgweb with docker
make view       # print pgweb access point
make log        # tail -f pgweb logs
make info       # introspect pgweb with jq
make stop       # stop pgweb container
make clean      # remove pgweb container
make pull       # pull latest pgweb image
make rmi        # remove pgweb image
make save       # save pgweb image to /tmp/pgweb.tgz
make load       # load pgweb image from /tmp

18 - PostgREST:自动 API

使用Docker拉起PostgREST,自动根据PostgreSQL模式生成后端REST API

PostgREST

PostgREST是一个自动根据 PostgreSQL 数据库模式生成 REST API的二进制组件。

例如,以下命令将使用docker拉起 postgrest (本地 8884 端口,使用默认管理员用户,暴露Pigsty CMDB模式)

docker run --init --name postgrest --restart always --detach --publish 8884:8081 postgrest/postgrest

访问 http://10.10.10.10:8884 会展示所有自动生成API的定义,并自动使用 Swagger Editor 暴露API文档。

如果您想要进行增删改查,设计更精细的权限控制,请参考 Tutorial 1 - The Golden Key,生成一个签名JWT。

This is an example of creating pigsty cmdb API with PostgREST

cd ~/pigsty/app/postgrest ; docker-compose up -d

http://10.10.10.10:8884 is the default endpoint for PostgREST

http://10.10.10.10:8883 is the default api docs for PostgREST

make up         # pull up postgrest with docker-compose
make run        # launch postgrest with docker
make ui         # run swagger ui container
make view       # print postgrest access point
make log        # tail -f postgrest logs
make info       # introspect postgrest with jq
make stop       # stop postgrest container
make clean      # remove postgrest container
make rmui       # remove swagger ui container
make pull       # pull latest postgrest image
make rmi        # remove postgrest image
make save       # save postgrest image to /tmp/postgrest.tgz
make load       # load postgrest image from /tmp

Swagger UI

Launch a swagger OpenAPI UI and visualize PostgREST API on 8883 with:

docker run --init --name postgrest --name swagger -p 8883:8080 -e API_URL=http://10.10.10.10:8884 swaggerapi/swagger-ui
# docker run -d -e API_URL=http://10.10.10.10:8884 -p 8883:8080 swaggerapi/swagger-editor # swagger editor

Check http://10.10.10.10:8883/

19 - Electric:PGLite 同步引擎

使用 Electric 解决 PostgreSQL 数据同步难题,支持部分复制和实时数据传输。

Electric 是一个 PostgreSQL 同步引擎,解决了数据同步的复杂问题。

Electric 支持部分复制、扇出传输和高效的数据交付,是构建实时应用和离线优先应用的理想选择。

快速开始

cd ~/pigsty/app/electric
make up     # 启动 Electric 服务

访问地址: http://electric.pigsty 或 http://10.10.10.10:3000

功能特性

  • 部分复制:只同步需要的数据
  • 实时同步:毫秒级数据更新
  • 离线优先:支持离线工作,自动同步
  • 冲突解决:自动处理数据冲突
  • 类型安全:TypeScript 支持

相关链接

20 - Jupyter:笔记本 AI IDE

使用 Jupyter Lab 并访问 PostgreSQL 数据库,组合使用 SQL 与 Python 的能力进行数据分析。

Jupyter Lab 是基于 IPython Notebook 的完整数据科学研发环境,可用于数据分析与可视化。

Pigsty 提供了 Docker Compose 模板,可以一键在容器中启动 Jupyter Lab 服务,并方便地访问 PostgreSQL 数据库。

快速开始

在 Pigsty 软件模板目录中提供了 Jupyter 的 Docker Compose 配置文件:

cd ~/pigsty/app/jupyter

修改默认密码,编辑 .env 文件中的 JUPYTER_TOKEN 参数(默认值为 pigsty)。

创建数据目录并启动服务:

make dir    # 创建 /data/jupyter 目录并设置权限
make up     # 使用 Docker Compose 启动服务

访问 Jupyter Lab:

  • 默认地址: http://lab.pigsty
  • 备用地址: http://10.10.10.10:8888
  • 默认 Token:pigsty

管理命令

Pigsty 提供了便捷的 Makefile 命令来管理 Jupyter 服务:

make up      # 启动 Jupyter Lab 服务
make dir     # 创建 /data/jupyter 数据目录
make log     # 查看容器日志
make info    # 显示服务信息
make stop    # 停止服务
make clean   # 停止并移除容器
make pull    # 拉取最新镜像
make save    # 保存 Docker 镜像到文件
make load    # 从文件加载 Docker 镜像

访问 PostgreSQL 数据库

在 Jupyter Lab 中访问 PostgreSQL 数据库需要先安装驱动。

在 Jupyter Lab 的 Terminal 中执行:

pip install psycopg2-binary psycopg2

然后在 Notebook 中使用 psycopg2 驱动访问 PostgreSQL:

import psycopg2

# 连接到 PostgreSQL 数据库
conn = psycopg2.connect('postgres://dbuser_meta:DBUser.Meta@10.10.10.10:5432/meta')

# 执行查询
cursor = conn.cursor()
cursor.execute("SELECT date, new_cases FROM covid.country_history WHERE country_code = 'CN';")
data = cursor.fetchall()

# 处理数据
for row in data:
    print(row)

你也可以使用其他 Python 数据分析库,如 Pandas、SQLAlchemy 等:

import pandas as pd
from sqlalchemy import create_engine

# 使用 SQLAlchemy 连接
engine = create_engine('postgresql://dbuser_meta:DBUser.Meta@10.10.10.10:5432/meta')

# 使用 Pandas 读取数据
df = pd.read_sql("SELECT * FROM covid.country_history WHERE country_code = 'CN'", engine)
print(df.head())

配置说明

Jupyter 服务的配置在 .env 文件中:

JUPYTER_TOKEN=pigsty    # Jupyter Lab 访问 Token(密码)

如果需要修改端口或其他配置,可以编辑 docker-compose.yml 文件:

services:
  jupyter:
    image: jupyter/scipy-notebook:latest
    ports:
      - "8888:8888"
    volumes:
      - /data/jupyter:/home/jovyan/work
    environment:
      - JUPYTER_TOKEN=${JUPYTER_TOKEN}

安装额外的 Python 包

Jupyter 容器支持使用 pipconda 安装 Python 包。

在 Jupyter Lab 的 Terminal 中执行:

# 使用 pip 安装
pip install numpy pandas matplotlib seaborn scikit-learn

# 使用 conda 安装
conda install -c conda-forge geopandas

# 使用国内镜像加速(可选)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy

数据持久化

Jupyter 的数据存储在 /data/jupyter 目录中,该目录会被挂载到容器的 /home/jovyan/work 路径。

所有保存在 work 目录下的 Notebook 和数据文件都会持久化保存在宿主机上,即使容器重启或删除也不会丢失。

安全建议

强烈建议修改默认的 Token(密码)!

  1. 编辑 .env 文件,修改 JUPYTER_TOKEN 的值
  2. 重启服务:make up

如果在生产环境中使用 Jupyter Lab,还应该:

  • 使用强密码或禁用 Token 认证
  • 配置 HTTPS 访问
  • 限制网络访问权限
  • 定期备份数据目录

相关链接

21 - 数据应用

基于 PostgreSQL 的数据可视化应用

22 - PGLOG:PG自带日志分析应用

Pigsty自带的,用于分析PostgreSQL CSV日志样本的一个样例Applet

PGLOG是Pigsty自带的一个样例应用,固定使用MetaDB中pglog.sample表作为数据来源。您只需要将日志灌入该表,然后访问相关Dashboard即可。

Pigsty提供了一些趁手的命令,用于拉取csv日志,并灌入样本表中。在元节点上,默认提供下列快捷命令:

catlog  [node=localhost]  [date=today]   # 打印CSV日志到标准输出
pglog                                    # 从标准输入灌入CSVLOG
pglog12                                  # 灌入PG12格式的CSVLOG
pglog13                                  # 灌入PG13格式的CSVLOG
pglog14                                  # 灌入PG14格式的CSVLOG (=pglog)

catlog | pglog                       # 分析当前节点当日的日志
catlog node-1 '2021-07-15' | pglog   # 分析node-1在2021-07-15的csvlog

接下来,您可以访问以下的连接,查看样例日志分析界面。

  • PGLOG Overview: 呈现整份CSV日志样本详情,按多种维度聚合。

  • PGLOG Session: 呈现日志样本中一条具体连接的详细信息。

catlog命令从特定节点拉取特定日期的CSV数据库日志,写入stdout

默认情况下,catlog会拉取当前节点当日的日志,您可以通过参数指定节点与日期。

组合使用pglogcatlog,即可快速拉取数据库CSV日志进行分析。

catlog | pglog                       # 分析当前节点当日的日志
catlog node-1 '2021-07-15' | pglog   # 分析node-1在2021-07-15的csvlog

23 - NOAA ISD 全球气象站历史数据查询

以ISD数据集为例,展现如何将数据导入数据库中

如果您拥有数据库后不知道干点什么,不妨参试试这个开源项目:Vonng/isd

您可以直接复用监控系统Grafana,以交互式的方式查阅近30000个地面气象站过去120年间的亚小时级气象数据。

这是一个功能完成的数据应用,可以查询全球30000个地表气象站从1901年来的气象观测记录。

项目地址:https://github.com/Vonng/isd

在线Demo地址:https://demo.pigsty.cc/d/isd-overview

isd-overview.jpg

快速上手

克隆本仓库

git clone https://github.com/Vonng/isd.git; cd isd;

准备一个 PostgreSQL 实例

该 PostgreSQL 实例应当启用了 PostGIS 扩展。使用 PGURL 环境变量传递数据库连接信息:

# Pigsty 默认使用的管理员账号是 dbuser_dba,密码是 DBUser.DBA
export PGURL=postgres://dbuser_dba:DBUser.DBA@127.0.0.1:5432/meta?sslmode=disable
psql "${PGURL}" -c 'SELECT 1'  # 检查连接是否可用

获取并导入ISD气象站元数据

这是一份每日更新的气象站元数据,包含了气象站的经纬度、海拔、名称、国家、省份等信息,使用以下命令下载并导入。

make reload-station   # 相当于先下载最新的Station数据再加载:get-station + load-station

获取并导入最新的 isd.daily 数据

isd.daily 是一个每日更新的数据集,包含了全球各气象站的日观测数据摘要,使用以下命令下载并导入。 请注意,直接从 NOAA 网站下载的原始数据需要经过解析方可入库,所以你需要下载或构建一个 ISD 数据 Parser。

make get-parser       # 从 Github 下载 Parser 二进制,当然你也可以用 make build 直接用 go 构建。
make reload-daily     # 下载本年度最新的 isd.daily 数据并导入数据库中

加载解析好的 CSV 数据集

ISD Daily 数据集有一些脏数据与重复数据,如果你不想手工解析处理清洗,这里也提供了一份解析好的稳定CSV数据集。

该数据集包含了截止到 2023-06-24 的 isd.daily 数据,你可以直接下载并导入 PostgreSQL 中,不需要 Parser,

make get-stable       # 从 Github 上获取稳定的 isd.daily 历史数据集。
make load-stable      # 将下载好的稳定历史数据集加载到 PostgreSQL 数据库中。

更多数据

ISD数据集有两个部分是每日更新的,气象站元数据,以及最新年份的 isd.daily (如 2023 年的 Tarball)。

你可以使用以下命令下载并刷新这两个部分。如果数据集没有更新,那么这些命令不会重新下载同样的数据包

make reload           # 实际上是:reload-station + reload-daily

你也可以使用以下命令下载并加载特定年份的 isd.daily 数据:

bin/get-daily  2022                   # 获取 2022 年的每日气象观测摘要 (1900-2023)
bin/load-daily "${PGURL}" 2022        # 加载 2022 年的每日气象观测摘要 (1900-2023) 

除了每日摘要 isd.daily, ISD 还提供了一份更详细的亚小时级原始观测记录 isd.hourly,下载与加载的方式与前者类似:

bin/get-hourly  2022                  # 下载特定某一年的小时级观测记录(例如2022年,可选 1900-2023)
bin/load-hourly "${PGURL}" 2022       # 加载特定某一年的小时级观测记录 

数据

数据集概要

ISD提供了四个数据集:亚小时级原始观测数据,每日统计摘要数据,月度统计摘要,年度统计摘要

数据集备注
ISD Hourly亚小时级观测记录
ISD Daily每日统计摘要
ISD Monthly没有用到,因为可以从 isd.daily 计算生成
ISD Yearly没有用到,因为可以从 isd.daily 计算生成

每日摘要数据集

  • 压缩包大小 2.8GB (截止至 2023-06-24)
  • 表大小 24GB,索引大小 6GB,PostgreSQL 中总大小约为 30GB
  • 如果启用了 timescaledb 压缩,总大小可以压缩到 4.5 GB。

亚小时级观测数据级

  • 压缩包总大小 117GB
  • 灌入数据库后表大小 1TB+ ,索引大小 600GB+,总大小 1.6TB

数据库模式

气象站元数据表

CREATE TABLE isd.station
(
    station    VARCHAR(12) PRIMARY KEY,
    usaf       VARCHAR(6) GENERATED ALWAYS AS (substring(station, 1, 6)) STORED,
    wban       VARCHAR(5) GENERATED ALWAYS AS (substring(station, 7, 5)) STORED,
    name       VARCHAR(32),
    country    VARCHAR(2),
    province   VARCHAR(2),
    icao       VARCHAR(4),
    location   GEOMETRY(POINT),
    longitude  NUMERIC GENERATED ALWAYS AS (Round(ST_X(location)::NUMERIC, 6)) STORED,
    latitude   NUMERIC GENERATED ALWAYS AS (Round(ST_Y(location)::NUMERIC, 6)) STORED,
    elevation  NUMERIC,
    period     daterange,
    begin_date DATE GENERATED ALWAYS AS (lower(period)) STORED,
    end_date   DATE GENERATED ALWAYS AS (upper(period)) STORED
);

每日摘要表

CREATE TABLE IF NOT EXISTS isd.daily
(
    station     VARCHAR(12) NOT NULL, -- station number 6USAF+5WBAN
    ts          DATE        NOT NULL, -- observation date
    -- 气温 & 露点
    temp_mean   NUMERIC(3, 1),        -- mean temperature ℃
    temp_min    NUMERIC(3, 1),        -- min temperature ℃
    temp_max    NUMERIC(3, 1),        -- max temperature ℃
    dewp_mean   NUMERIC(3, 1),        -- mean dew point ℃
    -- 气压
    slp_mean    NUMERIC(5, 1),        -- sea level pressure (hPa)
    stp_mean    NUMERIC(5, 1),        -- station pressure (hPa)
    -- 可见距离
    vis_mean    NUMERIC(6),           -- visible distance (m)
    -- 风速
    wdsp_mean   NUMERIC(4, 1),        -- average wind speed (m/s)
    wdsp_max    NUMERIC(4, 1),        -- max wind speed (m/s)
    gust        NUMERIC(4, 1),        -- max wind gust (m/s) 
    -- 降水 / 雪深
    prcp_mean   NUMERIC(5, 1),        -- precipitation (mm)
    prcp        NUMERIC(5, 1),        -- rectified precipitation (mm)
    sndp        NuMERIC(5, 1),        -- snow depth (mm)
    -- FRSHTT (Fog/Rain/Snow/Hail/Thunder/Tornado) 雾/雨/雪/雹/雷/龙卷
    is_foggy    BOOLEAN,              -- (F)og
    is_rainy    BOOLEAN,              -- (R)ain or Drizzle
    is_snowy    BOOLEAN,              -- (S)now or pellets
    is_hail     BOOLEAN,              -- (H)ail
    is_thunder  BOOLEAN,              -- (T)hunder
    is_tornado  BOOLEAN,              -- (T)ornado or Funnel Cloud
    -- 统计聚合使用的记录数
    temp_count  SMALLINT,             -- record count for temp
    dewp_count  SMALLINT,             -- record count for dew point
    slp_count   SMALLINT,             -- record count for sea level pressure
    stp_count   SMALLINT,             -- record count for station pressure
    wdsp_count  SMALLINT,             -- record count for wind speed
    visib_count SMALLINT,             -- record count for visible distance
    -- 气温标记
    temp_min_f  BOOLEAN,              -- aggregate min temperature
    temp_max_f  BOOLEAN,              -- aggregate max temperature
    prcp_flag   CHAR,                 -- precipitation flag: ABCDEFGHI
    PRIMARY KEY (station, ts)
); -- PARTITION BY RANGE (ts);

亚小时级原始观测数据表

ISD Hourly
CREATE TABLE IF NOT EXISTS isd.hourly
(
    station    VARCHAR(12) NOT NULL, -- station id
    ts         TIMESTAMP   NOT NULL, -- timestamp
    -- air
    temp       NUMERIC(3, 1),        -- [-93.2,+61.8]
    dewp       NUMERIC(3, 1),        -- [-98.2,+36.8]
    slp        NUMERIC(5, 1),        -- [8600,10900]
    stp        NUMERIC(5, 1),        -- [4500,10900]
    vis        NUMERIC(6),           -- [0,160000]
    -- wind
    wd_angle   NUMERIC(3),           -- [1,360]
    wd_speed   NUMERIC(4, 1),        -- [0,90]
    wd_gust    NUMERIC(4, 1),        -- [0,110]
    wd_code    VARCHAR(1),           -- code that denotes the character of the WIND-OBSERVATION.
    -- cloud
    cld_height NUMERIC(5),           -- [0,22000]
    cld_code   VARCHAR(2),           -- cloud code
    -- water
    sndp       NUMERIC(5, 1),        -- mm snow
    prcp       NUMERIC(5, 1),        -- mm precipitation
    prcp_hour  NUMERIC(2),           -- precipitation duration in hour
    prcp_code  VARCHAR(1),           -- precipitation type code
    -- sky
    mw_code    VARCHAR(2),           -- manual weather observation code
    aw_code    VARCHAR(2),           -- auto weather observation code
    pw_code    VARCHAR(1),           -- weather code of past period of time
    pw_hour    NUMERIC(2),           -- duration of pw_code period
    -- misc
    -- remark     TEXT,
    -- eqd        TEXT,
    data       JSONB                 -- extra data
) PARTITION BY RANGE (ts);

解析器

NOAA ISD 提供的原始数据是高度压缩的专有格式,需要通过解析器加工,才能转换为数据库表的格式。

针对 Daily 与 Hourly 两份数据集,这里提供了两个 Parser: isdd and isdh。 这两个解析器都以年度数据压缩包作为输入,产生 CSV 结果作为输出,以管道的方式工作,如下所示:

NAME
        isd -- Intergrated Surface Dataset Parser

SYNOPSIS
        isd daily   [-i <input|stdin>] [-o <output|stout>] [-v]
        isd hourly  [-i <input|stdin>] [-o <output|stout>] [-v] [-d raw|ts-first|hour-first]

DESCRIPTION
        The isd program takes noaa isd daily/hourly raw tarball data as input.
        and generate parsed data in csv format as output. Works in pipe mode

        cat data/daily/2023.tar.gz | bin/isd daily -v | psql ${PGURL} -AXtwqc "COPY isd.daily FROM STDIN CSV;" 

        isd daily  -v -i data/daily/2023.tar.gz  | psql ${PGURL} -AXtwqc "COPY isd.daily FROM STDIN CSV;"
        isd hourly -v -i data/hourly/2023.tar.gz | psql ${PGURL} -AXtwqc "COPY isd.hourly FROM STDIN CSV;"

OPTIONS
        -i  <input>     input file, stdin by default
        -o  <output>    output file, stdout by default
        -p  <profpath>  pprof file path, enable if specified
        -d              de-duplicate rows for hourly dataset (raw, ts-first, hour-first)
        -v              verbose mode
        -h              print help

用户界面

这里提供了几个使用 Grafana 制作的 Dashboard,可以用于探索 ISD 数据集,查询气象站与历史气象数据。


ISD Overview

全局概览,总体指标与气象站导航。

isd-overview.jpg


ISD Country

展示单个国家/地区内所有的气象站。

isd-country.jpg


ISD Station

展示单个气象站的详细信息,元数据,天/月/年度汇总指标。

ISD Station Dashboard

isd-station.jpg


ISD Detail

展示一个气象站原始亚小时级观测指标数据,需要 isd.hourly 数据集。

ISD Station Dashboard

isd-detail.jpg




24 - COVID-19 数据大盘

Pigsty 自带的,用于展示世界卫生组织官方 COVID 疫情数据的一个样例 Applet

Covid 是 Pigsty 自带的,用于展示世界卫生组织官方疫情数据大盘的一个样例 Applet。

您可以查阅每个国家与地区 COVID-19 的感染与死亡案例,以及全球的疫情趋势。


概览

GitHub 仓库地址:https://github.com/Vonng/pigsty-app/tree/master/covid

在线Demo地址:https://demo.pigsty.cc/d/covid


安装

在管理节点上进入应用目录,执行make以完成安装。

make            # 完成所有配置 

其他一些子任务:

make reload     # download latest data and pour it again
make ui         # install grafana dashboards
make sql        # install database schemas
make download   # download latest data
make load       # load downloaded data into database
make reload     # download latest data and pour it into database

25 - StackOverflow 调研

分析 StackOverflow 最近七年全球开发者调研数据中关于数据库的部分

概览

GitHub 仓库地址:https://github.com/Vonng/pigsty-app/tree/master/db

在线Demo地址:https://demo.pigsty.cc/d/sf-survey

26 - DB-Engine 热度分析

分析 DB-Engine 上的数据库管理系统,查阅其流行度变迁。

概览

GitHub 仓库地址:https://github.com/Vonng/pigsty-app/tree/master/db

在线Demo地址:https://demo.pigsty.cc/d/db-engine

27 - 云上算力价格计算器

分析阿里云 / AWS 上算力与存储的价格 (ECS/ESSD)

概览

GitHub 仓库地址:https://github.com/Vonng/pigsty-app/tree/master/cloud

在线Demo地址:https://demo.pigsty.cc/d/ecs

文章地址:《剖析算力成本:阿里云真降价了吗?

数据源

Aliyun ECS 价格可以在 价格计算器 - 定价详情 - 价格下载 中获取 CSV 原始数据。

模式

下载 阿里云 价格明细并导入分析

CREATE EXTENSION file_fdw;
CREATE SERVER fs FOREIGN DATA WRAPPER file_fdw;

DROP FOREIGN TABLE IF EXISTS aliyun_ecs CASCADE;
CREATE FOREIGN TABLE aliyun_ecs
    (
        "region" text,
        "system" text,
        "network" text,
        "isIO" bool,
        "instanceId" text,
        "hourlyPrice" numeric,
        "weeklyPrice" numeric,
        "standard" numeric,
        "monthlyPrice" numeric,
        "yearlyPrice" numeric,
        "2yearPrice" numeric,
        "3yearPrice" numeric,
        "4yearPrice" numeric,
        "5yearPrice" numeric,
        "id" text,
        "instanceLabel" text,
        "familyId" text,
        "serverType" text,
        "cpu" text,
        "localStorage" text,
        "NvmeSupport" text,
        "InstanceFamilyLevel" text,
        "EniTrunkSupported" text,
        "InstancePpsRx" text,
        "GPUSpec" text,
        "CpuTurboFrequency" text,
        "InstancePpsTx" text,
        "InstanceTypeId" text,
        "GPUAmount" text,
        "InstanceTypeFamily" text,
        "SecondaryEniQueueNumber" text,
        "EniQuantity" text,
        "EniPrivateIpAddressQuantity" text,
        "DiskQuantity" text,
        "EniIpv6AddressQuantity" text,
        "InstanceCategory" text,
        "CpuArchitecture" text,
        "EriQuantity" text,
        "MemorySize" numeric,
        "EniTotalQuantity" numeric,
        "PhysicalProcessorModel" text,
        "InstanceBandwidthRx" numeric,
        "CpuCoreCount" numeric,
        "Generation" text,
        "CpuSpeedFrequency" numeric,
        "PrimaryEniQueueNumber" text,
        "LocalStorageCategory" text,
        "InstanceBandwidthTx" text,
        "TotalEniQueueQuantity" text
        ) SERVER fs OPTIONS ( filename '/tmp/aliyun-ecs.csv', format 'csv',header 'true');

AWS EC2 同理,可以从 Vantage 下载价格清单:


DROP FOREIGN TABLE IF EXISTS aws_ec2 CASCADE;
CREATE FOREIGN TABLE aws_ec2
    (
        "name" TEXT,
        "id" TEXT,
        "Memory" TEXT,
        "vCPUs" TEXT,
        "GPUs" TEXT,
        "ClockSpeed" TEXT,
        "InstanceStorage" TEXT,
        "NetworkPerformance" TEXT,
        "ondemand" TEXT,
        "reserve" TEXT,
        "spot" TEXT
        ) SERVER fs OPTIONS ( filename '/tmp/aws-ec2.csv', format 'csv',header 'true');



DROP VIEW IF EXISTS ecs;
CREATE VIEW ecs AS
SELECT "region"                                       AS region,
       "id"                                           AS id,
       "instanceLabel"                                AS name,
       "familyId"                                     AS family,
       "CpuCoreCount"                                 AS cpu,
       "MemorySize"                                   AS mem,
       round("5yearPrice" / "CpuCoreCount" / 60, 2)   AS ycm5, -- ¥ / (core·month)
       round("4yearPrice" / "CpuCoreCount" / 48, 2)   AS ycm4, -- ¥ / (core·month)
       round("3yearPrice" / "CpuCoreCount" / 36, 2)   AS ycm3, -- ¥ / (core·month)
       round("2yearPrice" / "CpuCoreCount" / 24, 2)   AS ycm2, -- ¥ / (core·month)
       round("yearlyPrice" / "CpuCoreCount" / 12, 2)  AS ycm1, -- ¥ / (core·month)
       round("standard" / "CpuCoreCount", 2)          AS ycmm, -- ¥ / (core·month)
       round("hourlyPrice" / "CpuCoreCount" * 720, 2) AS ycmh, -- ¥ / (core·month)
       "CpuSpeedFrequency"::NUMERIC                   AS freq,
       "CpuTurboFrequency"::NUMERIC                   AS freq_turbo,
       "Generation"                                   AS generation
FROM aliyun_ecs
WHERE system = 'linux';

DROP VIEW IF EXISTS ec2;
CREATE VIEW ec2 AS
SELECT id,
       name,
       split_part(id, '.', 1)                                                               as family,
       split_part(id, '.', 2)                                                               as spec,
       (regexp_match(split_part(id, '.', 1), '^[a-zA-Z]+(\d)[a-z0-9]*'))[1]                 as gen,
       regexp_substr("vCPUs", '^[0-9]+')::int                                               as cpu,
       regexp_substr("Memory", '^[0-9]+')::int                                              as mem,
       CASE spot
           WHEN 'unavailable' THEN NULL
           ELSE round((regexp_substr("spot", '([0-9]+.[0-9]+)')::NUMERIC * 7.2), 2) END     AS spot,
       CASE ondemand
           WHEN 'unavailable' THEN NULL
           ELSE round((regexp_substr("ondemand", '([0-9]+.[0-9]+)')::NUMERIC * 7.2), 2) END AS ondemand,
       CASE reserve
           WHEN 'unavailable' THEN NULL
           ELSE round((regexp_substr("reserve", '([0-9]+.[0-9]+)')::NUMERIC * 7.2), 2) END  AS reserve,
       "ClockSpeed"                                                                         AS freq
FROM aws_ec2;

可视化