11

I need to use the random number generator from this library, but I wanted to use the official nginx image, so I was trying to see its source code and perform the changes required to have this library installed.

But I am at loss, as the instructions don't seem to fit with the way NGINX is being installed in that Dockerfile.

How can I install set-misc-nginx within the official NGINX Dockerfile?

PedroD
  • 5,670
  • 12
  • 46
  • 84

1 Answers1

21

You can extend the official ngnix to build the dynamic modules then load them in nginx:

# syntax=docker/dockerfile:experimental
ARG NGINX_VERSION
FROM nginx:${NGINX_VERSION} as build

RUN apt-get update && \
    apt-get install -y \
        openssh-client \
        git \
        wget \
        libxml2 \
        libxslt1-dev \
        libpcre3 \
        libpcre3-dev \
        zlib1g \
        zlib1g-dev \
        openssl \
        libssl-dev \
        libtool \
        automake \
        gcc \
        g++ \
        make && \
    rm -rf /var/cache/apt

RUN wget "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" && \
    tar -C /usr/src -xzvf nginx-${NGINX_VERSION}.tar.gz

RUN mkdir -p -m 0600 ~/.ssh && \
    ssh-keyscan github.com >> ~/.ssh/known_hosts

WORKDIR /src/ngx_devel_kit
RUN --mount=type=ssh git clone git@github.com:simpl/ngx_devel_kit .

WORKDIR /src/set-misc-nginx-module
RUN --mount=type=ssh git clone git@github.com:openresty/set-misc-nginx-module.git .

WORKDIR /usr/src/nginx-${NGINX_VERSION}
RUN NGINX_ARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p') \
    ./configure --with-compat --with-http_ssl_module --add-dynamic-module=/src/ngx_devel_kit --add-dynamic-module=/src/set-misc-nginx-module ${NGINX_ARGS} && \
    make modules

FROM nginx:${NGINX_VERSION}

COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build /usr/src/nginx-${NGINX_VERSION}/objs/ngx_http_set_misc_module.so /usr/src/nginx-${NGINX_VERSION}/objs/ndk_http_module.so /usr/lib/nginx/modules/

Note: this example is a multi-staged build that uses the docker build enhancements to clone the repositories (depending on your version of docker you may have to enable experimental features).

You can load the modules in the nginx.conf that's copied in the final image:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

load_module /usr/lib/nginx/modules/ndk_http_module.so;
load_module /usr/lib/nginx/modules/ngx_http_set_misc_module.so;

events {
    worker_connections  1024;
}

http {
    ...
}

Build the image: DOCKER_BUILDKIT=1 docker build --rm --ssh=default --build-arg NGINX_VERSION=1.17.3 --network host -t so:57739560 .

Run the container: docker run --rm -it -p 80:80 so:57739560

For another example of building dynamic modules using the official nginx image you can check out my nginx-modsecurity repo (nginx image extended with Modsecurity and Modsecurity-nginx).

Christoph Kluge
  • 1,947
  • 8
  • 23
masseyb
  • 3,745
  • 1
  • 17
  • 29
  • wow , thanks for the answer, so much new stuff to learn! I have one question: If you are coming `FROM nginx:${NGINX_VERSION}`, why are you downloading nginx again in this command `RUN wget "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" && ...`? – PedroD Sep 01 '19 at 14:39
  • @PedroD I’m downloading the sources of the same version as the image for the build stage to `make` the modules. – masseyb Sep 01 '19 at 14:53
  • 1
    @Christoph Kluge thanks for the edit, noticed that as well but never got around to updating it. – masseyb Nov 10 '20 at 11:59
  • Are we really extending the official image ? We are just building again a new nginx in it, no ? – hzrari Jan 22 '21 at 10:54
  • 1
    The modules are built in the first stage and extend the [official nginx image](https://hub.docker.com/_/nginx) in the second stage in docker speaking, note the second `FROM nginx:${NGINX_VERSION}` in the `Dockerfile`. In a multi-staged build this is basically "starting from a new copy of the official nginx image and add the modules that we just built in it", we don't rebuild nginx in the final stage. – masseyb Jan 22 '21 at 11:02
  • hum, cool, I have got the hint. I will try to follow the same logic. I need to build nginx with modsecurity and lua, based on alpine, with crontab and certbot of Let'sEncrypt :-) – hzrari Jan 22 '21 at 11:17
  • You can clone my [`nginx-modsecurity`](https://github.com/masseybradley/nginx-modsecurity) as a starting point, just pass the `NGINX_VERSION` `--build-arg` as a i.e. `-alpine` tag and change the `apt-get install`'s with `apk` install's. Shouldn't be too hard to adapt. – masseyb Jan 22 '21 at 11:25
  • 1
    Yes, thanks. I started from your Dockerfile, and I am adapting it, because https://github.com/SpiderLabs/owasp-modsecurity-crs migrated to https://github.com/coreruleset/coreruleset I will publish mine when I finish – hzrari Jan 22 '21 at 11:33