Skip to content

Commit 8909b98

Browse files
committed
Add separate postgres-plus-lake image with pg_lake extension
- Revert main Dockerfile to original Alpine-based image (postgres-plus) - Add new Dockerfile.pg_lake with Debian base for pg_lake compatibility - Update CI workflow to build both images (postgres-plus and postgres-plus-lake) - Update Makefile with targets for both images (build-lake, test-lake, etc.) - Update README to document both images The pg_lake extension requires PostgreSQL server internal headers that aren't available in Alpine-based images, so it uses a Debian (bookworm) base instead.
1 parent 93f9107 commit 8909b98

5 files changed

Lines changed: 424 additions & 79 deletions

File tree

.github/workflows/docker.yml

Lines changed: 181 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build and Push Docker Image
1+
name: Build and Push Docker Images
22

33
on:
44
push:
@@ -9,14 +9,14 @@ on:
99

1010
env:
1111
REGISTRY: ghcr.io
12-
IMAGE_NAME: constructive-io/docker/postgres-plus
1312
PG_VERSION: '17'
1413

1514
concurrency:
16-
group: ${{ github.workflow }}-${{ github.ref }}-docker-postgres-plus
15+
group: ${{ github.workflow }}-${{ github.ref }}
1716
cancel-in-progress: true
1817

1918
jobs:
19+
# Build postgres-plus (Alpine, lean image without pg_lake)
2020
build-postgres-plus:
2121
strategy:
2222
fail-fast: false
@@ -53,28 +53,28 @@ jobs:
5353
id: meta
5454
uses: docker/metadata-action@v5
5555
with:
56-
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
56+
images: ${{ env.REGISTRY }}/constructive-io/docker/postgres-plus
5757
tags: |
5858
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
5959
type=raw,value=${{ env.PG_VERSION }},enable=${{ github.ref == 'refs/heads/main' }}
6060
type=sha,format=short,prefix=
6161
type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
6262
type=semver,pattern={{major}}.{{minor}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
6363
64-
- name: Build (no push, PR only, amd64)
65-
if: github.event_name == 'pull_request' && matrix.platform == 'linux/amd64'
64+
- name: Build (PR only)
65+
if: github.event_name == 'pull_request'
6666
uses: docker/build-push-action@v6
6767
with:
6868
context: .
6969
file: ./Dockerfile
70-
platforms: linux/amd64
70+
platforms: ${{ matrix.platform }}
7171
push: false
7272
tags: ${{ steps.meta.outputs.tags }}
7373
labels: ${{ steps.meta.outputs.labels }}
7474
build-args: |
7575
PG_VERSION=${{ env.PG_VERSION }}
76-
cache-from: type=gha
77-
cache-to: type=gha,mode=max
76+
cache-from: type=gha,scope=postgres-plus-${{ matrix.arch }}
77+
cache-to: type=gha,mode=max,scope=postgres-plus-${{ matrix.arch }}
7878

7979
- name: Build & push by digest
8080
if: github.event_name != 'pull_request'
@@ -85,26 +85,116 @@ jobs:
8585
file: ./Dockerfile
8686
platforms: ${{ matrix.platform }}
8787
labels: ${{ steps.meta.outputs.labels }}
88-
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,push=true
88+
outputs: type=image,name=${{ env.REGISTRY }}/constructive-io/docker/postgres-plus,push-by-digest=true,push=true
89+
build-args: |
90+
PG_VERSION=${{ env.PG_VERSION }}
91+
cache-from: type=gha,scope=postgres-plus-${{ matrix.arch }}
92+
cache-to: type=gha,mode=max,scope=postgres-plus-${{ matrix.arch }}
93+
94+
- name: Export digest
95+
if: github.event_name != 'pull_request'
96+
run: |
97+
mkdir -p "${{ runner.temp }}/digests-postgres-plus"
98+
digest="${{ steps.build.outputs.digest }}"
99+
touch "${{ runner.temp }}/digests-postgres-plus/${digest#sha256:}"
100+
101+
- name: Upload digest
102+
if: github.event_name != 'pull_request'
103+
uses: actions/upload-artifact@v4
104+
with:
105+
name: digests-postgres-plus-${{ matrix.arch }}
106+
path: ${{ runner.temp }}/digests-postgres-plus/*
107+
108+
# Build postgres-plus-lake (Debian, includes pg_lake)
109+
build-postgres-plus-lake:
110+
strategy:
111+
fail-fast: false
112+
matrix:
113+
include:
114+
- platform: linux/amd64
115+
arch: amd64
116+
runner: ubuntu-latest
117+
- platform: linux/arm64
118+
arch: arm64
119+
runner: ubuntu-24.04-arm
120+
runs-on: ${{ matrix.runner }}
121+
122+
permissions:
123+
contents: read
124+
packages: write
125+
126+
steps:
127+
- name: Checkout
128+
uses: actions/checkout@v4
129+
130+
- name: Set up Docker Buildx
131+
uses: docker/setup-buildx-action@v3
132+
133+
- name: Log in to Container Registry
134+
if: github.event_name != 'pull_request'
135+
uses: docker/login-action@v3
136+
with:
137+
registry: ${{ env.REGISTRY }}
138+
username: ${{ github.actor }}
139+
password: ${{ secrets.GITHUB_TOKEN }}
140+
141+
- name: Extract metadata
142+
id: meta
143+
uses: docker/metadata-action@v5
144+
with:
145+
images: ${{ env.REGISTRY }}/constructive-io/docker/postgres-plus-lake
146+
tags: |
147+
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
148+
type=raw,value=${{ env.PG_VERSION }},enable=${{ github.ref == 'refs/heads/main' }}
149+
type=sha,format=short,prefix=
150+
type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
151+
type=semver,pattern={{major}}.{{minor}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
152+
153+
- name: Build (PR only)
154+
if: github.event_name == 'pull_request'
155+
uses: docker/build-push-action@v6
156+
with:
157+
context: .
158+
file: ./Dockerfile.pg_lake
159+
platforms: ${{ matrix.platform }}
160+
push: false
161+
tags: ${{ steps.meta.outputs.tags }}
162+
labels: ${{ steps.meta.outputs.labels }}
163+
build-args: |
164+
PG_VERSION=${{ env.PG_VERSION }}
165+
cache-from: type=gha,scope=postgres-plus-lake-${{ matrix.arch }}
166+
cache-to: type=gha,mode=max,scope=postgres-plus-lake-${{ matrix.arch }}
167+
168+
- name: Build & push by digest
169+
if: github.event_name != 'pull_request'
170+
id: build
171+
uses: docker/build-push-action@v6
172+
with:
173+
context: .
174+
file: ./Dockerfile.pg_lake
175+
platforms: ${{ matrix.platform }}
176+
labels: ${{ steps.meta.outputs.labels }}
177+
outputs: type=image,name=${{ env.REGISTRY }}/constructive-io/docker/postgres-plus-lake,push-by-digest=true,push=true
89178
build-args: |
90179
PG_VERSION=${{ env.PG_VERSION }}
91-
cache-from: type=gha
92-
cache-to: type=gha,mode=max
180+
cache-from: type=gha,scope=postgres-plus-lake-${{ matrix.arch }}
181+
cache-to: type=gha,mode=max,scope=postgres-plus-lake-${{ matrix.arch }}
93182

94183
- name: Export digest
95184
if: github.event_name != 'pull_request'
96185
run: |
97-
mkdir -p "${{ runner.temp }}/digests"
186+
mkdir -p "${{ runner.temp }}/digests-postgres-plus-lake"
98187
digest="${{ steps.build.outputs.digest }}"
99-
touch "${{ runner.temp }}/digests/${digest#sha256:}"
188+
touch "${{ runner.temp }}/digests-postgres-plus-lake/${digest#sha256:}"
100189
101190
- name: Upload digest
102191
if: github.event_name != 'pull_request'
103192
uses: actions/upload-artifact@v4
104193
with:
105-
name: digests-${{ matrix.arch }}
106-
path: ${{ runner.temp }}/digests/*
194+
name: digests-postgres-plus-lake-${{ matrix.arch }}
195+
path: ${{ runner.temp }}/digests-postgres-plus-lake/*
107196

197+
# Publish postgres-plus manifest
108198
publish-postgres-plus-manifest:
109199
if: github.event_name != 'pull_request'
110200
runs-on: ubuntu-latest
@@ -128,15 +218,87 @@ jobs:
128218
- name: Download digests
129219
uses: actions/download-artifact@v4
130220
with:
131-
pattern: digests-*
221+
pattern: digests-postgres-plus-*
222+
path: ${{ runner.temp }}/digests
223+
merge-multiple: true
224+
225+
- name: Extract metadata
226+
id: meta
227+
uses: docker/metadata-action@v5
228+
with:
229+
images: ${{ env.REGISTRY }}/constructive-io/docker/postgres-plus
230+
tags: |
231+
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
232+
type=raw,value=${{ env.PG_VERSION }},enable=${{ github.ref == 'refs/heads/main' }}
233+
type=sha,format=short,prefix=
234+
type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
235+
type=semver,pattern={{major}}.{{minor}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
236+
237+
- name: Create and push multi-arch manifests
238+
run: |
239+
set -euo pipefail
240+
241+
image="${{ env.REGISTRY }}/constructive-io/docker/postgres-plus"
242+
digest_dir="${{ runner.temp }}/digests"
243+
244+
if [ ! -d "$digest_dir" ]; then
245+
echo "No digests directory found at $digest_dir"
246+
exit 1
247+
fi
248+
249+
digests=""
250+
for digest_file in "$digest_dir"/*; do
251+
digest="$(basename "$digest_file")"
252+
digests="$digests $image@sha256:$digest"
253+
done
254+
255+
if [ -z "$digests" ]; then
256+
echo "No digests found to create manifest"
257+
exit 1
258+
fi
259+
260+
echo "Creating manifests for tags:"
261+
echo "${{ steps.meta.outputs.tags }}"
262+
263+
echo "${{ steps.meta.outputs.tags }}" | while read -r tag; do
264+
[ -z "$tag" ] && continue
265+
echo "Creating multi-arch manifest for $tag"
266+
docker buildx imagetools create -t "$tag" $digests
267+
done
268+
269+
# Publish postgres-plus-lake manifest
270+
publish-postgres-plus-lake-manifest:
271+
if: github.event_name != 'pull_request'
272+
runs-on: ubuntu-latest
273+
needs: build-postgres-plus-lake
274+
275+
permissions:
276+
contents: read
277+
packages: write
278+
279+
steps:
280+
- name: Set up Docker Buildx
281+
uses: docker/setup-buildx-action@v3
282+
283+
- name: Log in to Container Registry
284+
uses: docker/login-action@v3
285+
with:
286+
registry: ${{ env.REGISTRY }}
287+
username: ${{ github.actor }}
288+
password: ${{ secrets.GITHUB_TOKEN }}
289+
290+
- name: Download digests
291+
uses: actions/download-artifact@v4
292+
with:
293+
pattern: digests-postgres-plus-lake-*
132294
path: ${{ runner.temp }}/digests
133295
merge-multiple: true
134296

135297
- name: Extract metadata
136298
id: meta
137299
uses: docker/metadata-action@v5
138300
with:
139-
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
301+
images: ${{ env.REGISTRY }}/constructive-io/docker/postgres-plus-lake
140302
tags: |
141303
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
142304
type=raw,value=${{ env.PG_VERSION }},enable=${{ github.ref == 'refs/heads/main' }}
@@ -148,7 +310,7 @@ jobs:
148310
run: |
149311
set -euo pipefail
150312
151-
image="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
313+
image="${{ env.REGISTRY }}/constructive-io/docker/postgres-plus-lake"
152314
digest_dir="${{ runner.temp }}/digests"
153315
154316
if [ ! -d "$digest_dir" ]; then

Dockerfile

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
# Lean PostgreSQL image with pgvector, PostGIS, pg_textsearch, pgsodium, and pg_lake
1+
# Lean PostgreSQL image with pgvector, PostGIS, pg_textsearch, and pgsodium
22
# Multi-stage build - all toolchains discarded, only artifacts kept
33

44
ARG PG_VERSION=17
55
ARG PGVECTOR_VERSION=0.8.0
66
ARG POSTGIS_VERSION=3.5.1
77
ARG PG_TEXTSEARCH_VERSION=0.2.0
88
ARG PGSODIUM_VERSION=3.1.9
9-
ARG PG_LAKE_VERSION=main
109

1110
#############################################
1211
# Stage 1: Build extensions
@@ -17,7 +16,6 @@ ARG PGVECTOR_VERSION
1716
ARG POSTGIS_VERSION
1817
ARG PG_TEXTSEARCH_VERSION
1918
ARG PGSODIUM_VERSION
20-
ARG PG_LAKE_VERSION
2119

2220
RUN apk add --no-cache \
2321
git \
@@ -38,19 +36,7 @@ RUN apk add --no-cache \
3836
# PostGIS build tools
3937
perl \
4038
flex \
41-
bison \
42-
# pg_lake dependencies
43-
cmake \
44-
ninja \
45-
openssl-dev \
46-
snappy-dev \
47-
jansson-dev \
48-
lz4-dev \
49-
xz-dev \
50-
zstd-dev \
51-
libpq-dev \
52-
linux-headers \
53-
krb5-dev
39+
bison
5440

5541
WORKDIR /build
5642

@@ -84,25 +70,6 @@ RUN git clone --branch v${PGSODIUM_VERSION} --depth 1 https://github.com/michelp
8470
make -j$(nproc) && \
8571
make install
8672

87-
# pg_lake - Postgres with Iceberg and data lake access
88-
RUN git clone --branch ${PG_LAKE_VERSION} --depth 1 --recurse-submodules https://github.com/Snowflake-Labs/pg_lake.git && \
89-
cd pg_lake && \
90-
# Build and install avro library
91-
cd avro && git checkout -f . && git apply --ignore-whitespace ../avro.patch && \
92-
mkdir -p lang/c/build && cd lang/c/build && \
93-
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=RelWithDebInfo && \
94-
make -j$(nproc) && make install && \
95-
cd /build/pg_lake && \
96-
# Build pg_lake extensions (without DuckDB/pgduck_server for Alpine compatibility)
97-
make -C pg_map && make -C pg_map install && \
98-
make -C pg_extension_base && make -C pg_extension_base install && \
99-
make -C pg_extension_updater && make -C pg_extension_updater install && \
100-
make -C pg_lake_engine && make -C pg_lake_engine install && \
101-
make -C pg_lake_copy && make -C pg_lake_copy install && \
102-
make -C pg_lake_iceberg && make -C pg_lake_iceberg install && \
103-
make -C pg_lake_table && make -C pg_lake_table install && \
104-
make -C pg_lake && make -C pg_lake install
105-
10673
#############################################
10774
# Stage 2: Final lean runtime image
10875
#############################################
@@ -117,20 +84,11 @@ RUN apk add --no-cache \
11784
protobuf-c \
11885
libxml2 \
11986
pcre2 \
120-
libsodium \
121-
# pg_lake runtime dependencies
122-
snappy \
123-
jansson \
124-
lz4-libs \
125-
xz-libs \
126-
zstd-libs \
127-
libpq
87+
libsodium
12888

12989
# Copy compiled extensions from builder
13090
COPY --from=builder /usr/local/lib/postgresql/ /usr/local/lib/postgresql/
13191
COPY --from=builder /usr/local/share/postgresql/ /usr/local/share/postgresql/
132-
# Copy avro library for pg_lake
133-
COPY --from=builder /usr/local/lib/libavro* /usr/local/lib/
13492

13593
LABEL org.opencontainers.image.source="https://github.com/constructive-io/docker"
136-
LABEL org.opencontainers.image.description="PostgreSQL 17 with pgvector, PostGIS, pg_textsearch, pgsodium, and pg_lake"
94+
LABEL org.opencontainers.image.description="PostgreSQL 17 with pgvector, PostGIS, pg_textsearch, and pgsodium"

0 commit comments

Comments
 (0)