Skip to content

Commit 5dc746a

Browse files
committed
refactor: rebuild Docker image from scratch with pure Alpine, PHP and NGINX compiled from source and signed SBOM
1 parent 622469d commit 5dc746a

File tree

10 files changed

+290
-157
lines changed

10 files changed

+290
-157
lines changed

.github/workflows/docker-image-release.yml renamed to .github/workflows/release.yml

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Docker Provenance Multi-Arch Build
1+
name: Docker Image Release
22

33
on:
44
release:
@@ -92,6 +92,42 @@ jobs:
9292
run: |
9393
cosign sign --yes docker.io/fontebasso/php-nginx@${{ steps.push.outputs.digest }}
9494
95+
attach-sbom:
96+
name: Generate and Attach SBOM
97+
needs: merge-multiarch
98+
runs-on: ubuntu-latest
99+
steps:
100+
- name: Install Syft
101+
uses: anchore/sbom-action/[email protected]
102+
103+
- name: Install Cosign
104+
uses: sigstore/[email protected]
105+
106+
- name: Generate SBOM (Syft JSON)
107+
run: |
108+
syft docker.io/fontebasso/php-nginx@${{ needs.merge-multiarch.outputs.digest }} \
109+
-o spdx-json > sbom.spdx.json
110+
111+
- name: Attach SBOM to image
112+
run: |
113+
cosign attach sbom \
114+
--sbom sbom.spdx.json \
115+
docker.io/fontebasso/php-nginx@${{ needs.merge-multiarch.outputs.digest }}
116+
117+
- name: Upload SBOM artifact
118+
uses: actions/upload-artifact@v4
119+
with:
120+
name: 'sbom'
121+
path: sbom.spdx.json
122+
123+
- name: Sign SBOM
124+
env:
125+
COSIGN_EXPERIMENTAL: "1"
126+
run: |
127+
cosign sign --yes \
128+
--attachment sbom \
129+
docker.io/fontebasso/php-nginx@${{ needs.merge-multiarch.outputs.digest }}
130+
95131
generate-provenance:
96132
name: Generate SLSA Provenance v1.1
97133
needs: merge-multiarch
@@ -104,7 +140,50 @@ jobs:
104140
registry-username: ${{ secrets.DOCKERHUB_USERNAME }}
105141
registry-password: ${{ secrets.DOCKERHUB_TOKEN }}
106142
permissions:
143+
packages: write
107144
id-token: write
108145
contents: read
109-
packages: write
110146
actions: read
147+
148+
publish-assets:
149+
name: Publish SBOM and Provenance to Release
150+
needs: [ attach-sbom, generate-provenance, merge-multiarch ]
151+
runs-on: ubuntu-latest
152+
permissions:
153+
contents: write
154+
steps:
155+
- name: Extract release version
156+
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
157+
158+
- name: Install Cosign
159+
uses: sigstore/[email protected]
160+
161+
- name: Download provenance from registry
162+
run: |
163+
cosign download attestation \
164+
docker.io/fontebasso/php-nginx@${{ needs.merge-multiarch.outputs.digest }} \
165+
--output-file provenance.intoto.jsonl
166+
167+
- name: Download SBOM artifact
168+
uses: actions/download-artifact@v4
169+
with:
170+
name: 'sbom'
171+
172+
- name: Save digest to file
173+
run: echo "${{ needs.merge-multiarch.outputs.digest }}" > digest.txt
174+
175+
- name: Generate checksums
176+
run: |
177+
sha256sum \
178+
provenance.intoto.jsonl \
179+
sbom.spdx.json \
180+
digest.txt > checksums.txt
181+
182+
- name: Upload release assets
183+
uses: softprops/action-gh-release@v2
184+
with:
185+
files: |
186+
provenance.intoto.jsonl
187+
sbom.spdx.json
188+
digest.txt
189+
checksums.txt

Dockerfile

Lines changed: 174 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,190 @@
1-
ARG NAME_IMAGE_BASE='php'
2-
ARG NAME_IMAGE_TAG='8.3-fpm-alpine3.20'
1+
ARG ALPINE_VERSION=3.21
2+
ARG PHP_VERSION=8.3.20
3+
ARG NGINX_VERSION=1.27.5
34

4-
FROM ${NAME_IMAGE_BASE}:${NAME_IMAGE_TAG}
5-
6-
ARG VERSION_OS='3.20'
7-
ARG VERSION_PHP='8.3'
8-
ARG VERSION='unknown'
5+
FROM alpine:${ALPINE_VERSION}
6+
ARG ALPINE_VERSION
7+
ARG PHP_VERSION
8+
ARG NGINX_VERSION
99

1010
LABEL \
11-
org.opencontainers.image.title="PHP + NGINX" \
12-
org.opencontainers.image.description="Lightweight and secure image with PHP 8.3 and NGINX on Alpine" \
13-
org.opencontainers.image.source="https://github.com/fontebasso/docker-php-nginx" \
14-
org.opencontainers.image.version="${VERSION}" \
15-
org.opencontainers.image.licenses="MIT" \
16-
maintainer="Samuel Fontebasso <[email protected]>" \
17-
alpine="${VERSION_OS}" \
18-
php_version="${VERSION_PHP}"
11+
org.opencontainers.image.title="PHP + NGINX (compiled from source)" \
12+
org.opencontainers.image.description="Image built from Alpine with PHP and NGINX compiled from source using only permissive licenses (MIT/BSD/Apache)" \
13+
org.opencontainers.image.source="https://github.com/fontebasso/docker-php-nginx" \
14+
org.opencontainers.image.licenses="MIT" \
15+
maintainer="Samuel Fontebasso <[email protected]>" \
16+
alpine="${ALPINE_VERSION}" \
17+
php_version="${PHP_VERSION}" \
18+
nginx_version="${NGINX_VERSION}"
1919

2020
ENV APP_DIR="/app"
2121

2222
RUN set -eux; \
23-
apk update; \
24-
apk add --no-cache \
25-
ca-certificates \
26-
curl \
27-
git \
28-
icu-dev \
29-
imagemagick \
30-
jpeg-dev \
31-
freetype-dev \
32-
libpng-dev \
33-
libxml2-dev \
34-
libzip-dev \
35-
oniguruma-dev \
36-
sqlite \
37-
nginx \
38-
nginx-mod-http-headers-more \
39-
runit \
40-
openssl \
41-
libjpeg-turbo-dev \
42-
ncurses; \
43-
apk add --no-cache --virtual .build-deps \
44-
build-base \
45-
autoconf \
46-
linux-headers \
47-
bzip2-dev \
48-
curl-dev \
49-
libmcrypt-dev \
50-
imagemagick-dev \
51-
wget \
52-
gcc; \
53-
docker-php-ext-configure gd --with-freetype --with-jpeg; \
54-
docker-php-ext-configure pcntl --enable-pcntl; \
55-
docker-php-ext-install -j$(nproc) \
56-
bcmath \
57-
bz2 \
58-
calendar \
59-
exif \
60-
gd \
61-
opcache \
62-
pcntl \
63-
pdo_mysql \
64-
shmop \
65-
sockets \
66-
sysvmsg \
67-
sysvsem \
68-
sysvshm \
69-
zip; \
70-
git clone --depth=1 https://github.com/Imagick/imagick.git /tmp/imagick; \
71-
cd /tmp/imagick; \
72-
phpize; \
73-
./configure; \
74-
make -j$(nproc); \
75-
make install; \
76-
docker-php-ext-enable --ini-name docker-php-ext-x-01-imagick.ini imagick; \
77-
rm -rf /tmp/imagick; \
78-
pecl install grpc; \
79-
docker-php-ext-enable --ini-name docker-php-ext-x-02-grpc.ini grpc; \
80-
apk del .build-deps; \
81-
rm -rf /var/cache/apk/*; \
82-
rm -rf /tmp/*; \
83-
rm -f /var/log/nginx/access.log; \
84-
ln -sf /dev/null /var/log/nginx/access.log; \
85-
ln -sf /dev/stderr /var/log/nginx/error.log; \
86-
mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
23+
ln -sf /bin/false /usr/bin/tar; \
24+
apk update; \
25+
apk add --no-cache \
26+
bash \
27+
runit \
28+
ca-certificates \
29+
curl \
30+
git \
31+
tzdata \
32+
libevent \
33+
libzip \
34+
libedit \
35+
openssl \
36+
zlib \
37+
sqlite-libs \
38+
oniguruma \
39+
libarchive-tools;
40+
41+
# --- Build NGINX ---
42+
RUN set -eux; \
43+
apk add --no-cache --virtual .build-nginx-deps \
44+
build-base \
45+
pcre2-dev \
46+
zlib-dev \
47+
openssl-dev; \
48+
curl -fsSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz -o /tmp/nginx.tar.gz; \
49+
curl -fsSL https://github.com/openresty/headers-more-nginx-module/archive/refs/tags/v0.38.tar.gz -o /tmp/headers-more.tar.gz; \
50+
mkdir -p /tmp/nginx /tmp/headers-more-nginx-module-0.38; \
51+
bsdtar -xf /tmp/nginx.tar.gz -C /tmp; \
52+
bsdtar -xf /tmp/headers-more.tar.gz -C /tmp; \
53+
cd /tmp/nginx-${NGINX_VERSION}; \
54+
./configure \
55+
--prefix=/opt/nginx \
56+
--with-http_ssl_module \
57+
--with-http_gzip_static_module \
58+
--with-http_stub_status_module \
59+
--with-http_realip_module \
60+
--with-threads \
61+
--with-pcre \
62+
--add-module=/tmp/headers-more-nginx-module-0.38 \
63+
--with-cc-opt='-O2 -fPIC' \
64+
--conf-path=/etc/nginx/nginx.conf \
65+
--error-log-path=/var/log/nginx/error.log \
66+
--http-log-path=/var/log/nginx/access.log; \
67+
make -j$(nproc); \
68+
make install; \
69+
ln -s /opt/nginx/sbin/nginx /usr/sbin/nginx; \
70+
apk del .build-nginx-deps; \
71+
rm -rf /tmp/nginx*
72+
73+
# --- Build PHP ---
74+
RUN set -eux; \
75+
apk add --no-cache --virtual .build-php-deps \
76+
autoconf \
77+
bzip2-dev \
78+
curl-dev \
79+
libedit-dev \
80+
libxml2-dev \
81+
libpng-dev \
82+
jpeg-dev \
83+
freetype-dev \
84+
libsodium-dev \
85+
libjpeg-turbo-dev \
86+
libwebp-dev \
87+
libxpm-dev \
88+
libzip-dev \
89+
sqlite-dev \
90+
openssl-dev \
91+
zlib-dev \
92+
bzip2-dev \
93+
oniguruma-dev \
94+
linux-headers \
95+
gcc \
96+
g++ \
97+
make \
98+
pkgconf; \
99+
curl -fsSL https://www.php.net/distributions/php-${PHP_VERSION}.tar.gz -o /tmp/php.tar.gz; \
100+
bsdtar -xf /tmp/php.tar.gz -C /tmp; \
101+
cd /tmp/php-${PHP_VERSION}; \
102+
./configure \
103+
--prefix=/opt/php \
104+
--enable-fpm \
105+
--enable-gd \
106+
--with-bz2 \
107+
--with-freetype \
108+
--with-jpeg \
109+
--with-webp \
110+
--with-xpm \
111+
--with-png \
112+
--with-openssl \
113+
--with-zlib \
114+
--with-curl \
115+
--with-sodium \
116+
--with-libedit \
117+
--enable-mbstring \
118+
--enable-bcmath \
119+
--enable-exif \
120+
--enable-pcntl \
121+
--enable-opcache \
122+
--enable-pdo \
123+
--enable-shmop \
124+
--enable-sockets \
125+
--enable-sysvmsg \
126+
--enable-sysvsem \
127+
--enable-sysvshm \
128+
--enable-calendar \
129+
--with-pdo-mysql \
130+
--with-pdo-sqlite \
131+
--with-config-file-scan-dir=/opt/php/etc/conf.d \
132+
--with-zip \
133+
--disable-cgi \
134+
--disable-phpdbg; \
135+
make -j$(nproc); \
136+
make install; \
137+
cp sapi/fpm/php-fpm.conf /opt/php/etc/php-fpm.conf; \
138+
cp sapi/fpm/www.conf /opt/php/etc/php-fpm.d/www.conf; \
139+
cp php.ini-production /opt/php/lib/php.ini; \
140+
ln -s /opt/php/sbin/php-fpm /usr/sbin/php-fpm; \
141+
ln -s /opt/php/bin/php /usr/bin/php; \
142+
ln -s /opt/php/bin/phpize /usr/bin/phpize; \
143+
ln -s /opt/php/bin/pecl /usr/bin/pecl; \
144+
ln -s /opt/php/bin/php-config /usr/bin/php-config; \
145+
mkdir -p /opt/php/etc/conf.d; \
146+
apk del .build-php-deps; \
147+
rm -rf /tmp/php*
87148

88149
COPY ./src /
89-
COPY ./custom_params.ini /usr/local/etc/php/conf.d/docker-php-ext-x-03-custom-params.ini
150+
COPY ./custom_params.ini /opt/php/etc/conf.d/php-03-custom-params.ini
90151

91152
RUN set -eux; \
92-
touch /env; \
93-
chown -R www-data:www-data /env /app /var/log/nginx /etc/service /var/run /var/lib/nginx /run/nginx; \
94-
chmod +x \
95-
/sbin/runit-wrapper \
96-
/sbin/runsvdir-start \
97-
/etc/service/nginx/run \
98-
/etc/service/php-fpm/run
153+
apk add --no-cache \
154+
libgomp \
155+
libheif \
156+
openjpeg \
157+
librsvg \
158+
libsodium \
159+
libraw \
160+
libwmf \
161+
libxml2 \
162+
sqlite-libs \
163+
libzip \
164+
freetype \
165+
libjpeg-turbo \
166+
libpng \
167+
libwebp \
168+
libxpm \
169+
oniguruma \
170+
libarchive-tools; \
171+
apk del bash; \
172+
touch /env; \
173+
chmod +x \
174+
/sbin/runit-wrapper \
175+
/sbin/runsvdir-start \
176+
/etc/service/*/run; \
177+
adduser -S www-data -G www-data; \
178+
mkdir -p \
179+
/run/nginx \
180+
/var/log/nginx \
181+
/opt/nginx/client_body_temp; \
182+
chown -R www-data:www-data \
183+
/app /env /etc/service /opt/nginx /var/log/nginx /opt/php /tmp /run/nginx
99184

100185
USER www-data
101186
WORKDIR /app
102-
EXPOSE 80/tcp
187+
188+
EXPOSE 80
103189

104190
CMD ["/sbin/runit-wrapper"]

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@ This repository contains a Docker image for running high-performance PHP web app
1212
1313
## Features
1414

15-
- **PHP 8.3:** Modern version with performance improvements and long-term support.
1615
- **Alpine Linux 3.20:** Minimal base for better security and smaller footprint.
16+
- **PHP 8.3:** Modern version with performance improvements and long-term support.
1717
- **Nginx:** Fast and reliable web server.
18-
- **Essential PHP Extensions:** Includes `bcmath`, `bz2`, `calendar`, `exif`, `gd`, `opcache`, `pcntl`, `pdo_mysql`, `shmop`, `sockets`, `sysvmsg`, `sysvsem`, `sysvshm`, `zip`, `imagick`, `grpc`.
19-
- **Pre-installed Libraries:** `git`, `icu-dev`, `imagemagick`, `freetype`, `jpeg`, `libpng`, `libxml2`, `libzip`, `oniguruma`, `curl`, `nginx-mod-http-headers-more`.
2018
- **Runit:** Lightweight init system for process supervision.
2119
- **Multi-arch builds:** Supports linux/amd64 and linux/arm64.
2220

0 commit comments

Comments
 (0)