Skip to content

Commit d054ed3

Browse files
committed
Multi-platform build with GitHub Actions, semantic versioning, and cosign signing
1 parent f9a956b commit d054ed3

File tree

6 files changed

+254
-101
lines changed

6 files changed

+254
-101
lines changed

.github/workflows/docker-monitor.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ jobs:
1313
with:
1414
token: ${{ secrets.TOKEN }}
1515
image: 'library/php'
16-
tag: '8.1-fpm-alpine3.16'
16+
tag: '8.2-fpm-alpine3.16'

.github/workflows/docker.yaml

Lines changed: 153 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,168 @@ on:
55
types: [published]
66

77
jobs:
8-
build-push-image:
8+
build:
99
runs-on: ubuntu-latest
10+
permissions:
11+
id-token: write
12+
packages: write
13+
contents: read
14+
attestations: write
15+
env:
16+
REGISTRY: index.docker.io
17+
REGISTRY_NAME: fontebasso/php-nginx
18+
19+
outputs:
20+
VERSION: ${{ steps.vars.outputs.VERSION }}
21+
MAJOR: ${{ steps.vars.outputs.MAJOR }}
22+
MINOR: ${{ steps.vars.outputs.MINOR }}
23+
1024
steps:
25+
- name: Set up QEMU
26+
uses: docker/setup-qemu-action@v3
27+
28+
- name: Set up Docker Buildx
29+
uses: docker/setup-buildx-action@v3
30+
31+
- name: Install Syft
32+
run: |
33+
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
34+
1135
- name: Publish version env var
1236
run: echo "VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
1337

14-
- name: checkout code
15-
uses: actions/checkout@v2
38+
- name: Checkout code
39+
uses: actions/checkout@v4
1640

1741
- name: Login to Docker Hub
1842
uses: docker/login-action@v1
1943
with:
20-
username: ${{ secrets.DOCKERHUB_USERNAME }}
44+
username: fontebasso
2145
password: ${{ secrets.DOCKERHUB_TOKEN }}
2246

23-
- name: Set up QEMU
24-
uses: docker/setup-qemu-action@v1
47+
- name: Extract version parts
48+
id: vars
49+
run: |
50+
IFS='.' read -r MAJOR MINOR PATCH <<< "${{ env.VERSION }}"
51+
echo "MAJOR=$MAJOR" >> $GITHUB_ENV
52+
echo "MINOR=$MINOR" >> $GITHUB_ENV
53+
echo "VERSION=${{ env.VERSION }}" >> $GITHUB_OUTPUT
54+
echo "MAJOR=$MAJOR" >> $GITHUB_OUTPUT
55+
echo "MINOR=$MINOR" >> $GITHUB_OUTPUT
2556
26-
- name: Set up Docker Buildx
27-
id: buildx
28-
uses: docker/setup-buildx-action@v1
29-
30-
- name: build and push the image
31-
run: |
32-
docker buildx build . \
33-
--build-arg BUILD_ID=${{ github.run_id }} \
34-
--build-arg COMMIT_ID=$(git rev-parse --short "$GITHUB_SHA") \
35-
--tag ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:${{ env.VERSION }} \
36-
--tag ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:latest \
37-
--platform linux/amd64,linux/arm64 \
38-
--push
39-
40-
- name: Push readme
41-
uses: actionhippie/pushrm@v1
42-
with:
43-
provider: dockerhub
44-
target: fontebasso/php-nginx
45-
username: ${{ secrets.DOCKERHUB_USERNAME }}
46-
password: ${{ secrets.DOCKERHUB_PASSWORD }}
47-
readme: README.md
57+
- name: Docker meta
58+
id: meta
59+
uses: docker/metadata-action@v5
60+
with:
61+
images: ${{ env.REGISTRY_NAME }}
62+
tags: |
63+
${{ env.VERSION }}
64+
${{ env.MAJOR }}.${{ env.MINOR }}
65+
${{ env.MAJOR }}
66+
latest
67+
annotations: |
68+
org.opencontainers.image.title=${{ env.REGISTRY_NAME }}
69+
org.opencontainers.image.description=$(cat README.md)
70+
71+
- name: Build and push
72+
id: push
73+
uses: docker/build-push-action@v6
74+
with:
75+
context: .
76+
platforms: linux/amd64,linux/arm64
77+
tags: ${{ steps.meta.outputs.tags }}
78+
push: true
79+
provenance: mode=max
80+
sbom: true
81+
build-args: |
82+
BUILD_ID=${{ github.run_id }}
83+
COMMIT_ID=$(git rev-parse --short "$GITHUB_SHA")
84+
85+
- name: Extract provenance
86+
shell: bash
87+
run: |
88+
echo $(jq -r '.provenance[]' < $GITHUB_WORKSPACE/.github/actions/buildx/output.json) > provenance.json
89+
90+
- name: Upload provenance
91+
uses: actions/upload-artifact@v4
92+
with:
93+
name: provenance
94+
path: provenance.json
95+
96+
- name: Generate SBOM
97+
id: sbom
98+
shell: bash
99+
run: |
100+
for tag in $(echo "${{ steps.meta.outputs.tags }}" | grep -Ev '^$' | tr ',' '\n'); do
101+
for platform in linux/amd64 linux/arm64; do
102+
digest=$(docker buildx imagetools inspect "${tag}" --raw | jq -r ".manifests[] | select(.platform.architecture==\"${platform##*/}\") | .digest")
103+
if [ -n "$digest" ]; then
104+
normalized_tag=$(echo "${tag}_${platform}" | tr ':' '_' | tr '.' '_' | tr '/' '_' | tr '-' '_')
105+
echo "${normalized_tag}=${digest}" >> digest_mapping.txt
106+
mkdir -p sbom
107+
syft "${tag}" -o spdx-json > "sbom/${normalized_tag}.sbom.spdx.json"
108+
fi
109+
done
110+
done
111+
112+
- name: Upload digest mapping file
113+
uses: actions/upload-artifact@v4
114+
with:
115+
name: digest_mapping
116+
path: digest_mapping.txt
117+
118+
- name: Upload SBOM files
119+
uses: actions/upload-artifact@v4
120+
with:
121+
name: sbom
122+
path: sbom
123+
124+
sign:
125+
runs-on: ubuntu-latest
126+
needs: build
127+
env:
128+
REGISTRY_NAME: fontebasso/php-nginx
129+
130+
strategy:
131+
matrix:
132+
platform: ["linux/amd64", "linux/arm64"]
133+
tags: ["latest", "${{ needs.build.outputs.VERSION }}", "${{ needs.build.outputs.MAJOR }}.${{ needs.build.outputs.MINOR }}", "${{ needs.build.outputs.MAJOR }}"]
134+
135+
steps:
136+
- name: Login to Docker Hub
137+
uses: docker/login-action@v1
138+
with:
139+
username: fontebasso
140+
password: ${{ secrets.DOCKERHUB_TOKEN }}
141+
142+
- name: Download digest mapping file
143+
uses: actions/download-artifact@v4
144+
with:
145+
name: digest_mapping
146+
147+
- name: Prepare
148+
run: |
149+
normalized_tag=$(echo "${{ env.REGISTRY_NAME }}:${{ matrix.tags }}_${{ matrix.platform }}" | tr ':' '_' | tr '.' '_' | tr '/' '_' | tr '-' '_')
150+
TAG_DIGEST=$(grep "^${normalized_tag}=" digest_mapping.txt | cut -d '=' -f 2)
151+
echo "TAG_DIGEST=${TAG_DIGEST}" >> $GITHUB_ENV
152+
echo "TAG_NORMALIZED=${normalized_tag}" >> $GITHUB_ENV
153+
154+
- name: Cosign install
155+
run: |
156+
curl -LO https://github.com/sigstore/cosign/releases/download/v2.2.4/cosign-linux-amd64
157+
chmod +x cosign-linux-amd64
158+
mv cosign-linux-amd64 cosign
159+
160+
- name: Load Cosign key
161+
run: |
162+
echo "${{ secrets.B64_COSIGN_KEY }}" | base64 -d > cosign.key
163+
echo "${{ secrets.B64_COSIGN_PUB }}" | base64 -d > cosign.pub
164+
165+
- name: Sign image with Cosign
166+
run: |
167+
./cosign sign --yes --key cosign.key ${{ env.REGISTRY_NAME }}@${{ env.TAG_DIGEST }}
168+
./cosign verify --key cosign.pub ${{ env.REGISTRY_NAME }}@${{ env.TAG_DIGEST }}
169+
170+
- name: Publish signature Rekor
171+
run: |
172+
./cosign sign --yes --key cosign.key --rekor-url https://rekor.sigstore.dev ${{ env.REGISTRY_NAME }}@${{ env.TAG_DIGEST }}

Dockerfile

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,32 @@ LABEL \
1313

1414
RUN set -ex; \
1515
\
16-
apk add --no-cache --upgrade git \
17-
bzip2-dev \
18-
ca-certificates \
19-
curl \
20-
curl-dev \
21-
freetype-dev \
22-
ghostscript \
23-
icu-dev \
24-
imagemagick \
25-
imagemagick-dev \
26-
imagemagick-libs \
27-
jpeg-dev \
28-
libjpeg-turbo-dev \
29-
libmcrypt-dev \
30-
libpng-dev \
31-
libressl-dev \
32-
libxml2-dev \
33-
libzip-dev \
34-
nginx \
35-
nginx-mod-http-headers-more \
36-
oniguruma-dev \
37-
postgresql-dev \
38-
runit; \
16+
apk update; \
17+
apk add --no-cache --upgrade bzip2-dev \
18+
ca-certificates \
19+
curl \
20+
curl-dev \
21+
freetype-dev \
22+
ghostscript \
23+
git \
24+
icu-dev \
25+
imagemagick \
26+
imagemagick-dev \
27+
imagemagick-libs \
28+
jpeg-dev \
29+
libjpeg-turbo-dev \
30+
libmcrypt-dev \
31+
libpng-dev \
32+
libressl-dev \
33+
libxml2-dev \
34+
libzip-dev \
35+
ncurses \
36+
nginx \
37+
nginx-mod-http-headers-more \
38+
oniguruma-dev \
39+
openssl \
40+
runit \
41+
sqlite; \
3942
apk add --no-cache --virtual build-dependencies build-base gcc wget autoconf linux-headers; \
4043
docker-php-ext-configure gd \
4144
--with-freetype \
@@ -49,30 +52,40 @@ RUN set -ex; \
4952
exif \
5053
gd \
5154
opcache \
55+
pcntl \
5256
pdo_mysql \
5357
shmop \
5458
sockets \
5559
sysvmsg \
5660
sysvsem \
5761
sysvshm \
58-
pcntl \
5962
zip; \
6063
pecl install imagick; \
6164
docker-php-ext-enable --ini-name docker-php-ext-x-01-imagick.ini imagick; \
6265
ln -sf /dev/stdout /var/log/nginx/access.log; \
6366
ln -sf /dev/stderr /var/log/nginx/error.log; \
64-
mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"; \
65-
apk upgrade --no-cache;
67+
mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini";
6668

6769
COPY ./src /
6870
COPY ./custom_params.ini /usr/local/etc/php/conf.d/docker-php-ext-x-02-custom-params.ini
6971

72+
RUN touch /env \
73+
&& chown -R www-data:www-data /env \
74+
&& chown -R www-data:www-data /app \
75+
&& chown -R www-data:www-data /var/log/nginx \
76+
&& chown -R www-data:www-data /etc/service \
77+
&& chown -R www-data:www-data /var/run \
78+
&& chown -R www-data:www-data /var/lib/nginx \
79+
&& chown -R www-data:www-data /run/nginx
80+
7081
RUN chmod +x \
7182
/sbin/runit-wrapper \
7283
/sbin/runsvdir-start \
7384
/etc/service/nginx/run \
7485
/etc/service/php-fpm/run
7586

87+
USER www-data
88+
7689
WORKDIR /app
7790
EXPOSE 80/tcp
7891

0 commit comments

Comments
 (0)