The Problem
I have a web-application that I want to containerize with docker and reverse-proxy via nginx. This web application shall receive uploads of audio files (~200-500Mb), thus I want upload progress events while uploading to be sent to the client.
I decided to base my docker image (see dockerfile below) on an alpine base that also contains glibc. From there the idea was to install nginx from the alpine repositories and use the nginx upload progress module to send the progress events. This module is compiled into the nginx module on alpine by default (See Alpine Repository)!
Thus, I created a simple nginx.conf
file (see below) that just enables the upload_progress uploads 1m;
directive in the http-block and made sure it gets copied into the container to /etc/nginx/nginx.conf
.
I then started the container, installed nginx through apk
and ran nginx -t
. However, the conf file fails the test with this error message:
/ # nginx -t
nginx: [emerg] unknown directive "upload_progress" in /etc/nginx/nginx.conf:10
nginx: configuration file /etc/nginx/nginx.conf test failed
Troubleshooting so far
The error indicates that the binary does not have the upload progress module compiled in. However, this goes contrary to what is documented on the alpine repositories.
I also validated that the module is present in the binary by running a docker container with -i
and executing nginx -V
inside it to get a dump of all the modules and flags it was compiled with. It contains the necessary --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-upload-progress-module-0.9.2/
as expected (see nginx -V dump below).
The nginx.conf is not the issue. When I run the given nginx conf file locally where I have compiled the upload progress module into nginx, it runs fine.
So now I’m left confused, what am I doing wrong? Why can’t I use the upload_progress
directive when the module exists in the nginx binary?
dockerfile
FROM frolvlad/alpine-glibc
# Install dependencies
RUN apk update
RUN apk add --no-cache openrc nginx sqlite-libs
COPY ./nginx.conf /etc/nginx/nginx.conf
nginx.conf
# nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
upload_progress uploads 1m;
types_hash_max_size 4096;
client_max_body_size 1000M;
sendfile on;
keepalive_timeout 600;
server {
server_name aldrune.com;
autoindex off;
listen 80;
root /frontend;
location /session_audio/ {
#CORS
add_header Access-Control-Allow-Origin '*';
alias /audiomedia/;
}
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
nginx -V dump
/ # nginx -V
nginx version: nginx/1.22.0
built with OpenSSL 1.1.1o 3 May 2022
TLS SNI support enabled
configure arguments: --prefix=/var/lib/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --pid-path=/run/nginx/nginx.pid --lock-path=/run/nginx/nginx.lock --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --with-perl_modules_path=/usr/lib/perl5/vendor_perl --user=nginx --group=nginx --with-threads --with-file-aio --without-pcre2 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_realip_module --with-stream_geoip_module=dynamic --with-stream_ssl_preread_module --add-dynamic-module=/home/buildozer/aports/main/nginx/src/njs-0.7.4/nginx --add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_devel_kit-0.3.1/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/traffic-accounting-nginx-module-2.0/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/array-var-nginx-module-0.05/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_brotli-1.0.0rc/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_cache_purge-2.5.1/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx_cookie_flag_module-1.1.0/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-dav-ext-module-3.0.0/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/echo-nginx-module-0.62/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/encrypted-session-nginx-module-0.09/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx-fancyindex-0.5.2/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_http_geoip2_module-3.3/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/headers-more-nginx-module-0.33/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-log-zmq-1.0.0/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/lua-nginx-module-0.10.21/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/lua-upstream-nginx-module-0.07/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/naxsi-1.3/naxsi_src --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nchan-1.2.8/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/redis2-nginx-module-0.15/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/set-misc-nginx-module-0.33/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-http-shibboleth-2.0.1/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_http_untar_module-1.1/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-upload-progress-module-0.9.2/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-upstream-fair-0.1.3/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_upstream_jdomain-1.3.0/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-vod-module-1.29/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-module-vts-0.1.18/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/mod_zip-1.2.0/ --add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-rtmp-module-1.2.2/
2
Answers
@Ivan Shatsky provided the accepted solution, I just wanted to be more explicit of what exactly I did for others reading in the future.
On alpine you can pretty easily install nginx modules since they are provided in the repositories. The module in question for me for example is here.
Thus you can simply run
apk add nginx-mod-http-upload-progress
and you'll get the so file you need.apk
installs those under/usr/lib/nginx/modules/ngx_http_uploadprogress_module.so
.Knowing this, you can add the
load_module
command as Ivan suggested:load_module /usr/lib/nginx/modules/ngx_http_uploadprogress_module.so;
Yes, it isn’t. You compile it as a dynamic module using
configure script parameter, so you need to load it dynamically using the
load_module
directive:at the top configuration level before you were able to use it (or compile it into nginx binary as a static module).