Skip to content

Commit c330729

Browse files
fcanovaigbartolinimnenciaNiccoloFei
authored
ci: build minimal and standard images (#135)
Build images without barman-cloud, to be used with backup plugins. Other changes: - Implement timestamp-based versioning for images - Simplify build workflows for enhanced local testing and contribution - Adopt OCI annotations and generate SBOMs for improved transparency Closes #132 Signed-off-by: Francesco Canovai <[email protected]> Signed-off-by: Gabriele Bartolini <[email protected]> Signed-off-by: Marco Nenciarini <[email protected]> Signed-off-by: Niccolò Fei <[email protected]> Co-authored-by: Gabriele Bartolini <[email protected]> Co-authored-by: Marco Nenciarini <[email protected]> Co-authored-by: Niccolò Fei <[email protected]>
1 parent dff09fc commit c330729

File tree

5 files changed

+540
-19
lines changed

5 files changed

+540
-19
lines changed

.github/workflows/bake.yaml

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
name: Bake images
2+
3+
on:
4+
schedule:
5+
- cron: 0 8 * * 1
6+
workflow_dispatch:
7+
inputs:
8+
environment:
9+
type: choice
10+
options:
11+
- testing
12+
- production
13+
default: testing
14+
description: "Choose the environment to bake the images for"
15+
16+
jobs:
17+
# Start by building images for testing. We want to run security checks before pushing those to production.
18+
testbuild:
19+
name: Build for testing
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
packages: write
24+
security-events: write
25+
outputs:
26+
metadata: ${{ steps.build.outputs.metadata }}
27+
images: ${{ steps.images.outputs.images }}
28+
steps:
29+
- name: Checkout Code
30+
uses: actions/checkout@v4
31+
32+
- name: Log in to the GitHub Container registry
33+
uses: docker/login-action@v3
34+
with:
35+
registry: ghcr.io
36+
username: ${{ github.actor }}
37+
password: ${{ secrets.GITHUB_TOKEN }}
38+
39+
# TODO: review this when GitHub has linux/arm64 runners available (Q1 2025?)
40+
# https://github.com/github/roadmap/issues/970
41+
- name: Set up QEMU
42+
uses: docker/setup-qemu-action@v3
43+
with:
44+
platforms: 'arm64'
45+
46+
- name: Set up Docker Buildx
47+
uses: docker/setup-buildx-action@v3
48+
49+
- name: Build and push
50+
uses: docker/bake-action@v6
51+
id: build
52+
env:
53+
environment: testing
54+
registry: ghcr.io/${{ github.repository_owner }}
55+
revision: ${{ github.sha }}
56+
with:
57+
push: true
58+
59+
# Get a list of the images that were built and pushed. We only care about a single tag for each image.
60+
- name: Generated images
61+
id: images
62+
run: |
63+
echo "images=$(echo '${{ steps.build.outputs.metadata }}' | jq -c '[ .[]."image.name" | sub(",.*";"") ]')" >> "$GITHUB_OUTPUT"
64+
65+
security:
66+
name: Security checks
67+
runs-on: ubuntu-latest
68+
needs:
69+
- testbuild
70+
strategy:
71+
matrix:
72+
image: ${{fromJson(needs.testbuild.outputs.images)}}
73+
steps:
74+
- name: Checkout Code
75+
uses: actions/checkout@v4
76+
77+
- name: Log in to the GitHub Container registry
78+
uses: docker/login-action@v3
79+
with:
80+
registry: ghcr.io
81+
username: ${{ github.actor }}
82+
password: ${{ secrets.GITHUB_TOKEN }}
83+
84+
- name: Dockle
85+
uses: erzz/dockle-action@v1
86+
with:
87+
image: ${{ matrix.image }}
88+
exit-code: '1'
89+
90+
- name: Snyk
91+
uses: snyk/actions/docker@master
92+
continue-on-error: true
93+
env:
94+
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
95+
with:
96+
image: "${{ matrix.image }}"
97+
args: --severity-threshold=high --file=Dockerfile
98+
99+
- name: Upload result to GitHub Code Scanning
100+
uses: github/codeql-action/upload-sarif@v3
101+
continue-on-error: true
102+
with:
103+
sarif_file: snyk.sarif
104+
105+
# Build the image for production.
106+
#
107+
# TODO: no need to rebuild everything, just copy the testing images we have generated to the production registry
108+
# if we get here and we are building for production.
109+
prodbuild:
110+
if: github.event.inputs.environment == 'production' || github.event_name == 'schedule'
111+
name: Build for production
112+
runs-on: ubuntu-latest
113+
needs:
114+
- security
115+
permissions:
116+
contents: read
117+
packages: write
118+
security-events: write
119+
steps:
120+
- name: Checkout Code
121+
uses: actions/checkout@v4
122+
123+
- name: Log in to the GitHub Container registry
124+
uses: docker/login-action@v3
125+
with:
126+
registry: ghcr.io
127+
username: ${{ github.actor }}
128+
password: ${{ secrets.GITHUB_TOKEN }}
129+
130+
- name: Set up QEMU
131+
uses: docker/setup-qemu-action@v3
132+
with:
133+
platforms: 'arm64'
134+
135+
- name: Set up Docker Buildx
136+
uses: docker/setup-buildx-action@v3
137+
138+
- name: Build and push
139+
uses: docker/bake-action@v6
140+
id: build
141+
env:
142+
environment: production
143+
registry: ghcr.io/${{ github.repository_owner }}
144+
revision: ${{ github.sha }}
145+
with:
146+
push: true

BUILD.md

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Building PostgreSQL Container Images for CloudNativePG
2+
3+
This guide outlines the process for building PostgreSQL operand images for
4+
CloudNativePG using [Docker Bake](https://docs.docker.com/build/bake/) and a
5+
[GitHub workflow](.github/workflows/bake.yaml).
6+
7+
The central component of this framework is the
8+
[Bake file (`docker-bake.hcl`)](docker-bake.hcl).
9+
10+
## Prerequisites
11+
12+
Ensure the following tools and components are available before proceeding:
13+
14+
1. [Docker Buildx](https://github.com/docker/buildx): A CLI plugin for advanced
15+
image building.
16+
2. Build Driver for Multi-Architecture Images: For example, `docker-container`
17+
(see [Build Drivers](https://docs.docker.com/build/builders/drivers/) and
18+
["Install QEMU Manually"](https://docs.docker.com/build/building/multi-platform/#install-qemu-manually)).
19+
3. [Distribution Registry](https://distribution.github.io/distribution/):
20+
Formerly known as Docker Registry, to host and manage the built images.
21+
22+
### Verifying Requirements
23+
24+
To confirm your environment is properly set up, run:
25+
26+
```bash
27+
docker buildx bake --check
28+
```
29+
30+
If errors appear, you may need to switch to a different build driver. For
31+
example, use the following commands to configure a `docker-container` build
32+
driver:
33+
34+
```bash
35+
docker buildx create \
36+
--name docker-container \
37+
--driver docker-container \
38+
--use \
39+
--driver-opt network=host \
40+
--bootstrap
41+
```
42+
43+
> *Note:* The `--driver-opt network=host` setting is required only for testing
44+
> when you push to a distribution registry listening on `localhost`.
45+
46+
> *Note:* This page is not intended to serve as a comprehensive guide for
47+
> building multi-architecture images with Docker and Bake. If you encounter any
48+
> issues, please refer to the resources listed above for detailed instructions
49+
> and troubleshooting.
50+
51+
## Default Target
52+
53+
The `default` target in Bake represents a Cartesian product of the following
54+
dimensions:
55+
56+
- **Base Image**
57+
- **Type** (e.g. `minimal` or `standard`)
58+
- **Platforms**
59+
- **PostgreSQL Versions**
60+
61+
## Building Images
62+
63+
To build PostgreSQL images using the `default` target — that is, for all the
64+
combinations of base image, format, platforms, and PostgreSQL versions — run:
65+
66+
```bash
67+
docker buildx bake --push
68+
```
69+
70+
> *Note:* The `--push` flag is required to upload the images to the registry.
71+
> Without it, the images will remain cached within the builder container,
72+
> making testing impossible.
73+
74+
If you want to limit the build to a specific combination, you can specify the
75+
target in the `VERSION-TYPE-BASE` format. For example, to build an image for
76+
PostgreSQL 17 with the `minimal` format on the `bookworm` base image:
77+
78+
```bash
79+
docker buildx bake --push postgresql-17-minimal-bookworm
80+
```
81+
82+
You can also limit the build to a single platform, for example AMD64, with:
83+
84+
```bash
85+
docker buildx bake --push --set "*.platform=linux/amd64"
86+
```
87+
88+
The two can be mixed as well:
89+
90+
```bash
91+
docker buildx bake --push \
92+
--set "*.platform=linux/amd64" \
93+
postgresql-17-minimal-bookworm
94+
```
95+
96+
## The Distribution Registry
97+
98+
The images must be pushed to any registry server that complies with the **OCI
99+
Distribution Specification**.
100+
101+
By default, the build process assumes a registry server running locally at
102+
`localhost:5000`. To use a different registry, set the `registry` environment
103+
variable when executing the `docker` command, as shown:
104+
105+
```bash
106+
registry=<REGISTRY_URL> docker buildx ...
107+
```
108+
109+
## Local Testing
110+
111+
You can test the image-building process locally if you meet the necessary
112+
[prerequisites](prerequisites).
113+
114+
To do this, you'll need a local registry server. If you don't already have one,
115+
you can deploy a temporary, disposable [distribution registry](https://distribution.github.io/distribution/about/deploying/)
116+
with the following command:
117+
118+
```bash
119+
docker run -d --rm -p 5000:5000 --name registry registry:2
120+
```
121+
122+
This command runs a lightweight, temporary instance of the `registry:2`
123+
container on port `5000`.
124+
125+
## Trademarks
126+
127+
*[Postgres, PostgreSQL and the Slonik Logo](https://www.postgresql.org/about/policies/trademarks/)
128+
are trademarks or registered trademarks of the PostgreSQL Community Association
129+
of Canada, and used with their permission.*

Dockerfile

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
ARG BASE=debian:bookworm-slim
2+
FROM $BASE AS minimal
3+
4+
ARG PG_VERSION
5+
ARG PG_MAJOR=${PG_VERSION%%.*}
6+
7+
ENV PATH=$PATH:/usr/lib/postgresql/$PG_MAJOR/bin
8+
9+
RUN apt-get update && \
10+
apt-get install -y --no-install-recommends postgresql-common ca-certificates gnupg && \
11+
/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y && \
12+
apt-get install -y --no-install-recommends -o Dpkg::::="--force-confdef" -o Dpkg::::="--force-confold" postgresql-common && \
13+
sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf && \
14+
apt-get install -y --no-install-recommends \
15+
-o Dpkg::::="--force-confdef" -o Dpkg::::="--force-confold" "postgresql-${PG_MAJOR}=${PG_VERSION}*" && \
16+
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false && \
17+
rm -rf /var/lib/apt/lists/* /var/cache/* /var/log/*
18+
19+
RUN usermod -u 26 postgres
20+
USER 26
21+
22+
23+
FROM minimal AS standard
24+
25+
USER root
26+
RUN apt-get update && \
27+
apt-get install -y --no-install-recommends locales-all \
28+
"postgresql-${PG_MAJOR}-pgaudit" \
29+
"postgresql-${PG_MAJOR}-pgvector" \
30+
"postgresql-${PG_MAJOR}-pg-failover-slots" && \
31+
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false && \
32+
rm -rf /var/lib/apt/lists/* /var/cache/* /var/log/*
33+
34+
USER 26

0 commit comments

Comments
 (0)