diff --git a/modules/Dockerfile b/modules/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..9ea6df85a079979a74ae26759d9f4c8e963d7ced --- /dev/null +++ b/modules/Dockerfile @@ -0,0 +1,67 @@ +FROM nginx:mainline as builder + +ARG ENABLED_MODULES + +RUN set -ex \ + && if [ "$ENABLED_MODULES" = "" ]; then \ + echo "No additional modules enabled, exiting"; \ + exit 1; \ + fi + +COPY ./ /modules/ + +RUN set -ex \ + && apt update \ + && apt install -y --no-install-suggests --no-install-recommends \ + patch make wget mercurial devscripts debhelper dpkg-dev \ + quilt lsb-release build-essential libxml2-utils xsltproc \ + equivs git g++ \ + && hg clone https://hg.nginx.org/pkg-oss/ \ + && cd pkg-oss \ + && mkdir /tmp/packages \ + && for module in $ENABLED_MODULES; do \ + echo "Building $module for nginx-$NGINX_VERSION"; \ + if [ -d /modules/$module ]; then \ + echo "Building $module from user-supplied sources"; \ + # check if module sources file is there and not empty + if [ ! -s /modules/$module/source ]; then \ + echo "No source file for $module in modules/$module/source, exiting"; \ + exit 1; \ + fi; \ + # some modules require build dependencies + if [ -f /modules/$module/build-deps ]; then \ + echo "Installing $module build dependencies"; \ + apt update && apt install -y --no-install-suggests --no-install-recommends $(cat /modules/$module/build-deps | xargs); \ + fi; \ + # if a module has a build dependency that is not in a distro, provide a + # shell script to fetch/build/install those + # note that shared libraries produced as a result of this script will + # not be copied from the builder image to the main one so build static + if [ -x /modules/$module/prebuild ]; then \ + echo "Running prebuild script for $module"; \ + /modules/$module/prebuild; \ + fi; \ + /pkg-oss/build_module.sh -v $NGINX_VERSION -f -y -o /tmp/packages -n $module $(cat /modules/$module/source); \ + elif make -C /pkg-oss/debian list | grep -P "^$module\s+\d" > /dev/null; then \ + echo "Building $module from pkg-oss sources"; \ + cd /pkg-oss/debian; \ + make rules-module-$module BASE_VERSION=$NGINX_VERSION; \ + mk-build-deps --install --tool="apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes" debuild-module-$module/nginx-$NGINX_VERSION/debian/control; \ + make module-$module BASE_VERSION=$NGINX_VERSION; \ + find ../../ -maxdepth 1 -mindepth 1 -type f -name "*.deb" -exec mv -v {} /tmp/packages/ \;; \ + else \ + echo "Don't know how to build $module module, exiting"; \ + exit 1; \ + fi; \ + done + +FROM nginx:mainline +ARG ENABLED_MODULES +COPY --from=builder /tmp/packages /tmp/packages +RUN set -ex \ + && apt update \ + && for module in $ENABLED_MODULES; do \ + apt install --no-install-suggests --no-install-recommends -y /tmp/packages/nginx-module-${module}_${NGINX_VERSION}*.deb; \ + done \ + && rm -rf /tmp/packages \ + && rm -rf /var/lib/apt/lists/ diff --git a/modules/Dockerfile.alpine b/modules/Dockerfile.alpine new file mode 100644 index 0000000000000000000000000000000000000000..b2b8b3e3f68d9dc94b4935db87af74bd61e0d1e0 --- /dev/null +++ b/modules/Dockerfile.alpine @@ -0,0 +1,67 @@ +FROM nginx:mainline-alpine as builder + +ARG ENABLED_MODULES + +RUN set -ex \ + && if [ "$ENABLED_MODULES" = "" ]; then \ + echo "No additional modules enabled, exiting"; \ + exit 1; \ + fi + +COPY ./ /modules/ + +RUN set -ex \ + && apk update \ + && apk add linux-headers openssl-dev pcre-dev zlib-dev openssl abuild \ + musl-dev libxslt libxml2-utils make mercurial gcc unzip git \ + xz g++ \ + # allow abuild as a root user \ + && printf "#!/bin/sh\\n/usr/bin/abuild -F \"\$@\"\\n" > /usr/local/bin/abuild \ + && chmod +x /usr/local/bin/abuild \ + && hg clone https://hg.nginx.org/pkg-oss/ \ + && cd pkg-oss \ + && mkdir /tmp/packages \ + && for module in $ENABLED_MODULES; do \ + echo "Building $module for nginx-$NGINX_VERSION"; \ + if [ -d /modules/$module ]; then \ + echo "Building $module from user-supplied sources"; \ + # check if module sources file is there and not empty + if [ ! -s /modules/$module/source ]; then \ + echo "No source file for $module in modules/$module/source, exiting"; \ + exit 1; \ + fi; \ + # some modules require build dependencies + if [ -f /modules/$module/build-deps ]; then \ + echo "Installing $module build dependencies"; \ + apk update && apk add $(cat /modules/$module/build-deps | xargs); \ + fi; \ + # if a module has a build dependency that is not in a distro, provide a + # shell script to fetch/build/install those + # note that shared libraries produced as a result of this script will + # not be copied from the builder image to the main one so build static + if [ -x /modules/$module/prebuild ]; then \ + echo "Running prebuild script for $module"; \ + /modules/$module/prebuild; \ + fi; \ + /pkg-oss/build_module.sh -v $NGINX_VERSION -f -y -o /tmp/packages -n $module $(cat /modules/$module/source); \ + elif make -C /pkg-oss/alpine list | grep -E "^$module\s+\d+" > /dev/null; then \ + echo "Building $module from pkg-oss sources"; \ + cd /pkg-oss/alpine; \ + make abuild-module-$module BASE_VERSION=$NGINX_VERSION; \ + apk add $(. ./abuild-module-$module/APKBUILD; echo $makedepends;); \ + make module-$module BASE_VERSION=$NGINX_VERSION; \ + find ~/packages -type f -name "*.apk" -exec mv -v {} /tmp/packages/ \;; \ + else \ + echo "Don't know how to build $module module, exiting"; \ + exit 1; \ + fi; \ + done + +FROM nginx:mainline-alpine +ARG ENABLED_MODULES +COPY --from=builder /tmp/packages /tmp/packages +RUN set -ex \ + && for module in $ENABLED_MODULES; do \ + apk add --no-cache --allow-untrusted /tmp/packages/nginx-module-${module}-${NGINX_VERSION}*.apk; \ + done \ + && rm -rf /tmp/packages diff --git a/modules/README.md b/modules/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8680022eb4e11401e2f50f3fab4a67b0ee99ef29 --- /dev/null +++ b/modules/README.md @@ -0,0 +1,83 @@ +# Adding third-party modules to nginx official image + +It's possible to extend a mainline image with third-party modules either from +your own instuctions following a simple filesystem layout/syntax using +`build_module.sh` helper script, or failing back to package sources from +`https://hg.nginx.org/pkg-oss`. + +## Usage + +``` +$ docker build --build-arg ENABLED_MODULES="ndk lua" -t my-nginx-with-lua . +``` +This command will attempt to build an image called `my-nginx-with-lua` based on +official nginx docker hub image with two modules: `ndk` and `lua`. +By default, a Debian-based image will be used. If you wish to use Alpine +instead, add `-f Dockerfile.alpine` to the command line. + +The build script will look for module build definition files on filesystem +directory under the same name as the module (and resulting package) and if +those are not found will try to look up requested modules in the pkg-oss +repository. + +For well-known modules we maintain a set of build sources packages over at +`pkg-oss`, so it's probably a good idea to rely on those instead of providing +your own implementation. + +As of the time of writing this README, the following modules and their versions +are available from `pkg-oss` repository: + +``` +/pkg-oss $ LC_ALL=C make -C debian list-all-modules +make: Entering directory '/pkg-oss/debian' +brotli 1.0.0-1 +encrypted-session 0.08-1 +geoip 1.19.6-1 +geoip2 3.3-1 +headers-more 0.33-1 +image-filter 1.19.6-1 +lua 0.10.19-1 +modsecurity 1.0.1-1 +ndk 0.3.1-1 +njs 0.5.0-1 +opentracing 0.10.0-1 +passenger 6.0.6-1 +perl 1.19.6-1 +rtmp 1.2.1-1 +set-misc 0.32-1 +subs-filter 0.6.4-1 +xslt 1.19.6-1 +make: Leaving directory '/pkg-oss/debian' +``` + +If you still want to provide your own instructions for a specific module, +organize the build directory in a following way, e.g. for `echo` module: + +``` +docker-nginx/modules $ tree echo +echo +├── build-deps +├── prebuild +└── source + +0 directories, 3 files +``` + +The scripts expect one file to always exist for a module you wish to build +manually: `source`. It should contain a link to a zip/tarball source code of a +module you want to build. In `build-deps` you can specify build dependencies +for a module as found in Debian or Alpine repositories. `prebuild` is a shell +script (make it `chmod +x prebuild`!) that will be executed prior to building +the module but after installing the dependencies, so it can be used to install +additional build dependencies if they are not available from Debian or Alpine. +Keep in mind that those dependencies wont be automatically copied to the +resulting image and if you're building a library, build it statically. + +Once the build is done in the builder image, the built packages are copied over +to resulting image and installed via apt/apk. The resulting image will be +tagged and can be used the same way as an official docker hub image. + +Note that we can not provide any support for those modifications and in no way +guarantee they will work as nice as a build without third-party modules. If +you encounter any issues running your image with the modules enabled, please +reproduce with a vanilla image first. diff --git a/modules/echo/build-deps b/modules/echo/build-deps new file mode 100644 index 0000000000000000000000000000000000000000..1ccfbc2f47dcc52f33efec2c92339ebca0e6efbc --- /dev/null +++ b/modules/echo/build-deps @@ -0,0 +1 @@ +make gcc diff --git a/modules/echo/prebuild b/modules/echo/prebuild new file mode 100755 index 0000000000000000000000000000000000000000..cd2864b05d58973bc07472728f0d740570889574 --- /dev/null +++ b/modules/echo/prebuild @@ -0,0 +1,12 @@ +#!/bin/sh + +# if a module has a build dependency that is not in debian/alpine +# use this script to fetch/build/install them +# +# note that shared libraries produced as a result of this script will +# not be copied from the builder image to the resulting one, so you need to +# build them statically + +echo "No prebuild stage required - all dependencies are satisfied already!" + +exit 0 diff --git a/modules/echo/source b/modules/echo/source new file mode 100644 index 0000000000000000000000000000000000000000..3a6ad274d57a580175bf9386bab4b0612e5bec9d --- /dev/null +++ b/modules/echo/source @@ -0,0 +1 @@ +https://github.com/openresty/echo-nginx-module/archive/v0.62.tar.gz