├── README.md
├── LICENSE
├── .github
└── workflows
│ └── docker-build.yaml
└── Dockerfile
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
nginx
4 |
Built-from-source container image of NGINX
5 |
docker pull quay.io/ricardbejarano/nginx
6 |
7 |
8 |
9 | ## Features
10 |
11 | * Compiled from source during build time
12 | * Built `FROM scratch`, with zero bloat
13 | * Reduced attack surface (no shell, no UNIX tools, no package manager...)
14 | * Runs as unprivileged (non-`root`) user
15 |
16 |
17 | ## Tags
18 |
19 | ### Docker Hub
20 |
21 | Available on Docker Hub as [`docker.io/ricardbejarano/nginx`](https://hub.docker.com/r/ricardbejarano/nginx):
22 |
23 | - [`1.28.0`, `latest` *(Dockerfile)*](Dockerfile)
24 |
25 | ### RedHat Quay
26 |
27 | Available on RedHat Quay as [`quay.io/ricardbejarano/nginx`](https://quay.io/repository/ricardbejarano/nginx):
28 |
29 | - [`1.28.0`, `latest` *(Dockerfile)*](Dockerfile)
30 |
31 |
32 | ## Configuration
33 |
34 | ### Volumes
35 |
36 | - Mount your **configuration** at `/etc/nginx/nginx.conf`.
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2025 Ricard Bejarano
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/workflows/docker-build.yaml:
--------------------------------------------------------------------------------
1 | name: "Build and push container image"
2 |
3 |
4 | on:
5 | push:
6 | branches: ["*"]
7 | tags: ["*"]
8 | schedule:
9 | - cron: "0 0 * * *"
10 |
11 |
12 | jobs:
13 | main:
14 | runs-on: "ubuntu-latest"
15 | steps:
16 | - name: "Checkout"
17 | uses: "actions/checkout@v4"
18 |
19 | - name: "Login to Docker Hub"
20 | uses: "docker/login-action@v3"
21 | with:
22 | registry: "docker.io"
23 | username: "${{ secrets.DOCKER_HUB_USERNAME }}"
24 | password: "${{ secrets.DOCKER_HUB_PASSWORD }}"
25 |
26 | - name: "Login to RedHat Quay"
27 | uses: "docker/login-action@v3"
28 | with:
29 | registry: "quay.io"
30 | username: "${{ secrets.REDHAT_QUAY_USERNAME }}"
31 | password: "${{ secrets.REDHAT_QUAY_PASSWORD }}"
32 |
33 | - name: "Set up QEMU"
34 | uses: "docker/setup-qemu-action@v3"
35 |
36 | - name: "Set up Docker Buildx"
37 | uses: "docker/setup-buildx-action@v3"
38 |
39 | - name: "Build and push"
40 | uses: "docker/build-push-action@v6"
41 | with:
42 | platforms: "linux/amd64"
43 | push: true
44 | tags: |
45 | docker.io/${{ github.repository }}:latest
46 | docker.io/${{ github.repository }}:${{ github.ref_name }}
47 | quay.io/${{ github.repository }}:latest
48 | quay.io/${{ github.repository }}:${{ github.ref_name }}
49 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM docker.io/alpine:3 AS fetch-openssl
2 | WORKDIR /tmp/openssl
3 | ARG OPENSSL_VERSION="3.5.1"
4 | ADD --checksum=sha256:529043b15cffa5f36077a4d0af83f3de399807181d607441d734196d889b641f https://github.com/openssl/openssl/releases/download/openssl-$OPENSSL_VERSION/openssl-$OPENSSL_VERSION.tar.gz /tmp/openssl.tar.gz
5 | RUN tar -xzvf /tmp/openssl.tar.gz --strip-components=1
6 |
7 | FROM docker.io/alpine:3 AS fetch-pcre
8 | WORKDIR /tmp/pcre
9 | ARG PCRE_VERSION="10.45"
10 | ADD --checksum=sha256:0e138387df7835d7403b8351e2226c1377da804e0737db0e071b48f07c9d12ee https://github.com/PCRE2Project/pcre2/releases/download/pcre2-$PCRE_VERSION/pcre2-$PCRE_VERSION.tar.gz /tmp/pcre.tar.gz
11 | RUN tar -xzvf /tmp/pcre.tar.gz --strip-components=1
12 |
13 | FROM docker.io/alpine:3 AS fetch-zlib
14 | WORKDIR /tmp/zlib
15 | ARG ZLIB_VERSION="1.3.1"
16 | ADD --checksum=sha256:9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23 https://zlib.net/zlib-$ZLIB_VERSION.tar.gz /tmp/zlib.tar.gz
17 | RUN tar -xzvf /tmp/zlib.tar.gz --strip-components=1
18 |
19 | FROM docker.io/alpine:3 AS build
20 | RUN apk add \
21 | build-base \
22 | ca-certificates \
23 | linux-headers \
24 | perl-dev
25 | WORKDIR /tmp/nginx
26 | ADD --checksum=sha256:c6b5c6b086c0df9d3ca3ff5e084c1d0ef909e6038279c71c1c3e985f576ff76a https://nginx.org/download/nginx-1.28.0.tar.gz /tmp/nginx.tar.gz
27 | RUN tar -xzvf /tmp/nginx.tar.gz --strip-components=1
28 | COPY --from=fetch-openssl /tmp/openssl ./openssl
29 | COPY --from=fetch-pcre /tmp/pcre ./pcre
30 | COPY --from=fetch-zlib /tmp/zlib ./zlib
31 | RUN ./configure \
32 | --with-cc-opt='-static' \
33 | --with-ld-opt='-static' \
34 | --conf-path='/etc/nginx/nginx.conf' \
35 | --pid-path='/tmp/nginx.pid' \
36 | --http-log-path='/dev/stdout' \
37 | --error-log-path='/dev/stderr' \
38 | --http-client-body-temp-path='/tmp/client_temp' \
39 | --http-fastcgi-temp-path='/tmp/fastcgi_temp' \
40 | --http-proxy-temp-path='/tmp/proxy_temp' \
41 | --http-scgi-temp-path='/tmp/scgi_temp' \
42 | --http-uwsgi-temp-path='/tmp/uwsgi_temp' \
43 | --with-select_module \
44 | --with-poll_module \
45 | --with-threads \
46 | --with-file-aio \
47 | --with-http_ssl_module \
48 | --with-http_v2_module \
49 | --with-http_v3_module \
50 | --with-http_realip_module \
51 | --with-http_addition_module \
52 | # --with-http_xslt_module \
53 | # --with-http_image_filter_module \
54 | # --with-http_geoip_module \
55 | --with-http_sub_module \
56 | --with-http_dav_module \
57 | --with-http_flv_module \
58 | --with-http_mp4_module \
59 | --with-http_gunzip_module \
60 | --with-http_gzip_static_module \
61 | --with-http_auth_request_module \
62 | --with-http_random_index_module \
63 | --with-http_secure_link_module \
64 | --with-http_degradation_module \
65 | --with-http_slice_module \
66 | --with-http_stub_status_module \
67 | # --with-http_perl_module \
68 | --with-mail \
69 | --with-mail_ssl_module \
70 | --with-stream \
71 | --with-stream_ssl_module \
72 | --with-stream_realip_module \
73 | # --with-stream_geoip_module \
74 | --with-stream_ssl_preread_module \
75 | # --with-google_perftools_module \
76 | --with-cpp_test_module \
77 | --with-compat \
78 | --with-openssl='openssl' \
79 | --with-pcre='pcre' \
80 | --with-zlib='zlib' \
81 | && make -j"$(nproc)"
82 | RUN mkdir /rootfs \
83 | && mkdir /rootfs/bin \
84 | && cp /tmp/nginx/objs/nginx /rootfs/bin/ \
85 | && mkdir /rootfs/etc \
86 | && echo 'nogroup:*:10000:nobody' > /rootfs/etc/group \
87 | && echo 'nobody:*:10000:10000:::' > /rootfs/etc/passwd \
88 | && mkdir -p /rootfs/etc/ssl/certs \
89 | && cp /etc/ssl/certs/ca-certificates.crt /rootfs/etc/ssl/certs/ \
90 | && mkdir /rootfs/tmp
91 |
92 | FROM scratch
93 | COPY --from=build --chown=10000:10000 /rootfs /
94 | USER 10000:10000
95 | ENTRYPOINT ["/bin/nginx"]
96 | CMD ["-g", "daemon off;"]
97 |
--------------------------------------------------------------------------------