├── .dockerignore ├── .gitignore ├── .gitlab-ci.yml ├── Dockerfile ├── Dockerfile-geoip ├── Makefile ├── README.md └── logo.png /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | LICENSE 3 | README.md 4 | logo.jpg 5 | logo.png 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # don't accidentally commit our MaxMind GeoIP config 2 | GeoIP.conf -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Lint all Dockerfiles in this repo 3 | docker-lint: 4 | image: projectatomic/dockerfile-lint 5 | stage: .pre 6 | script: 7 | - dockerfile_lint -f Dockerfile 8 | - dockerfile_lint -f Dockerfile-geoip 9 | 10 | # Docker buildx for multiplatform 11 | buildx: 12 | image: docker:stable-git 13 | stage: .pre 14 | variables: 15 | GIT_STRATEGY: none 16 | artifacts: 17 | paths: 18 | - buildx 19 | expire_in: 6 hours 20 | services: 21 | - docker:stable-dind 22 | script: 23 | - export DOCKER_BUILDKIT=1 24 | - git clone git://github.com/docker/buildx ./docker-buildx 25 | - docker build --platform=local -o . ./docker-buildx 26 | 27 | # I will unify these build steps once more when this GitLab CI issue is fixed: 28 | # https://gitlab.com/gitlab-com/support-forum/issues/5036 29 | build-amd64: 30 | image: docker:stable 31 | stage: build 32 | services: 33 | - name: docker:stable-dind 34 | command: ["--experimental"] 35 | retry: 2 36 | before_script: 37 | - mkdir -p ~/.docker/cli-plugins 38 | - mv buildx ~/.docker/cli-plugins/docker-buildx 39 | - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes 40 | script: 41 | - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY 42 | - docker buildx create --use --name build-amd64 43 | - docker buildx build --load --platform linux/amd64 -t "$CI_REGISTRY_IMAGE" -t "$CI_REGISTRY_IMAGE:x86_64" -f ./Dockerfile . 44 | - docker push "$CI_REGISTRY_IMAGE" 45 | 46 | build-aarch64: 47 | image: docker:stable 48 | stage: build 49 | services: 50 | - name: docker:stable-dind 51 | command: ["--experimental"] 52 | retry: 2 53 | before_script: 54 | - mkdir -p ~/.docker/cli-plugins 55 | - mv buildx ~/.docker/cli-plugins/docker-buildx 56 | - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes 57 | script: 58 | - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY 59 | - docker buildx create --use --name build-aarch64 60 | - docker buildx build --load --platform linux/arm64 -t "$CI_REGISTRY_IMAGE:aarch64" -f ./Dockerfile . 61 | - docker push "$CI_REGISTRY_IMAGE:aarch64" 62 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Most of the below is based on the Nginx Team's Alpine Dockerfile 2 | # https://github.com/nginxinc/docker-nginx/blob/e3e35236b2c77e02266955c875b74bdbceb79c44/mainline/alpine/Dockerfile 3 | 4 | # --- Nginx Build Container --- # 5 | FROM alpine:3 as builder 6 | 7 | # Nginx Version (See: https://nginx.org/en/CHANGES) 8 | ENV NGINX_VERSION 1.19.4 9 | ENV NGINX_GPG B0F4253373F8F6F510D42178520A9993A1C052F8 10 | 11 | # Nginx User UID/GID 12 | ARG NGINX_ID=6666 13 | 14 | # Nginx build config 15 | ARG CONFIG="\ 16 | --prefix=/etc/nginx \ 17 | --sbin-path=/usr/sbin/nginx \ 18 | --modules-path=/usr/lib/nginx/modules \ 19 | --conf-path=/etc/nginx/nginx.conf \ 20 | --error-log-path=/var/log/nginx/error.log \ 21 | --http-log-path=/var/log/nginx/access.log \ 22 | --pid-path=/var/run/nginx.pid \ 23 | --lock-path=/var/run/nginx.lock \ 24 | --http-client-body-temp-path=/var/cache/nginx/client_temp \ 25 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ 26 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ 27 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ 28 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ 29 | --user=nginx \ 30 | --group=nginx \ 31 | --with-http_ssl_module \ 32 | --with-http_realip_module \ 33 | --with-http_addition_module \ 34 | --with-http_sub_module \ 35 | --with-http_dav_module \ 36 | --with-http_flv_module \ 37 | --with-http_mp4_module \ 38 | --with-http_gunzip_module \ 39 | --with-http_gzip_static_module \ 40 | --with-http_random_index_module \ 41 | --with-http_secure_link_module \ 42 | --with-http_stub_status_module \ 43 | --with-http_auth_request_module \ 44 | --with-http_xslt_module=dynamic \ 45 | --with-http_image_filter_module=dynamic \ 46 | --with-threads \ 47 | --with-stream \ 48 | --with-stream_ssl_module \ 49 | --with-stream_ssl_preread_module \ 50 | --with-stream_realip_module \ 51 | --with-http_slice_module \ 52 | --with-mail \ 53 | --with-mail_ssl_module \ 54 | --with-compat \ 55 | --with-file-aio \ 56 | --with-http_v2_module \ 57 | --with-openssl=/usr/src/boringssl \ 58 | --with-cc-opt=-I'/usr/src/boringssl/.openssl/include/' \ 59 | --add-module=/usr/src/modules/ngx_headers_more \ 60 | --add-module=/usr/src/modules/ngx_subs_filter \ 61 | --add-module=/usr/src/modules/ngx_brotli \ 62 | " 63 | 64 | RUN set -xe \ 65 | \ 66 | # Add BoringSSL build deps 67 | && apk add --no-cache --virtual .boringssl-deps \ 68 | build-base \ 69 | cmake \ 70 | git \ 71 | go \ 72 | linux-headers \ 73 | perl \ 74 | \ 75 | # Download and prepare BoringSSL source 76 | && git clone --depth 1 https://boringssl.googlesource.com/boringssl "/usr/src/boringssl" \ 77 | && mkdir "/usr/src/boringssl/build/" \ 78 | && cd "/usr/src/boringssl/build/" \ 79 | && cmake -DCMAKE_BUILD_TYPE=Release ../ \ 80 | && make -j$(getconf _NPROCESSORS_ONLN) \ 81 | && mkdir -p "/usr/src/boringssl/.openssl/lib" \ 82 | && cd "/usr/src/boringssl/.openssl" \ 83 | && ln -s ../include \ 84 | && cd "/usr/src/boringssl" \ 85 | && cp "build/crypto/libcrypto.a" "build/ssl/libssl.a" ".openssl/lib" \ 86 | \ 87 | # Download additional Nginx modules (for each of these we need to include an --add-module line in the Nginx configuration step) 88 | && mkdir -p /usr/src/modules \ 89 | && git clone --depth 1 https://github.com/openresty/headers-more-nginx-module.git /usr/src/modules/ngx_headers_more \ 90 | && git clone --depth 1 https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git /usr/src/modules/ngx_subs_filter \ 91 | && git clone --depth 1 https://github.com/leev/ngx_http_geoip2_module.git /usr/src/modules/ngx_http_geoip2_module \ 92 | && git clone --depth 1 https://github.com/google/ngx_brotli.git /usr/src/modules/ngx_brotli \ 93 | && cd /usr/src/modules/ngx_brotli && git submodule update --init \ 94 | \ 95 | # Download and prepare Nginx 96 | && cd /usr/src \ 97 | && addgroup -S -g $NGINX_ID nginx \ 98 | && adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx -u $NGINX_ID nginx \ 99 | && apk add --no-cache --virtual .build-deps \ 100 | gcc \ 101 | libc-dev \ 102 | make \ 103 | pcre-dev \ 104 | zlib-dev \ 105 | linux-headers \ 106 | curl \ 107 | gnupg \ 108 | libxslt-dev \ 109 | gd-dev \ 110 | libmaxminddb-dev \ 111 | && curl -fSL https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz -o nginx.tar.gz \ 112 | && curl -fSL https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz.asc -o nginx.tar.gz.asc \ 113 | && export GNUPGHOME="$(mktemp -d)" \ 114 | && found=''; \ 115 | for server in \ 116 | ha.pool.sks-keyservers.net \ 117 | hkp://keyserver.ubuntu.com:80 \ 118 | hkp://p80.pool.sks-keyservers.net:80 \ 119 | pgp.mit.edu \ 120 | ; do \ 121 | echo "Fetching GPG key $NGINX_GPG from $server"; \ 122 | gpg --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPG" && found=yes && break; \ 123 | done; \ 124 | test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPG" && exit 1; \ 125 | gpg --batch --verify nginx.tar.gz.asc nginx.tar.gz \ 126 | && rm -rf "$GNUPGHOME" nginx.tar.gz.asc \ 127 | && tar -zxC /usr/src -f nginx.tar.gz \ 128 | && rm nginx.tar.gz \ 129 | && mv -v /usr/src/nginx-$NGINX_VERSION /usr/src/nginx 130 | 131 | # Build debug bits 132 | RUN cd /usr/src/nginx \ 133 | && ./configure $CONFIG --with-debug \ 134 | \ 135 | # Prevent build-error 127 which seems to be caused by the ssl.h file missing: 136 | && mkdir -p /usr/src/boringssl/.openssl/include/openssl/ \ 137 | && touch /usr/src/boringssl/.openssl/include/openssl/ssl.h \ 138 | && make -j$(getconf _NPROCESSORS_ONLN) \ 139 | && mv objs/nginx objs/nginx-debug \ 140 | && mv objs/ngx_http_xslt_filter_module.so objs/ngx_http_xslt_filter_module-debug.so \ 141 | && mv objs/ngx_http_image_filter_module.so objs/ngx_http_image_filter_module-debug.so 142 | 143 | # Build main bits 144 | RUN cd /usr/src/nginx \ 145 | && ./configure $CONFIG \ 146 | \ 147 | # Prevent build-error 127 which seems to be caused by the ssl.h file missing: 148 | && mkdir -p /usr/src/boringssl/.openssl/include/openssl/ \ 149 | && touch /usr/src/boringssl/.openssl/include/openssl/ssl.h \ 150 | && make -j$(getconf _NPROCESSORS_ONLN) 151 | 152 | # Clean some unnecessary source so we're copying less into the next stage 153 | RUN rm -rf /usr/src/boringssl/build 154 | 155 | # Move the source into a single place 156 | RUN mkdir /tmp/buildsource 157 | RUN mv -fv /usr/src/nginx/ /tmp/buildsource/nginx/ 158 | RUN mv -fv /usr/src/modules/ /tmp/buildsource/modules/ 159 | RUN mv -fv /usr/src/boringssl/ /tmp/buildsource/boringssl/ 160 | 161 | # Backup our NGINX_ID environment variable 162 | RUN echo "$NGINX_ID" > /tmp/buildsource/nginx_id 163 | 164 | 165 | # --- Runtime Container --- # 166 | FROM alpine:3 167 | LABEL maintainer "Alex Haydock " 168 | LABEL name "BoringNginx" 169 | LABEL version 1.19.4 170 | 171 | COPY --from=builder /tmp/buildsource /usr/src 172 | 173 | RUN set -xe \ 174 | \ 175 | # Set the NGINX_ID environment variable again 176 | && export NGINX_ID="$(cat /usr/src/nginx_id)" \ 177 | \ 178 | # Re-add the Nginx user 179 | && addgroup -S -g $NGINX_ID nginx \ 180 | && adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx -u $NGINX_ID nginx \ 181 | \ 182 | # Add some more deps to install Nginx 183 | && apk add --no-cache --virtual .installdeps binutils make wget \ 184 | \ 185 | # Install Nginx 186 | && cd /usr/src/nginx \ 187 | && make install \ 188 | && rm -rf /etc/nginx/html/ \ 189 | && mkdir /etc/nginx/conf.d/ \ 190 | && mkdir -p /usr/share/nginx/html/ \ 191 | && install -m644 html/index.html /usr/share/nginx/html/ \ 192 | && install -m644 html/50x.html /usr/share/nginx/html/ \ 193 | && install -m755 objs/nginx-debug /usr/sbin/nginx-debug \ 194 | && install -m755 objs/ngx_http_xslt_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_xslt_filter_module-debug.so \ 195 | && install -m755 objs/ngx_http_image_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_image_filter_module-debug.so \ 196 | && ln -s ../../usr/lib/nginx/modules /etc/nginx/modules \ 197 | && strip /usr/sbin/nginx* \ 198 | && strip /usr/lib/nginx/modules/*.so \ 199 | \ 200 | # Bring in gettext so we can get `envsubst`, then throw 201 | # the rest away. To do this, we need to install `gettext` 202 | # then move `envsubst` out of the way so `gettext` can 203 | # be deleted completely, then move `envsubst` back. 204 | && apk add --no-cache --virtual .gettext gettext \ 205 | && mv /usr/bin/envsubst /tmp/ \ 206 | \ 207 | # Work out our runtime dependencies 208 | && runDeps="$( \ 209 | scanelf --needed --nobanner --format '%n#p' /usr/sbin/nginx /usr/lib/nginx/modules/*.so /tmp/envsubst \ 210 | | tr ',' '\n' \ 211 | | sort -u \ 212 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 213 | )" \ 214 | # Install the runtime dependencies as virtual metapackage called ".nginx-rundeps" 215 | && apk add --no-cache --virtual .nginx-rundeps $runDeps \ 216 | \ 217 | # Bring in tzdata so users can set the timezone through environment variables 218 | && apk add --no-cache tzdata \ 219 | \ 220 | # Add the default Nginx config files 221 | # (these are pulled directly from the Nginx team's Docker repo without modification) 222 | && wget https://hg.nginx.org/pkg-oss/raw-file/tip/alpine/nginx.conf -O /etc/nginx/nginx.conf \ 223 | && wget https://hg.nginx.org/pkg-oss/raw-file/tip/alpine/default.conf -O /etc/nginx/conf.d/default.conf \ 224 | \ 225 | # Remove our virtual metapackages 226 | && apk del .installdeps .gettext \ 227 | && mv /tmp/envsubst /usr/local/bin/ \ 228 | \ 229 | # Delete source files to save space in final image 230 | && rm -rf /usr/src/* \ 231 | \ 232 | # Make sure ownership is correct on everything Nginx will need to write to. 233 | # This means we can run the container as the Nginx user if we want to. 234 | && chown -R $NGINX_ID:$NGINX_ID "/etc/nginx" \ 235 | && chown -R $NGINX_ID:$NGINX_ID "/var/cache/nginx" \ 236 | && chown -R $NGINX_ID:$NGINX_ID "/var/log/nginx" \ 237 | && touch "/var/run/nginx.pid" \ 238 | && chown $NGINX_ID:$NGINX_ID "/var/run/nginx.pid" \ 239 | && touch "/var/run/nginx.lock" \ 240 | && chown $NGINX_ID:$NGINX_ID "/var/run/nginx.lock" \ 241 | \ 242 | # Print final built version (for debug purposes) 243 | && echo "" && nginx -V 244 | 245 | # Runtime settings 246 | STOPSIGNAL SIGTERM 247 | CMD ["nginx", "-g", "daemon off;"] 248 | -------------------------------------------------------------------------------- /Dockerfile-geoip: -------------------------------------------------------------------------------- 1 | # Most of the below is based on the Nginx Team's Alpine Dockerfile 2 | # https://github.com/nginxinc/docker-nginx/blob/e3e35236b2c77e02266955c875b74bdbceb79c44/mainline/alpine/Dockerfile 3 | 4 | # --- MaxMind GeoIP Container --- # 5 | FROM ubuntu:focal as geoip 6 | RUN apt-get update && apt-get install geoipupdate -y 7 | COPY GeoIP.conf /etc/GeoIP.conf 8 | RUN geoipupdate -v 9 | 10 | 11 | # --- Nginx Build Container --- # 12 | FROM alpine:3 as builder 13 | 14 | # Nginx Version (See: https://nginx.org/en/CHANGES) 15 | ENV NGINX_VERSION 1.19.4 16 | ENV NGINX_GPG B0F4253373F8F6F510D42178520A9993A1C052F8 17 | 18 | # Nginx User UID/GID 19 | ARG NGINX_ID=6666 20 | 21 | # Nginx build config 22 | ARG CONFIG="\ 23 | --prefix=/etc/nginx \ 24 | --sbin-path=/usr/sbin/nginx \ 25 | --modules-path=/usr/lib/nginx/modules \ 26 | --conf-path=/etc/nginx/nginx.conf \ 27 | --error-log-path=/var/log/nginx/error.log \ 28 | --http-log-path=/var/log/nginx/access.log \ 29 | --pid-path=/var/run/nginx.pid \ 30 | --lock-path=/var/run/nginx.lock \ 31 | --http-client-body-temp-path=/var/cache/nginx/client_temp \ 32 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ 33 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ 34 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ 35 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ 36 | --user=nginx \ 37 | --group=nginx \ 38 | --with-http_ssl_module \ 39 | --with-http_realip_module \ 40 | --with-http_addition_module \ 41 | --with-http_sub_module \ 42 | --with-http_dav_module \ 43 | --with-http_flv_module \ 44 | --with-http_mp4_module \ 45 | --with-http_gunzip_module \ 46 | --with-http_gzip_static_module \ 47 | --with-http_random_index_module \ 48 | --with-http_secure_link_module \ 49 | --with-http_stub_status_module \ 50 | --with-http_auth_request_module \ 51 | --with-http_xslt_module=dynamic \ 52 | --with-http_image_filter_module=dynamic \ 53 | --with-threads \ 54 | --with-stream \ 55 | --with-stream_ssl_module \ 56 | --with-stream_ssl_preread_module \ 57 | --with-stream_realip_module \ 58 | --with-http_slice_module \ 59 | --with-mail \ 60 | --with-mail_ssl_module \ 61 | --with-compat \ 62 | --with-file-aio \ 63 | --with-http_v2_module \ 64 | --with-openssl=/usr/src/boringssl \ 65 | --with-cc-opt=-I'/usr/src/boringssl/.openssl/include/' \ 66 | --add-module=/usr/src/modules/ngx_headers_more \ 67 | --add-module=/usr/src/modules/ngx_subs_filter \ 68 | --add-module=/usr/src/modules/ngx_http_geoip2_module \ 69 | --add-module=/usr/src/modules/ngx_brotli \ 70 | " 71 | 72 | RUN set -xe \ 73 | \ 74 | # Add BoringSSL build deps 75 | && apk add --no-cache --virtual .boringssl-deps \ 76 | build-base \ 77 | cmake \ 78 | git \ 79 | go \ 80 | linux-headers \ 81 | perl \ 82 | \ 83 | # Download and prepare BoringSSL source 84 | && git clone --depth 1 https://boringssl.googlesource.com/boringssl "/usr/src/boringssl" \ 85 | && mkdir "/usr/src/boringssl/build/" \ 86 | && cd "/usr/src/boringssl/build/" \ 87 | && cmake -DCMAKE_BUILD_TYPE=Release ../ \ 88 | && make -j$(getconf _NPROCESSORS_ONLN) \ 89 | && mkdir -p "/usr/src/boringssl/.openssl/lib" \ 90 | && cd "/usr/src/boringssl/.openssl" \ 91 | && ln -s ../include \ 92 | && cd "/usr/src/boringssl" \ 93 | && cp "build/crypto/libcrypto.a" "build/ssl/libssl.a" ".openssl/lib" \ 94 | \ 95 | # Download additional Nginx modules (for each of these we need to include an --add-module line in the Nginx configuration step) 96 | && mkdir -p /usr/src/modules \ 97 | && git clone --depth 1 https://github.com/openresty/headers-more-nginx-module.git /usr/src/modules/ngx_headers_more \ 98 | && git clone --depth 1 https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git /usr/src/modules/ngx_subs_filter \ 99 | && git clone --depth 1 https://github.com/leev/ngx_http_geoip2_module.git /usr/src/modules/ngx_http_geoip2_module \ 100 | && git clone --depth 1 https://github.com/google/ngx_brotli.git /usr/src/modules/ngx_brotli \ 101 | && cd /usr/src/modules/ngx_brotli && git submodule update --init \ 102 | \ 103 | # Download and prepare Nginx 104 | && cd /usr/src \ 105 | && addgroup -S -g $NGINX_ID nginx \ 106 | && adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx -u $NGINX_ID nginx \ 107 | && apk add --no-cache --virtual .build-deps \ 108 | gcc \ 109 | libc-dev \ 110 | make \ 111 | pcre-dev \ 112 | zlib-dev \ 113 | linux-headers \ 114 | curl \ 115 | gnupg \ 116 | libxslt-dev \ 117 | gd-dev \ 118 | libmaxminddb-dev \ 119 | && curl -fSL https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz -o nginx.tar.gz \ 120 | && curl -fSL https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz.asc -o nginx.tar.gz.asc \ 121 | && export GNUPGHOME="$(mktemp -d)" \ 122 | && found=''; \ 123 | for server in \ 124 | ha.pool.sks-keyservers.net \ 125 | hkp://keyserver.ubuntu.com:80 \ 126 | hkp://p80.pool.sks-keyservers.net:80 \ 127 | pgp.mit.edu \ 128 | ; do \ 129 | echo "Fetching GPG key $NGINX_GPG from $server"; \ 130 | gpg --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPG" && found=yes && break; \ 131 | done; \ 132 | test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPG" && exit 1; \ 133 | gpg --batch --verify nginx.tar.gz.asc nginx.tar.gz \ 134 | && rm -rf "$GNUPGHOME" nginx.tar.gz.asc \ 135 | && tar -zxC /usr/src -f nginx.tar.gz \ 136 | && rm nginx.tar.gz \ 137 | && mv -v /usr/src/nginx-$NGINX_VERSION /usr/src/nginx 138 | 139 | # Build debug bits 140 | RUN cd /usr/src/nginx \ 141 | && ./configure $CONFIG --with-debug \ 142 | \ 143 | # Prevent build-error 127 which seems to be caused by the ssl.h file missing: 144 | && mkdir -p /usr/src/boringssl/.openssl/include/openssl/ \ 145 | && touch /usr/src/boringssl/.openssl/include/openssl/ssl.h \ 146 | && make -j$(getconf _NPROCESSORS_ONLN) \ 147 | && mv objs/nginx objs/nginx-debug \ 148 | && mv objs/ngx_http_xslt_filter_module.so objs/ngx_http_xslt_filter_module-debug.so \ 149 | && mv objs/ngx_http_image_filter_module.so objs/ngx_http_image_filter_module-debug.so 150 | 151 | # Build main bits 152 | RUN cd /usr/src/nginx \ 153 | && ./configure $CONFIG \ 154 | \ 155 | # Prevent build-error 127 which seems to be caused by the ssl.h file missing: 156 | && mkdir -p /usr/src/boringssl/.openssl/include/openssl/ \ 157 | && touch /usr/src/boringssl/.openssl/include/openssl/ssl.h \ 158 | && make -j$(getconf _NPROCESSORS_ONLN) 159 | 160 | # Clean some unnecessary source so we're copying less into the next stage 161 | RUN rm -rf /usr/src/boringssl/build 162 | 163 | # Move the source into a single place 164 | RUN mkdir /tmp/buildsource 165 | RUN mv -fv /usr/src/nginx/ /tmp/buildsource/nginx/ 166 | RUN mv -fv /usr/src/modules/ /tmp/buildsource/modules/ 167 | RUN mv -fv /usr/src/boringssl/ /tmp/buildsource/boringssl/ 168 | 169 | # Backup our NGINX_ID environment variable 170 | RUN echo "$NGINX_ID" > /tmp/buildsource/nginx_id 171 | 172 | 173 | # --- Runtime Container --- # 174 | FROM alpine:3 175 | LABEL maintainer "Alex Haydock " 176 | LABEL name "BoringNginx" 177 | LABEL version 1.19.4 178 | 179 | COPY --from=builder /tmp/buildsource /usr/src 180 | # See this page for GeoIP info: https://github.com/leev/ngx_http_geoip2_module#example-usage 181 | COPY --from=geoip /var/lib/GeoIP/GeoLite2-Country.mmdb /var/lib/GeoIP/GeoLite2-Country.mmdb 182 | 183 | RUN set -xe \ 184 | \ 185 | # Set the NGINX_ID environment variable again 186 | && export NGINX_ID="$(cat /usr/src/nginx_id)" \ 187 | \ 188 | # Re-add the Nginx user 189 | && addgroup -S -g $NGINX_ID nginx \ 190 | && adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx -u $NGINX_ID nginx \ 191 | \ 192 | # Add some more deps to install Nginx 193 | && apk add --no-cache --virtual .installdeps binutils make wget \ 194 | \ 195 | # Install Nginx 196 | && cd /usr/src/nginx \ 197 | && make install \ 198 | && rm -rf /etc/nginx/html/ \ 199 | && mkdir /etc/nginx/conf.d/ \ 200 | && mkdir -p /usr/share/nginx/html/ \ 201 | && install -m644 html/index.html /usr/share/nginx/html/ \ 202 | && install -m644 html/50x.html /usr/share/nginx/html/ \ 203 | && install -m755 objs/nginx-debug /usr/sbin/nginx-debug \ 204 | && install -m755 objs/ngx_http_xslt_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_xslt_filter_module-debug.so \ 205 | && install -m755 objs/ngx_http_image_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_image_filter_module-debug.so \ 206 | && ln -s ../../usr/lib/nginx/modules /etc/nginx/modules \ 207 | && strip /usr/sbin/nginx* \ 208 | && strip /usr/lib/nginx/modules/*.so \ 209 | \ 210 | # Bring in gettext so we can get `envsubst`, then throw 211 | # the rest away. To do this, we need to install `gettext` 212 | # then move `envsubst` out of the way so `gettext` can 213 | # be deleted completely, then move `envsubst` back. 214 | && apk add --no-cache --virtual .gettext gettext \ 215 | && mv /usr/bin/envsubst /tmp/ \ 216 | \ 217 | # Work out our runtime dependencies 218 | && runDeps="$( \ 219 | scanelf --needed --nobanner --format '%n#p' /usr/sbin/nginx /usr/lib/nginx/modules/*.so /tmp/envsubst \ 220 | | tr ',' '\n' \ 221 | | sort -u \ 222 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 223 | )" \ 224 | # Install the runtime dependencies as virtual metapackage called ".nginx-rundeps" 225 | && apk add --no-cache --virtual .nginx-rundeps $runDeps \ 226 | \ 227 | # Bring in tzdata so users can set the timezone through environment variables 228 | && apk add --no-cache tzdata \ 229 | \ 230 | # Add the default Nginx config files 231 | # (these are pulled directly from the Nginx team's Docker repo without modification) 232 | && wget https://hg.nginx.org/pkg-oss/raw-file/tip/alpine/nginx.conf -O /etc/nginx/nginx.conf \ 233 | && wget https://hg.nginx.org/pkg-oss/raw-file/tip/alpine/default.conf -O /etc/nginx/conf.d/default.conf \ 234 | \ 235 | # Remove our virtual metapackages 236 | && apk del .installdeps .gettext \ 237 | && mv /tmp/envsubst /usr/local/bin/ \ 238 | \ 239 | # Delete source files to save space in final image 240 | && rm -rf /usr/src/* \ 241 | \ 242 | # Make sure ownership is correct on everything Nginx will need to write to. 243 | # This means we can run the container as the Nginx user if we want to. 244 | && chown -R $NGINX_ID:$NGINX_ID "/etc/nginx" \ 245 | && chown -R $NGINX_ID:$NGINX_ID "/var/cache/nginx" \ 246 | && chown -R $NGINX_ID:$NGINX_ID "/var/log/nginx" \ 247 | && touch "/var/run/nginx.pid" \ 248 | && chown $NGINX_ID:$NGINX_ID "/var/run/nginx.pid" \ 249 | && touch "/var/run/nginx.lock" \ 250 | && chown $NGINX_ID:$NGINX_ID "/var/run/nginx.lock" \ 251 | \ 252 | # Print final built version (for debug purposes) 253 | && echo "" && nginx -V 254 | 255 | # Runtime settings 256 | STOPSIGNAL SIGTERM 257 | CMD ["nginx", "-g", "daemon off;"] 258 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # root trap 2 | ifeq ($(shell id -u),0) 3 | $(error Please do not run this Makefile as root. Please add yourself to the 'docker' group.) 4 | endif 5 | 6 | # the build we push to GitLab can't have the MaxMind GeoIP DB in it without violating the license 7 | .PHONY: build 8 | build: 9 | docker build --pull -t registry.gitlab.com/alexhaydock/boringnginx . 10 | 11 | .PHONY: gitlab 12 | gitlab: 13 | docker push registry.gitlab.com/alexhaydock/boringnginx 14 | 15 | .PHONY: push 16 | push: build gitlab 17 | 18 | # we can build the geo-enabled container locally if we have a MaxMind GeoIP.conf in this directory 19 | .PHONY: geoip 20 | geoip: 21 | docker build --pull -t boringnginx-geo -f Dockerfile-geoip . 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # alexhaydock/boringnginx 2 | 3 | [![pipeline status](https://gitlab.com/alexhaydock/boringnginx/badges/master/pipeline.svg)](https://gitlab.com/alexhaydock/boringnginx/-/commits/master) 4 | 5 | This container builds the [latest stable Nginx](https://nginx.org/en/CHANGES) with the [latest BoringSSL code](https://boringssl.googlesource.com/boringssl/). It was created to aid with the easy deployment of TLS 1.3 services at a time when most Linux distributions were not packaging a version of OpenSSL that could handle it. 6 | 7 | This container is built automatically using GitLab CI and supports the `x86_64` and `aarch64` architectures. 8 | 9 | This container builds Nginx with the following modules: 10 | * [ngx_brotli](https://github.com/google/ngx_brotli.git) 11 | * [ngx_headers_more](https://github.com/openresty/headers-more-nginx-module) 12 | * [ngx_http2_geoip](https://github.com/leev/ngx_http_geoip2_module.git) (when built locally with appropriate `GeoIP.conf`) 13 | * [ngx_subs_filter](https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git) 14 | 15 | There are versions of this container which build against: 16 | * [BoringSSL](https://gitlab.com/alexhaydock/boringnginx) (this container) 17 | * [LibreSSL](https://gitlab.com/alexhaydock/nginx-libressl) 18 | * [OpenSSL](https://gitlab.com/alexhaydock/nginx-openssl) 19 | 20 | ### Quick test this container locally 21 | Run this container as a quick test (it will listen on http://127.0.0.1 and you will see logs directly in the terminal when connections are made): 22 | ``` 23 | docker run --rm -it -p "127.0.0.1:80:80/tcp" registry.gitlab.com/alexhaydock/boringnginx:$(uname -m) 24 | ``` 25 | 26 | ### Running with your own config file 27 | Run this container as a daemon with your own config file: 28 | ``` 29 | docker run -d -p "80:80/tcp" -p "443:443/tcp" -v /path/to/nginx.conf:/etc/nginx.conf:ro registry.gitlab.com/alexhaydock/boringnginx:$(uname -m) 30 | ``` 31 | 32 | ### Build This Container Locally 33 | I cannot distribute the MaxMind GeoIP databases legally with this project, so if you want GeoIP features, you must build this container locally. Sign up for a free account with [MaxMind](https://www.maxmind.com) and follow the instructions to generate your own `GeoIP.conf` and place it in this directory. 34 | 35 | Now run: 36 | ``` 37 | make geoip 38 | ``` 39 | 40 | Or you can build the regular container with just: 41 | ``` 42 | make build 43 | ``` 44 | 45 | ### Running Without Root 46 | You can lock down this container and run without root and dropping all capabilities by using the `--user` and `--cap-drop=ALL` arguments. 47 | 48 | For this example to work, your config file should instruct Nginx to listen on port `8080` inside the container: 49 | ``` 50 | docker run --rm -it -p "80:8080/tcp" --user 6666 --cap-drop=ALL -v /path/to/nginx.conf:/etc/nginx.conf:ro registry.gitlab.com/alexhaydock/boringnginx:$(uname -m) 51 | ``` 52 | 53 | You will need to make sure that the UID you pick matches the one you have set as the `NGINX_ID` in the `Dockerfile`, and that any configs which you mount into the container are owned by this UID (it does not need to exist on the host system). 54 | 55 | If you are running rootless like this, you will also want to ensure that the `nginx.conf` does not try to listen on any ports below `1000` (you can still listen on `:80` and `:443` externally since the Docker daemon runs as root and can handle this - Nginx does not need to). 56 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexhaydock/BoringNginx/703fb9b91c9c72fee6256493e540bb9ad2331454/logo.png --------------------------------------------------------------------------------