# syntax=docker/dockerfile:1 # ============================================================================= # Official pg_trickle Docker Hub image. # # A self-contained PostgreSQL 18 image with pg_trickle pre-installed and # pre-configured. Suitable for: # - Quick local evaluation: docker run --rm -e POSTGRES_PASSWORD=pass ... # - CI/CD matrices: replace postgres:18 with this image # - Kubernetes base images: base for CNPG additionalPlugins overlays # # NOT the same as the CNPG Image Volume Extension image (cnpg/Dockerfile.ext), # which is scratch-based and extension-files only. # # Build (from project root): # docker build -t pgtrickle/pg_trickle:0.7.0-pg18 -f Dockerfile.hub . # # Run: # docker run --rm -e POSTGRES_PASSWORD=secret pgtrickle/pg_trickle:0.7.0-pg18 # ============================================================================= # ── Stage 1: Build the extension ──────────────────────────────────────────── FROM postgres:18-bookworm AS builder ARG VERSION=0.7.0 # Install build dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ build-essential \ libreadline-dev \ zlib1g-dev \ pkg-config \ libssl-dev \ libclang-dev \ clang \ postgresql-server-dev-18 \ ca-certificates \ && rm -rf /var/lib/apt/lists/* # Install Rust stable toolchain RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ | sh -s -- -y --default-toolchain stable ENV PATH="/root/.cargo/bin:${PATH}" # Install cargo-pgrx (version must match Cargo.toml) RUN cargo install --locked cargo-pgrx --version 0.17.0 # Initialise pgrx for PostgreSQL 18 using the system pg_config RUN cargo pgrx init --pg18 /usr/bin/pg_config # ── Dependency caching layer ──────────────────────────────────────────────── WORKDIR /build COPY Cargo.toml Cargo.lock ./ # Minimal stubs so cargo can fetch deps without the full source tree. RUN mkdir -p src/bin src/dvm/operators benches && \ echo '#![allow(warnings)] fn main() {}' > src/bin/pgrx_embed.rs && \ echo '#![allow(warnings)]' > src/lib.rs && \ echo '' > src/dvm/mod.rs && \ echo '' > src/dvm/operators/mod.rs && \ echo '' > src/ivm.rs && \ echo 'fn main() {}' > benches/refresh_bench.rs && \ echo 'fn main() {}' > benches/diff_operators.rs RUN --mount=type=cache,target=/root/.cargo/registry \ --mount=type=cache,target=/root/.cargo/git \ cargo fetch # ── Compile the extension ──────────────────────────────────────────────────── COPY src/ src/ COPY pg_trickle.control ./ RUN --mount=type=cache,target=/root/.cargo/registry \ --mount=type=cache,target=/root/.cargo/git \ --mount=type=cache,target=/build/target \ cargo pgrx package --pg-config /usr/bin/pg_config && \ mkdir -p /artefacts && \ cp -r target/release/pg_trickle-pg18 /artefacts/ # ── Stage 2: Runtime image ──────────────────────────────────────────────────── FROM postgres:18-bookworm ARG VERSION=0.7.0 ARG REPO_URL=https://github.com/grove/pg-trickle LABEL org.opencontainers.image.title="pg_trickle" \ org.opencontainers.image.description="PostgreSQL 18 with pg_trickle streaming tables and IVM pre-installed" \ org.opencontainers.image.version="${VERSION}" \ org.opencontainers.image.licenses="Apache-2.0" \ org.opencontainers.image.source="${REPO_URL}" \ org.opencontainers.image.documentation="${REPO_URL}/blob/main/docs/GETTING_STARTED.md" # Copy extension artifacts from builder COPY --from=builder \ /artefacts/pg_trickle-pg18/usr/share/postgresql/18/extension/ \ /usr/share/postgresql/18/extension/ COPY --from=builder \ /artefacts/pg_trickle-pg18/usr/lib/postgresql/18/lib/ \ /usr/lib/postgresql/18/lib/ # Configure pg_trickle in the default postgresql.conf template so any # cluster created from this image has the extension auto-loaded. RUN echo "" >> /usr/share/postgresql/postgresql.conf.sample && \ echo "# pg_trickle configuration" >> /usr/share/postgresql/postgresql.conf.sample && \ echo "shared_preload_libraries = 'pg_trickle'" >> /usr/share/postgresql/postgresql.conf.sample && \ echo "wal_level = logical" >> /usr/share/postgresql/postgresql.conf.sample && \ echo "max_replication_slots = 10" >> /usr/share/postgresql/postgresql.conf.sample && \ echo "max_worker_processes = 16" >> /usr/share/postgresql/postgresql.conf.sample # Create the extension on the default 'postgres' database during initdb so # the background worker launcher finds it immediately on first startup. RUN mkdir -p /docker-entrypoint-initdb.d && \ echo "CREATE EXTENSION IF NOT EXISTS pg_trickle CASCADE;" \ > /docker-entrypoint-initdb.d/00-pg-trickle.sql # Verify artifacts are in place RUN ls -la /usr/share/postgresql/18/extension/pg_trickle* && \ ls -la /usr/lib/postgresql/18/lib/pg_trickle* EXPOSE 5432