Skip to content

Commit 971d2e1

Browse files
committed
feat: Small core version of supabase postgres
Builds a smaller version of supabase postgres with a limited subset of extensions. It also creates a snapshot of the system on boot so we can have faster boots when using this image.
1 parent 8808138 commit 971d2e1

File tree

8 files changed

+1889
-3
lines changed

8 files changed

+1889
-3
lines changed
Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
name: Release Minimal Alpine Images on Dockerhub
2+
3+
# This workflow builds and publishes minimal Alpine-based Supabase Postgres images
4+
# with configurable extension profiles. It runs separately from the main release
5+
# workflow to avoid conflicts with the full Ubuntu-based images.
6+
7+
on:
8+
push:
9+
branches:
10+
- develop
11+
- release/*
12+
paths:
13+
- ".github/workflows/dockerhub-release-minimal.yml"
14+
- "Dockerfile-alpine-minimal"
15+
- "extensions-config.json"
16+
- "nix/packages/postgres-configurable.nix"
17+
workflow_dispatch:
18+
inputs:
19+
extension_profile:
20+
description: 'Extension profile to build'
21+
type: choice
22+
options:
23+
- core
24+
- standard
25+
- full
26+
- all
27+
default: standard
28+
custom_extensions:
29+
description: 'Custom comma-separated extension list (overrides profile)'
30+
required: false
31+
default: ''
32+
postgres_version:
33+
description: 'PostgreSQL version to build'
34+
type: choice
35+
options:
36+
- '17'
37+
- '15'
38+
- 'all'
39+
default: '17'
40+
41+
permissions:
42+
contents: read
43+
id-token: write
44+
45+
jobs:
46+
# Prepare build matrix based on inputs
47+
prepare:
48+
runs-on: blacksmith-4vcpu-ubuntu-2404
49+
outputs:
50+
matrix_config: ${{ steps.set-matrix.outputs.matrix_config }}
51+
steps:
52+
- name: Checkout Repo
53+
uses: supabase/postgres/.github/actions/shared-checkout@HEAD
54+
55+
- uses: ./.github/actions/nix-install-ephemeral
56+
57+
- name: Generate build matrix
58+
id: set-matrix
59+
run: |
60+
nix run nixpkgs#nushell -- -c '
61+
let input_profile = "${{ github.event.inputs.extension_profile || '\''standard'\'' }}"
62+
let input_pg_version = "${{ github.event.inputs.postgres_version || '\''17'\'' }}"
63+
let custom_extensions = "${{ github.event.inputs.custom_extensions || '\'''\'' }}"
64+
65+
# Determine profiles to build
66+
let profiles = if $custom_extensions != "" {
67+
["custom"]
68+
} else if $input_profile == "all" {
69+
["core", "standard", "full"]
70+
} else {
71+
[$input_profile]
72+
}
73+
74+
# Determine PostgreSQL versions to build
75+
let pg_versions = if $input_pg_version == "all" {
76+
["15", "17"]
77+
} else {
78+
[$input_pg_version]
79+
}
80+
81+
# Generate matrix combinations
82+
let matrix = ($profiles | each { |profile|
83+
$pg_versions | each { |pg_ver|
84+
{
85+
profile: $profile,
86+
pg_version: $pg_ver,
87+
custom_extensions: (if $profile == "custom" { $custom_extensions } else { "" })
88+
}
89+
}
90+
} | flatten)
91+
92+
let matrix_config = {
93+
include: $matrix
94+
}
95+
96+
$"matrix_config=($matrix_config | to json -r)" | save --append $env.GITHUB_OUTPUT
97+
'
98+
99+
# Get build arguments from ansible/vars.yml
100+
build_args:
101+
runs-on: blacksmith-4vcpu-ubuntu-2404
102+
outputs:
103+
build_args: ${{ steps.args.outputs.result }}
104+
steps:
105+
- name: Checkout Repo
106+
uses: supabase/postgres/.github/actions/shared-checkout@HEAD
107+
108+
- uses: ./.github/actions/nix-install-ephemeral
109+
110+
- id: args
111+
run: |
112+
nix run nixpkgs#nushell -- -c '
113+
open ansible/vars.yml
114+
| items { |key value| {name: $key, item: $value} }
115+
| where { |it| ($it.item | describe) == "string" }
116+
| each { |it| $"($it.name)=($it.item)" }
117+
| str join "\n"
118+
| save --append $env.GITHUB_OUTPUT
119+
'
120+
121+
# Build images for each profile/version/arch combination
122+
build_release_image:
123+
needs: [prepare, build_args]
124+
strategy:
125+
matrix: ${{ fromJson(needs.prepare.outputs.matrix_config) }}
126+
fail-fast: false
127+
runs-on: ${{ matrix.arch == 'arm64' && 'large-linux-arm' || 'large-linux-x86' }}
128+
timeout-minutes: 180
129+
steps:
130+
- name: Checkout Repo
131+
uses: supabase/postgres/.github/actions/shared-checkout@HEAD
132+
133+
- uses: ./.github/actions/nix-install-ephemeral
134+
135+
- run: docker context create builders
136+
137+
- uses: docker/setup-buildx-action@v3
138+
with:
139+
endpoint: builders
140+
141+
- uses: docker/login-action@v2
142+
with:
143+
username: ${{ secrets.DOCKER_USERNAME }}
144+
password: ${{ secrets.DOCKER_PASSWORD }}
145+
146+
- name: Get image tag
147+
id: image
148+
run: |
149+
nix run nixpkgs#nushell -- -c '
150+
let pg_version = "${{ matrix.pg_version }}"
151+
let profile = "${{ matrix.profile }}"
152+
let custom_ext = "${{ matrix.custom_extensions }}"
153+
154+
# Get the release version from vars.yml
155+
let release_key = $"postgres($pg_version)"
156+
let pg_release = (open ansible/vars.yml | get postgres_release | get $release_key | str trim)
157+
158+
# Build tag based on profile
159+
let tag_suffix = if $custom_ext != "" {
160+
"alpine-custom"
161+
} else {
162+
$"alpine-($profile)"
163+
}
164+
165+
let tag = $"supabase/postgres:($pg_release)-($tag_suffix)"
166+
$"tag=($tag)" | save --append $env.GITHUB_OUTPUT
167+
'
168+
169+
- name: Build and push image (amd64)
170+
if: matrix.arch != 'arm64'
171+
uses: docker/build-push-action@v5
172+
with:
173+
push: true
174+
build-args: |
175+
POSTGRES_VERSION=${{ matrix.pg_version }}
176+
EXTENSION_PROFILE=${{ matrix.profile }}
177+
CUSTOM_EXTENSIONS=${{ matrix.custom_extensions }}
178+
target: production
179+
tags: ${{ steps.image.outputs.tag }}_amd64
180+
platforms: linux/amd64
181+
cache-from: type=gha,scope=${{ github.ref_name }}-minimal-${{ matrix.profile }}-${{ matrix.pg_version }}-amd64
182+
cache-to: type=gha,mode=max,scope=${{ github.ref_name }}-minimal-${{ matrix.profile }}-${{ matrix.pg_version }}-amd64
183+
file: Dockerfile-alpine-minimal
184+
185+
- name: Build and push image (arm64)
186+
if: matrix.arch == 'arm64'
187+
uses: docker/build-push-action@v5
188+
with:
189+
push: true
190+
build-args: |
191+
POSTGRES_VERSION=${{ matrix.pg_version }}
192+
EXTENSION_PROFILE=${{ matrix.profile }}
193+
CUSTOM_EXTENSIONS=${{ matrix.custom_extensions }}
194+
target: production
195+
tags: ${{ steps.image.outputs.tag }}_arm64
196+
platforms: linux/arm64
197+
cache-from: type=gha,scope=${{ github.ref_name }}-minimal-${{ matrix.profile }}-${{ matrix.pg_version }}-arm64
198+
cache-to: type=gha,mode=max,scope=${{ github.ref_name }}-minimal-${{ matrix.profile }}-${{ matrix.pg_version }}-arm64
199+
file: Dockerfile-alpine-minimal
200+
201+
# Build for both architectures in parallel
202+
build_multiarch:
203+
needs: [prepare, build_args]
204+
strategy:
205+
matrix:
206+
include: ${{ fromJson(needs.prepare.outputs.matrix_config).include }}
207+
arch: [amd64, arm64]
208+
fail-fast: false
209+
runs-on: ${{ matrix.arch == 'arm64' && 'large-linux-arm' || 'large-linux-x86' }}
210+
timeout-minutes: 180
211+
steps:
212+
- name: Checkout Repo
213+
uses: supabase/postgres/.github/actions/shared-checkout@HEAD
214+
215+
- uses: ./.github/actions/nix-install-ephemeral
216+
217+
- run: docker context create builders
218+
219+
- uses: docker/setup-buildx-action@v3
220+
with:
221+
endpoint: builders
222+
223+
- uses: docker/login-action@v2
224+
with:
225+
username: ${{ secrets.DOCKER_USERNAME }}
226+
password: ${{ secrets.DOCKER_PASSWORD }}
227+
228+
- name: Get image tag
229+
id: image
230+
run: |
231+
nix run nixpkgs#nushell -- -c '
232+
let pg_version = "${{ matrix.pg_version }}"
233+
let profile = "${{ matrix.profile }}"
234+
let custom_ext = "${{ matrix.custom_extensions }}"
235+
236+
# Get the release version from vars.yml
237+
let release_key = $"postgres($pg_version)"
238+
let pg_release = (open ansible/vars.yml | get postgres_release | get $release_key | str trim)
239+
240+
# Build tag based on profile
241+
let tag_suffix = if $custom_ext != "" {
242+
"alpine-custom"
243+
} else {
244+
$"alpine-($profile)"
245+
}
246+
247+
let tag = $"supabase/postgres:($pg_release)-($tag_suffix)"
248+
$"tag=($tag)" | save --append $env.GITHUB_OUTPUT
249+
'
250+
251+
- name: Build and push image
252+
uses: docker/build-push-action@v5
253+
with:
254+
push: true
255+
build-args: |
256+
POSTGRES_VERSION=${{ matrix.pg_version }}
257+
EXTENSION_PROFILE=${{ matrix.profile }}
258+
CUSTOM_EXTENSIONS=${{ matrix.custom_extensions }}
259+
target: production
260+
tags: ${{ steps.image.outputs.tag }}_${{ matrix.arch }}
261+
platforms: linux/${{ matrix.arch }}
262+
cache-from: type=gha,scope=${{ github.ref_name }}-minimal-${{ matrix.profile }}-${{ matrix.pg_version }}-${{ matrix.arch }}
263+
cache-to: type=gha,mode=max,scope=${{ github.ref_name }}-minimal-${{ matrix.profile }}-${{ matrix.pg_version }}-${{ matrix.arch }}
264+
file: Dockerfile-alpine-minimal
265+
266+
# Merge multi-arch manifests
267+
merge_manifest:
268+
needs: [prepare, build_multiarch]
269+
strategy:
270+
matrix:
271+
include: ${{ fromJson(needs.prepare.outputs.matrix_config).include }}
272+
runs-on: large-linux-x86
273+
steps:
274+
- name: Checkout Repo
275+
uses: supabase/postgres/.github/actions/shared-checkout@HEAD
276+
277+
- uses: ./.github/actions/nix-install-ephemeral
278+
279+
- uses: docker/setup-buildx-action@v3
280+
281+
- uses: docker/login-action@v2
282+
with:
283+
username: ${{ secrets.DOCKER_USERNAME }}
284+
password: ${{ secrets.DOCKER_PASSWORD }}
285+
286+
- name: Get image tag
287+
id: get_tag
288+
run: |
289+
nix run nixpkgs#nushell -- -c '
290+
let pg_version = "${{ matrix.pg_version }}"
291+
let profile = "${{ matrix.profile }}"
292+
let custom_ext = "${{ matrix.custom_extensions }}"
293+
294+
let release_key = $"postgres($pg_version)"
295+
let pg_release = (open ansible/vars.yml | get postgres_release | get $release_key | str trim)
296+
297+
let tag_suffix = if $custom_ext != "" {
298+
"alpine-custom"
299+
} else {
300+
$"alpine-($profile)"
301+
}
302+
303+
let tag = $"supabase/postgres:($pg_release)-($tag_suffix)"
304+
$"tag=($tag)" | save --append $env.GITHUB_OUTPUT
305+
'
306+
307+
- name: Merge multi-arch manifests
308+
run: |
309+
docker buildx imagetools create -t ${{ steps.get_tag.outputs.tag }} \
310+
${{ steps.get_tag.outputs.tag }}_amd64 \
311+
${{ steps.get_tag.outputs.tag }}_arm64
312+
313+
- name: Create alpine alias for standard profile
314+
if: matrix.profile == 'standard'
315+
run: |
316+
nix run nixpkgs#nushell -- -c '
317+
let pg_version = "${{ matrix.pg_version }}"
318+
let release_key = $"postgres($pg_version)"
319+
let pg_release = (open ansible/vars.yml | get postgres_release | get $release_key | str trim)
320+
321+
# Create an alias without the profile suffix for standard
322+
let alias_tag = $"supabase/postgres:($pg_release)-alpine"
323+
let source_tag = "${{ steps.get_tag.outputs.tag }}"
324+
325+
$"alias_tag=($alias_tag)" | save --append $env.GITHUB_OUTPUT
326+
'
327+
328+
docker buildx imagetools create -t ${{ env.alias_tag }} \
329+
${{ steps.get_tag.outputs.tag }}_amd64 \
330+
${{ steps.get_tag.outputs.tag }}_arm64
331+
332+
- name: Upload tag artifact
333+
uses: actions/upload-artifact@v4
334+
with:
335+
name: minimal-image-tag-${{ matrix.profile }}-${{ matrix.pg_version }}
336+
path: |
337+
echo "${{ steps.get_tag.outputs.tag }}" > tag.txt
338+
if-no-files-found: warn
339+
340+
# Summary job
341+
summary:
342+
needs: [prepare, merge_manifest]
343+
runs-on: ubuntu-latest
344+
if: always()
345+
steps:
346+
- name: Summary
347+
run: |
348+
echo "## Minimal Alpine Image Build Summary" >> $GITHUB_STEP_SUMMARY
349+
echo "" >> $GITHUB_STEP_SUMMARY
350+
echo "### Build Configuration" >> $GITHUB_STEP_SUMMARY
351+
echo "- **Trigger**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
352+
echo "- **Profile**: ${{ github.event.inputs.extension_profile || 'standard' }}" >> $GITHUB_STEP_SUMMARY
353+
echo "- **PostgreSQL Version**: ${{ github.event.inputs.postgres_version || '17' }}" >> $GITHUB_STEP_SUMMARY
354+
if [ -n "${{ github.event.inputs.custom_extensions }}" ]; then
355+
echo "- **Custom Extensions**: ${{ github.event.inputs.custom_extensions }}" >> $GITHUB_STEP_SUMMARY
356+
fi
357+
echo "" >> $GITHUB_STEP_SUMMARY
358+
echo "### Built Images" >> $GITHUB_STEP_SUMMARY
359+
echo "Images have been published to Docker Hub with the following naming convention:" >> $GITHUB_STEP_SUMMARY
360+
echo "\`supabase/postgres:<version>-alpine-<profile>\`" >> $GITHUB_STEP_SUMMARY
361+
echo "" >> $GITHUB_STEP_SUMMARY
362+
echo "### Profiles" >> $GITHUB_STEP_SUMMARY
363+
echo "| Profile | Description | Est. Size |" >> $GITHUB_STEP_SUMMARY
364+
echo "|---------|-------------|-----------|" >> $GITHUB_STEP_SUMMARY
365+
echo "| core | Minimal extensions | ~200MB |" >> $GITHUB_STEP_SUMMARY
366+
echo "| standard | Common extensions | ~400MB |" >> $GITHUB_STEP_SUMMARY
367+
echo "| full | All extensions | ~1.5GB |" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)