在 HuggingFace 上搭建 NewAPI + PostgreSQL 数据库

背景

NewAPI 单个镜像默认不包含数据库,采用 SQLite 存储数据,并发性能较差。HuggingFace Spaces 提供 2 核 16G 的免费 Docker 容器,但仅支持开放一个端口。
解决方案:在 NewAPI 镜像基础上内嵌 PostgreSQL,实现数据库一体化部署,白嫖 HuggingFace 的免费服务。

项目文件

1. entrypoint.sh

#!/bin/bash
set -e
PG_VERSION=15
PG_BIN=/usr/lib/postgresql/$PG_VERSION/bin
PG_DATA=/data/pgdata
PG_LOG=/data/pgdata/pg.log
: "${POSTGRES_USER:=root}"
: "${POSTGRES_PASSWORD:=123456}"
: "${POSTGRES_DB:=new-api}"
: "${SQL_DSN:=postgresql://root:123456@localhost:5432/new-api}"
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
mkdir -p "$PG_DATA"
chown -R postgres:postgres "$PG_DATA"
if [ ! -f "$PG_DATA/PG_VERSION" ]; then
echo "Initializing PostgreSQL data directory..."
su postgres -c "$PG_BIN/initdb -D $PG_DATA --locale=en_US.UTF-8"
if [ ! -f "$PG_DATA/postgresql.conf" ]; then
echo "FATAL: initdb did not create postgresql.conf" >&2
exit 1
fi
cat > "$PG_DATA/pg_hba.conf" <<- EOHBA
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
EOHBA
fi
# 清理残留 PID 文件
if [ -f "$PG_DATA/postmaster.pid" ]; then
OLD_PID=$(head -1 "$PG_DATA/postmaster.pid")
if ! kill -0 "$OLD_PID" 2>/dev/null; then
echo "Removing stale PostgreSQL PID file (PID $OLD_PID)"
rm -f "$PG_DATA/postmaster.pid"
fi
fi
# 优化慢网络存储(HuggingFace Spaces 环境)
if ! grep -q "^fsync = off" "$PG_DATA/postgresql.conf" 2>/dev/null; then
echo "Applying PostgreSQL storage optimizations..."
cat >> "$PG_DATA/postgresql.conf" <<- EOF
fsync = off
full_page_writes = off
wal_level = minimal
max_wal_senders = 0
listen_addresses = 'localhost'
port = 5432
EOF
fi
echo "Starting PostgreSQL..."
su postgres -c "$PG_BIN/pg_ctl -D $PG_DATA -l $PG_LOG start"
# 等待 PostgreSQL 启动
for i in $(seq 1 600); do
if su postgres -c "$PG_BIN/pg_isready -q"; then
echo "PostgreSQL is ready."
break
fi
if [ "$i" -eq 600 ]; then
echo "=== PostgreSQL log (timeout) ==="
cat "$PG_LOG" 2>/dev/null || echo "(no log file)"
exit 1
fi
sleep 1
done
echo "Creating database user and database if needed..."
su postgres -c "$PG_BIN/psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='$POSTGRES_USER'"" | grep -q 1 || su postgres -c "$PG_BIN/psql -c "CREATE USER $POSTGRES_USER WITH PASSWORD '$POSTGRES_PASSWORD'""
su postgres -c "$PG_BIN/psql -tAc "SELECT 1 FROM pg_database WHERE datname='$POSTGRES_DB'"" | grep -q 1 || su postgres -c "$PG_BIN/psql -c "CREATE DATABASE \"$POSTGRES_DB\" OWNER $POSTGRES_USER""
export SQL_DSN
cd /data
echo "Starting new-api..."
/new-api &
NEWAPI_PID=$!
cleanup() {
echo "Shutting down..."
kill $NEWAPI_PID 2>/dev/null || true
su postgres -c "$PG_BIN/pg_ctl -D $PG_DATA stop" || true
exit 0
}
trap cleanup SIGTERM SIGINT
wait $NEWAPI_PID
EXIT_CODE=$?
su postgres -c "$PG_BIN/pg_ctl -D $PG_DATA stop" || true
exit $EXIT_CODE

2. Dockerfile

FROM calciumion/new-api:v0.13.2
RUN apt-get update && \
apt-get install -y postgresql-15 locales && \
sed -i 's/^# en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen && \
locale-gen && \
rm -rf /var/lib/apt/lists/* && \
pg_dropcluster 15 main && \
rm -rf /etc/postgresql/15
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENV POSTGRES_USER=root
ENV POSTGRES_PASSWORD=123456
ENV POSTGRES_DB=new-api
ENV SQL_DSN=postgresql://root:123456@localhost:5432/new-api
ENV TZ=Asia/Shanghai
ENV LANG=en_US.UTF-8
ENV LC_ALL=en_US.UTF-8
EXPOSE 3000
VOLUME ["/data"]
ENTRYPOINT ["/entrypoint.sh"]

HuggingFace Spaces 部署设置

在 Space 的 README.md 中配置:

app_port: 3000
  • 端口3000(NewAPI Web 端口)
  • 数据持久化/data 目录可以挂载 HuggingFace 的 Buckets 作为永久存储

部署步骤

  1. 在 HuggingFace 上创建新 Space,选择 Docker 运行时
  2. 上传 Dockerfileentrypoint.sh 到仓库根目录
  3. 配置 README.md 中的 app_port: 3000
  4. 等待自动构建完成
  5. Space 启动后,通过 HuggingFace 提供的 URL 访问 NewAPI 面板

优势

  • 免费:HuggingFace 提供 2 核 16G 免费容器
  • 高性能:PostgreSQL 替代 SQLite,并发性能大幅提升
  • 一体化:无需额外数据库服务,单镜像包含全部组件
  • 持久化:通过 HuggingFace Buckets 挂载 /data 目录,数据不丢失
THE END
喜欢就支持一下吧
点赞0 分享 收藏
评论 抢沙发
欢迎您留下宝贵的见解!(至少 2 字)
提交
昵称

昵称

昵称 表情 快捷回复

    暂无评论内容