Skip to content

Commit eccd4b0

Browse files
committed
feat: creating multi-platform nginx distroless image
0 parents  commit eccd4b0

File tree

11 files changed

+723
-0
lines changed

11 files changed

+723
-0
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@jbeverid

.github/workflows/main.yml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
name: ci
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
11+
env:
12+
IMAGE_NAME: jbeveridge/nginx-distroless
13+
NGINX_VERSION: 1.27.1
14+
15+
jobs:
16+
build:
17+
runs-on: ubuntu-latest
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
platform:
22+
- linux/amd64
23+
- linux/arm64
24+
- linux/arm/v7
25+
- linux/ppc64le
26+
- linux/s390x
27+
steps:
28+
- name: Checkout code
29+
uses: actions/checkout@v4
30+
31+
- name: Prepare
32+
run: |
33+
platform=${{ matrix.platform }}
34+
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
35+
36+
- name: Set up QEMU
37+
uses: docker/setup-qemu-action@v3
38+
39+
- name: Set up Docker Buildx
40+
uses: docker/setup-buildx-action@v3
41+
42+
- name: Login to Docker Hub
43+
uses: docker/login-action@v3
44+
with:
45+
username: ${{ secrets.DOCKERHUB_USERNAME }}
46+
password: ${{ secrets.DOCKERHUB_TOKEN }}
47+
48+
- name: Extract metadata
49+
id: meta
50+
uses: docker/metadata-action@v5
51+
with:
52+
images: ${{ env.IMAGE_NAME }}
53+
tags: |
54+
type=raw,value=latest
55+
type=raw,value=${{ env.NGINX_VERSION }}
56+
57+
- name: Build and push by digest
58+
id: build
59+
uses: docker/build-push-action@v6
60+
with:
61+
context: .
62+
platforms: ${{ matrix.platform }}
63+
sbom: true
64+
provenance: mode=max
65+
push: ${{ github.event_name != 'pull_request' }}
66+
labels: ${{ steps.meta.outputs.labels }}
67+
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
68+
69+
- name: Export digest
70+
run: |
71+
mkdir -p /tmp/digests
72+
digest="${{ steps.build.outputs.digest }}"
73+
touch "/tmp/digests/${digest#sha256:}"
74+
75+
- name: Upload digest
76+
uses: actions/upload-artifact@v4
77+
with:
78+
name: digests-${{ env.PLATFORM_PAIR }}
79+
path: /tmp/digests/*
80+
if-no-files-found: error
81+
retention-days: 1
82+
83+
merge:
84+
if: github.event_name != 'pull_request'
85+
needs: build
86+
runs-on: ubuntu-latest
87+
steps:
88+
- name: Download digests
89+
uses: actions/download-artifact@v4
90+
with:
91+
path: /tmp/digests
92+
pattern: digests-*
93+
merge-multiple: true
94+
95+
- name: Set up Docker Buildx
96+
uses: docker/setup-buildx-action@v3
97+
98+
- name: Login to Docker Hub
99+
uses: docker/login-action@v3
100+
with:
101+
username: ${{ vars.DOCKERHUB_USERNAME }}
102+
password: ${{ secrets.DOCKERHUB_TOKEN }}
103+
104+
- name: Create and push manifest
105+
working-directory: /tmp/digests
106+
run: |
107+
docker buildx imagetools create -t ${{ env.IMAGE_NAME }}:latest -t ${{ env.IMAGE_NAME }}:${{ env.NGINX_VERSION }} \
108+
$(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *)
109+
110+
- name: Inspect image
111+
run: |
112+
docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:latest
113+
docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:${{ env.NGINX_VERSION }}
114+
115+
- name: Check image digest
116+
run: |
117+
LATEST_DIGEST=$(docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:latest --format '{{json .Manifest}}' | jq -r '.digest')
118+
VERSION_DIGEST=$(docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:${{ env.NGINX_VERSION }} --format '{{json .Manifest}}' | jq -r '.digest')
119+
echo "Latest image digest: $LATEST_DIGEST"
120+
echo "Version image digest: $VERSION_DIGEST"

.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# See http://help.github.com/ignore-files/ for more about ignoring files.
2+
3+
# compiled output
4+
/dist
5+
/tmp
6+
/out-tsc
7+
8+
# IDEs and editors
9+
/.idea
10+
.project
11+
.classpath
12+
.c9/
13+
*.launch
14+
.settings/
15+
*.sublime-workspace
16+
17+
# IDE - VSCode
18+
.vscode/*
19+
!.vscode/settings.json
20+
!.vscode/tasks.json
21+
!.vscode/launch.json
22+
!.vscode/extensions.json
23+
24+
# System Files
25+
.DS_Store
26+
Thumbs.db

Dockerfile

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Build stage
2+
FROM debian:bookworm-slim AS build
3+
4+
ARG NGINX_VERSION=1.27.1
5+
WORKDIR /var/www/nginx-distroless
6+
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
7+
8+
# Install necessary libraries and dependencies to compile nginx
9+
RUN apt-get update && apt-get install -y \
10+
gcc g++ make unzip \
11+
libaio-dev libc-dev libxslt1-dev libxml2-dev zlib1g-dev \
12+
libpcre3-dev libbz2-dev libssl-dev autoconf wget \
13+
lsb-release apt-transport-https ca-certificates
14+
15+
# Define non-root user environment variables
16+
ENV USER=nonroot
17+
ENV UID=10001
18+
19+
# Create the nonroot user
20+
RUN adduser \
21+
--disabled-password \
22+
--gecos "" \
23+
--home "/nonexistent" \
24+
--shell "/sbin/nologin" \
25+
--no-create-home \
26+
--uid "${UID}" \
27+
"${USER}"
28+
29+
# Download and extract Nginx
30+
RUN wget "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" && \
31+
tar xf "nginx-${NGINX_VERSION}.tar.gz"
32+
33+
# Configure and compile Nginx
34+
WORKDIR /var/www/nginx-distroless/nginx-${NGINX_VERSION}
35+
RUN ./configure \
36+
--prefix=/etc/nginx \
37+
--sbin-path=/usr/sbin/nginx \
38+
--conf-path=/etc/nginx/nginx.conf \
39+
--error-log-path=/dev/stderr \
40+
--http-log-path=/dev/stdout \
41+
--pid-path=/var/run/nginx.pid \
42+
--lock-path=/var/run/nginx.lock \
43+
--http-client-body-temp-path=/var/cache/nginx/client_temp \
44+
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
45+
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
46+
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
47+
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
48+
--user=nonroot \
49+
--group=nonroot \
50+
--with-compat \
51+
--with-file-aio \
52+
--with-threads \
53+
--with-http_addition_module \
54+
--with-http_auth_request_module \
55+
--with-http_dav_module \
56+
--with-http_flv_module \
57+
--with-http_gunzip_module \
58+
--with-http_gzip_static_module \
59+
--with-http_mp4_module \
60+
--with-http_random_index_module \
61+
--with-http_realip_module \
62+
--with-http_secure_link_module \
63+
--with-http_slice_module \
64+
--with-http_ssl_module \
65+
--with-http_stub_status_module \
66+
--with-http_sub_module \
67+
--with-http_v2_module \
68+
--with-http_degradation_module \
69+
--with-pcre \
70+
--with-pcre-jit \
71+
--with-cc-opt="-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -fPIC" \
72+
--with-ld-opt="-Wl,-z,relro -Wl,-z,now -pie" \
73+
&& make -j$(nproc) \
74+
&& make install
75+
76+
# Create necessary directories
77+
RUN mkdir -p /var/cache/nginx/ /var/lib/nginx /etc/nginx/conf.d/ /usr/share/nginx/html
78+
79+
# Final stage
80+
FROM gcr.io/distroless/static
81+
ENV TZ="UTC"
82+
83+
# Copy necessary files from the build stage
84+
COPY --from=build /etc/passwd /etc/group /etc/
85+
COPY --from=build /etc/nginx /etc/nginx
86+
COPY --from=build /usr/sbin/nginx /usr/sbin/
87+
COPY --from=build /var/log /var/log
88+
COPY --from=build /var/cache/nginx /var/cache/nginx
89+
COPY --from=build /var/run /var/run
90+
COPY --from=build /usr/share/nginx /usr/share/nginx
91+
92+
# Copy required libraries
93+
COPY --from=build \
94+
/lib/*-linux-gnu/libdl.so.2 \
95+
/lib/*-linux-gnu/libcrypt.so.1 \
96+
/lib/*-linux-gnu/libpcre.so.3 \
97+
/lib/*-linux-gnu/libssl.so.3 \
98+
/usr/lib/*-linux-gnu/libcrypto.so.3 \
99+
/lib/*-linux-gnu/libz.so.1 \
100+
/lib/*-linux-gnu/libc.so.6 \
101+
/lib/*-linux-gnu/libnss_compat.so.2 \
102+
/lib/*-linux-gnu/libnss_files.so.2 \
103+
/lib/
104+
105+
# Copy dynamic linker
106+
COPY --from=build /lib/*-linux-gnu/ld-linux*.so.* /lib/
107+
108+
COPY licenses/NGINX_LICENSE /usr/share/licenses/NGINX_LICENSE
109+
COPY configs/nginx.conf /etc/nginx/nginx.conf
110+
COPY configs/default.conf /etc/nginx/conf.d/default.conf
111+
COPY html/index.html /usr/share/nginx/html/index.html
112+
COPY html/50x.html /usr/share/nginx/html/50x.html
113+
114+
# Switch to non-root user
115+
USER nonroot
116+
EXPOSE 8080
117+
STOPSIGNAL SIGTERM
118+
ENTRYPOINT ["nginx", "-g", "daemon off;"]

0 commit comments

Comments
 (0)