# Custom PostgreSQL 18.4 image with pg_partman + pg_cron extensions. # # The logs table of new-api is a RANGE-partitioned table on created_at, created # and maintained entirely on the database side by the pg_partman extension. # pg_cron drives periodic maintenance (premake future weekly partitions). # # Both extensions are installed via Debian packages. pg_cron must be loaded via # shared_preload_libraries, so we append it to postgresql.conf.sample: initdb # generates PGDATA/postgresql.conf from this sample, meaning both the temporary # server (during docker-entrypoint-initdb.d) and the real server load pg_cron, # allowing CREATE EXTENSION pg_cron to succeed at init time. # # Build/push: # docker build -t registry.cn-hangzhou.aliyuncs.com/fengsilin/postgres-partman:18 . # docker push registry.cn-hangzhou.aliyuncs.com/fengsilin/postgres-partman:18 FROM postgres:18 # Use Aliyun Debian mirror for faster/reliable apt downloads from within China. # postgres:18 is based on Debian trixie which uses the deb822-format # /etc/apt/sources.list.d/debian.sources file instead of sources.list. RUN sed -i 's|deb.debian.org|mirrors.aliyun.com|g; s|security.debian.org|mirrors.aliyun.com|g' \ /etc/apt/sources.list.d/debian.sources RUN apt-get update \ && apt-get install -y --no-install-recommends \ postgresql-18-partman \ postgresql-18-cron \ && rm -rf /var/lib/apt/lists/* # Preload pg_cron so it is available during first-run init scripts. # pg_partman is a plain SQL extension and does not need preloading. RUN echo "shared_preload_libraries = 'pg_cron'" >> /usr/share/postgresql/18/postgresql.conf.sample RUN echo "cron.database_name = 'new-api'" >> /usr/share/postgresql/18/postgresql.conf.sample # First-run init: create extensions, the partitioned logs parent table, register # it with pg_partman, build core indexes, and schedule maintenance via pg_cron. # Runs against the database named by POSTGRES_DB (new-api). COPY docker-entrypoint-initdb.d/01-partition.sql /docker-entrypoint-initdb.d/01-partition.sql