Nginx in Docker with GeoIP¶
To use the GeoIP2 module. We pretty much need to use a Dockerfile to start with the latest nginx, but then compile the GeoIP2 module from source. This is preferred because using precompiled binaries is actually challenging - we have to ensure we get the binary that was compiled with the same nginx version that we have. Compiling the module ourselves actually simplifies this process.
FROM nginx:latest
# Install dependencies
RUN apt-get update && apt-get install -y \
wget \
git \
curl \
unzip \
libmaxminddb-dev \
build-essential \
libpcre3 \
libpcre3-dev \
zlib1g-dev \
libssl-dev
# Download Nginx source matching installed version
RUN nginx_version=$(nginx -v 2>&1 | awk -F/ '{print $2}') && \
wget http://nginx.org/download/nginx-${nginx_version}.tar.gz && \
tar -xzvf nginx-${nginx_version}.tar.gz && \
cd nginx-${nginx_version} && \
git clone https://github.com/leev/ngx_http_geoip2_module.git
# Configure, compile, and install the module
RUN cd nginx-$(nginx -v 2>&1 | awk -F/ '{print $2}') && \
./configure --with-compat --add-dynamic-module=ngx_http_geoip2_module && \
make modules && \
cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
# Cleanup
RUN rm -rf /var/lib/apt/lists/* nginx-* ngx_http_geoip2_module
CMD ["nginx", "-g", "daemon off;"]
FROM nginx:alpine
# Install necessary packages
RUN apk add --no-cache \
build-base \
pcre-dev \
zlib-dev \
linux-headers \
libressl-dev \
libmaxminddb-dev \
git
# Download Nginx source code matching installed version
RUN nginx_version=$(nginx -v 2>&1 | awk -F/ '{print $2}') && \
wget http://nginx.org/download/nginx-${nginx_version}.tar.gz && \
tar -xzf nginx-${nginx_version}.tar.gz && \
cd nginx-${nginx_version} && \
git clone https://github.com/leev/ngx_http_geoip2_module.git
# Build the module
RUN cd nginx-$(nginx -v 2>&1 | awk -F/ '{print $2}') && \
./configure --with-compat --add-dynamic-module=ngx_http_geoip2_module && \
make modules && \
cp objs/ngx_http_geoip2_module.so /etc/nginx/modules/
# Cleanup
RUN rm -rf /var/cache/apk/* nginx-* ngx_http_geoip2_module
CMD ["nginx", "-g", "daemon off;"]
services:
nginx:
build: .
container_name: nginx
network_mode: "host"
volumes:
# conf files
- ./nginx.conf:/etc/nginx/nginx.conf
# SSL certs
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
# logs
- ./data/nginx/logs:/var/log/nginx
# optional confs
- ./conf.d:/etc/nginx/conf.d
# GeoIP database location
- ./data/geoip2:/usr/share/GeoIP
# command: >
# /bin/sh -c "apk add --no-cache nginx-mod-http-geoip2=1.26.3-r1 && nginx -g 'daemon off;'"
# if not running on host network, expose ports
# ports:
# - "80:80"
# - "443:443"
depends_on:
- certbot
- geoip-updater
geoip-updater:
image: maxmindinc/geoipupdate:latest
container_name: geoip-updater
volumes:
- ./data/geoip2:/usr/share/GeoIP
environment:
GEOIPUPDATE_ACCOUNT_ID: ${GEOIP_ACCOUNT_ID}
GEOIPUPDATE_LICENSE_KEY: ${GEOIP_LICENSE_KEY}
GEOIPUPDATE_EDITION_IDS: ${GEOIP_EDITION_IDS}
restart: on-failure
certbot:
image: certbot/dns-cloudflare # Certbot with Cloudflare DNS plugin
container_name: certbot
network_mode: "host"
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
- ./cloudflare.ini:/etc/letsencrypt/cloudflare.ini # Cloudflare credentials
entrypoint: >
/bin/sh -c "
certbot certonly --non-interactive --quiet --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
--email ${EMAIL} --agree-tos --no-eff-email --expand \
--domains ${DOMAINS};
while :; do
certbot renew --non-interactive --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini;
sleep 24h;
done"
Timers on host
Hot reload nginx
Update the GeoIP database (simply taking the container back up)
/usr/bin/docker exec certbot certbot renew --non-interactive --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini;
Frequently used commands¶
Prune docker images
Docker compose up with build