newapi单个镜像不含数据库,默认是采用sqlite存储数据,并发性能差,huggingface平台提供2h16g的免费docker,但是仅支持开放一个端口。
那么为什么不能在newapi原本的镜像基础上,加装一个数据库,这样就可以白嫖huggingface的服务了。
说干就干,直接上代码,新建一个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.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" << EOF
local all all trust
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
EOF
fi
# Remove stale PID file from previous run
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
# Optimize for slow network storage (Hugging Face 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
synchronous_commit = off
full_page_writes = off
EOF
fi
# Fix permissions on every start
chown -R postgres:postgres "$PG_DATA"
chmod 0700 "$PG_DATA"
# Recreate missing critical directories (HF persistent storage may lose them on restart)
for dir in base global pg_commit_ts pg_dynshmem pg_logical pg_logical/snapshots pg_logical/mappings pg_multixact/members pg_multixact/offsets pg_notify pg_replslot pg_serial pg_snapshots pg_stat pg_stat_tmp pg_subtrans pg_tblspc pg_twophase pg_wal pg_wal/archive_status pg_wal/summaries; do
if [ ! -d "$PG_DATA/$dir" ]; then
echo "Recreating missing directory: $dir"
mkdir -p "$PG_DATA/$dir"
fi
done
chown -R postgres:postgres "$PG_DATA"
rm -f "$PG_LOG"
echo "Starting PostgreSQL..."
su postgres -c "$PG_BIN/pg_ctl -D $PG_DATA -l $PG_LOG start" || {
echo "=== PostgreSQL log ==="
cat "$PG_LOG" 2>/dev/null || echo "(no log file)"
exit 1
}
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
然后新建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.UTF-8
ENV LC_ALL=en_US.UTF-8
EXPOSE 3000
VOLUME ["/data"]
ENTRYPOINT ["/entrypoint.sh"]记得修改readme文件端口app_port: 3000,数据文件在/data,可以挂载buckets作为永久存储。
非特殊说明,本文版权归 admin 所有,转载请注明出处.
评论