Skip to content

Instantly share code, notes, and snippets.

@hermanbanken
Last active April 22, 2024 10:53
Show Gist options
  • Save hermanbanken/96f0ff298c162a522ddbba44cad31081 to your computer and use it in GitHub Desktop.
Save hermanbanken/96f0ff298c162a522ddbba44cad31081 to your computer and use it in GitHub Desktop.
Compiling NGINX module as dynamic module for use in docker

Compiling NGINX module as dynamic module for use in docker

NGINX offers some very convenient Docker containers, but it is not documented how to extend the functionality of those containers without re-compiling NGINX yourself and continuously adapting your Dockerfile to match the ones in https://github.com/nginxinc/docker-nginx/.

This gist offers a way to build a NGINX ‘dynamic module’ against the widely used “nginx:alpine” docker image. Simply copy this Dockerfile & replace the arguments of the “wget” & “tar” & “configure” commands to include the module you want to build, then adjust the COPY command copying the module (.so file). In this example the NCHAN module is used as an example.

If you found this helpful, please leave a comment / reaction here! :love:

FROM nginx:alpine AS builder
# nginx:alpine contains NGINX_VERSION environment variable, like so:
# ENV NGINX_VERSION 1.15.0
# Our NCHAN version
ENV NCHAN_VERSION 1.1.15
# Download sources
RUN wget "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" -O nginx.tar.gz && \
wget "https://github.com/slact/nchan/archive/v${NCHAN_VERSION}.tar.gz" -O nchan.tar.gz
# For latest build deps, see https://github.com/nginxinc/docker-nginx/blob/master/mainline/alpine/Dockerfile
RUN apk add --no-cache --virtual .build-deps \
gcc \
libc-dev \
make \
openssl-dev \
pcre-dev \
zlib-dev \
linux-headers \
curl \
gnupg \
libxslt-dev \
gd-dev \
geoip-dev
# Reuse same cli arguments as the nginx:alpine image used to build
RUN CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p') \
tar -zxC /usr/src -f nginx.tar.gz && \
tar -xzvf "nchan.tar.gz" && \
NCHANDIR="$(pwd)/nchan-${NCHAN_VERSION}" && \
cd /usr/src/nginx-$NGINX_VERSION && \
./configure --with-compat $CONFARGS --add-dynamic-module=$NCHANDIR && \
make && make install
FROM nginx:alpine
# Extract the dynamic module NCHAN from the builder image
COPY --from=builder /usr/local/nginx/modules/ngx_nchan_module.so /usr/local/nginx/modules/ngx_nchan_module.so
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]
# Addition: load NCHAN
load_module /usr/local/nginx/modules/ngx_nchan_module.so;
user nginx;
worker_processes 5; # Addition: ultiple workers for NCHAN
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
@donlinglok
Copy link

Thanks @hermanbanken and everyone else commenting in this gist. 👍 Very helpful resource, in this hellhole 😡 of trying to compile NGINX with additional/patched modules.

In case it helps anyone else, here is my current Docker build to:

great script, here is my script of geoip:

FROM nginx:alpine AS builder

# nginx:alpine contains NGINX_VERSION environment variable, like so:
# ENV NGINX_VERSION 1.15.0

# Additional module version
ENV PROXY_CONNECT_VERSION 3.4

# For latest build deps, see https://github.com/nginxinc/docker-nginx/blob/master/mainline/alpine/Dockerfile
RUN apk add --no-cache --virtual .build-deps \
  git \
  gcc \
  libc-dev \
  make \
  openssl-dev \
  pcre2-dev \
  zlib-dev \
  linux-headers \
  libxslt-dev \
  gd-dev \
  geoip-dev \
  libedit-dev \
  bash \
  alpine-sdk \
  findutils \ 
  automake \ 
  autoconf \ 
  libtool

# Download sources
RUN wget "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" -O nginx.tar.gz && \
    git clone --recursive https://github.com/maxmind/libmaxminddb && \
    git clone https://github.com/leev/ngx_http_geoip2_module

RUN cd libmaxminddb && \
    ./bootstrap && \
    ./configure && \
    make && make install

# Reuse same cli arguments as the nginx:alpine image used to build (but remove the erroneous -fomit-frame-pointer)
RUN CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p') && \
    CONFARGS=${CONFARGS/-Os -fomit-frame-pointer -g/-Os} && \
    mkdir -p /usr/src && \
    tar -zxC /usr/src -f nginx.tar.gz && \
    cd /usr/src/nginx-$NGINX_VERSION && \
    ./configure --add-dynamic-module=/ngx_http_geoip2_module && \
    make && make install

FROM nginx:alpine
# Copy new dynamic module ngx_http_geoip2_module
COPY --from=builder /usr/lib/nginx/modules/ngx_http_geoip_module.so /usr/lib/nginx/modules/ngx_http_geoip_module.so
# Copy new nginx binary, due to patching for ngx_http_geoip2_module
COPY --from=builder /usr/sbin/nginx /usr/sbin/nginx

RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 8080
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment