From 2f4c44af3d4e5c37058f5449c3c90abe2295a065 Mon Sep 17 00:00:00 2001 From: Mike Lalumiere Date: Mon, 28 Apr 2025 15:07:30 -0400 Subject: [PATCH] Docker container exists for testing geoip2 nginx module --- README.md | 4 ++-- test/.gitignore | 1 + test/Dockerfile | 29 +++++++++++++++++++++++++ test/Makefile | 22 +++++++++++++++++++ test/README.md | 25 ++++++++++++++++++++++ test/cgi-env | 8 +++++++ test/entrypoint | 8 +++++++ test/nginx.conf | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 test/.gitignore create mode 100644 test/Dockerfile create mode 100644 test/Makefile create mode 100644 test/README.md create mode 100755 test/cgi-env create mode 100755 test/entrypoint create mode 100644 test/nginx.conf diff --git a/README.md b/README.md index ee14e89..088527a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Description =========== -**ngx_http_geoip2_module** - creates variables with values from the maxmind geoip2 databases based on the client IP (default) or from a specific variable (supports both IPv4 and IPv6) +**ngx_http_geoip2_module** - creates variables with values from the MaxMind GeoIP2 databases based on the client IP (default) or from a specific variable (supports both IPv4 and IPv6) The module now supports nginx streams and can be used in the same way the http module can be used. @@ -45,7 +45,7 @@ OR ## Download Maxmind GeoLite2 Database (optional) -The free GeoLite2 databases are available from [Maxminds website](http://dev.maxmind.com/geoip/geoip2/geolite2/) (requires signing up) +The free GeoLite2 databases are available from [MaxMind's website](http://dev.maxmind.com/geoip/geoip2/geolite2/) (requires signing up) ## Example Usage: ``` diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..eef5288 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +source/ diff --git a/test/Dockerfile b/test/Dockerfile new file mode 100644 index 0000000..483e987 --- /dev/null +++ b/test/Dockerfile @@ -0,0 +1,29 @@ +FROM ubuntu:noble + +COPY . /test +COPY source /source + +ARG NGINX_VERSION="1.28.0" +ARG GEOIPUPDATE_ACCOUNT_ID +ARG GEOIPUPDATE_EDITION_IDS="GeoLite2-Country GeoLite2-City" +ARG GEOIPUPDATE_LICENSE_KEY_FILE="/build/source/lk.txt" + +# build nginx and geoip2 module +WORKDIR /build +RUN apt-get update && apt-get install -y libterm-readline-gnu-perl python3-launchpadlib software-properties-common \ + && add-apt-repository -y ppa:maxmind/ppa && apt-get update \ + && apt-get install -y build-essential curl libmaxminddb0 libmaxminddb-dev libpcre2-dev mmdb-bin zlib1g-dev \ + && curl -sS -4 http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xvzf - \ + && cd nginx-${NGINX_VERSION} \ + && cp -v ./conf/fastcgi_params /test/ \ + && ./configure --with-compat --add-dynamic-module=/source \ + && make build modules install + +# download maxmind geoip databases +RUN --mount=type=secret,id=GEOIPUPDATE_LICENSE_KEY,target=$GEOIPUPDATE_LICENSE_KEY_FILE \ + apt-get install -y fcgiwrap geoipupdate recode \ + && rm -v /etc/GeoIP.conf \ + && geoipupdate -v -d /usr/share/GeoIP + +# entrypoint runs fcgiwrapper and nginx +ENTRYPOINT /test/entrypoint diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..26ae434 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,22 @@ +LOCAL_PORT ?= 8888 +PACKAGE_NAME ?= ngx_http_geoip2_module +CONTAINER_NAME ?= $(PACKAGE_NAME)-build + +all: clean container run + +clean: + docker rmi -f $(CONTAINER_NAME) + docker rm -f $(CONTAINER_NAME) + +container: source + docker buildx build --build-arg GEOIPUPDATE_ACCOUNT_ID --build-arg GEOIPUPDATE_EDITION_IDS --secret=type=env,id=GEOIPUPDATE_LICENSE_KEY,src=GEOIPUPDATE_LICENSE_KEY --network=host -t "$(CONTAINER_NAME)" . + docker create --name "$(CONTAINER_NAME)" "$(CONTAINER_NAME)" + +run: + docker run -p "$(LOCAL_PORT):80" -it "$(CONTAINER_NAME)" + +source: + mkdir -p ./source + find .. -maxdepth 1 -type f -exec cp -v {} source \; + +.PHONY: clean container run source diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..3971af8 --- /dev/null +++ b/test/README.md @@ -0,0 +1,25 @@ +# ngx_http_geoip2_module Test Container + +This directory contains resources to build a Docker container to test ngx_http_geoip2_module. + +First set GEOIPUPDATE_ACCOUNT_ID and GEOIPUPDATE_LICENSE_KEY environment variables for authentication with MaxMind to download databases. + +For example run a command like the following: +``` +export GEOIPUPDATE_ACCOUNT_ID=12345 GEOIPUPDATE_LICENSE_KEY=$(pass show '/auth/maxmind-license-key') +``` + +Then run `make` or `make container run` in this directory to build and start the container. + +The container exposes Nginx on local port 8888. Make requests in the form http://localhost:8888/$IP to test out the geoip2 module. The IP provided as part of the path is passed to the geoip2 module. The default endpoint prints its environment including variables prefixed with GEOIP2 set by the geoip2 module. + +For example: + +``` +$> curl -fsS localhost:8888/$(curl -sS ident.me) | grep GEOIP2 +GEOIP2_CITY_EPOCH=1745917200 +GEOIP2_CITY_NAME=Haverhill +GEOIP2_COUNTRY_CODE=US +GEOIP2_COUNTRY_EPOCH=1745917530 +GEOIP2_COUNTRY_NAME=United States +``` diff --git a/test/cgi-env b/test/cgi-env new file mode 100755 index 0000000..084d5f0 --- /dev/null +++ b/test/cgi-env @@ -0,0 +1,8 @@ +#!/bin/bash +# cgi-env writes an HTML page listing current environment variables +cgi-env() { + local body=$(env -0 | sort -z | xargs -0 printf "%s\n"| recode ascii..html) + printf "Content-type: text/html\\n\\n" + printf "\\ncgi-env\\n\\n
\\n%s\\n
\\n\\n\\n" "$body" +} +if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then cgi-env "$@"; fi diff --git a/test/entrypoint b/test/entrypoint new file mode 100755 index 0000000..0a798e1 --- /dev/null +++ b/test/entrypoint @@ -0,0 +1,8 @@ +#!/bin/bash + +sock="/var/run/fcgiwrap.socket" +fcgiwrap -s unix:"$sock" -c 2 -f & +sleep 1 +chown www-data: "$sock" +/usr/local/nginx/sbin/nginx -c /test/nginx.conf & +wait diff --git a/test/nginx.conf b/test/nginx.conf new file mode 100644 index 0000000..2c6850e --- /dev/null +++ b/test/nginx.conf @@ -0,0 +1,57 @@ +load_module modules/ngx_http_geoip2_module.so; + +user www-data www-data; + +events { + worker_connections 768; + multi_accept on; +} + +http { + access_log /test/access.log; + error_log /test/error.log; + + map $check $empty { + default 1; + "~^.+$" 0; + } + + geoip2 /usr/share/GeoIP/GeoLite2-City.mmdb { + auto_reload 5m; + $geoip2_city_epoch metadata build_epoch; + $geoip2_city_name source=$arg city names en; + } + + geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb { + auto_reload 5m; + $geoip2_country_epoch metadata build_epoch; + $geoip2_country_code source=$arg country iso_code; + $geoip2_country_name source=$arg country names en; + } + + server { + listen 80 default_server; + listen [::]:80 default_server; + + location ~ /(.+)$ { + gzip off; + set $arg $1; + root /test/; + include fastcgi_params; + + set $check "$geoip2_country_code"; + if ($empty) { + return 404; + } + + fastcgi_pass unix:/var/run/fcgiwrap.socket; + fastcgi_param SCRIPT_FILENAME $document_root/cgi-env; + + fastcgi_param GEOIP2_CITY_EPOCH $geoip2_city_epoch; + fastcgi_param GEOIP2_CITY_NAME $geoip2_city_name; + fastcgi_param GEOIP2_COUNTRY_CODE $geoip2_country_code; + fastcgi_param GEOIP2_COUNTRY_EPOCH $geoip2_country_epoch; + fastcgi_param GEOIP2_COUNTRY_NAME $geoip2_country_name; + } + } +}