The official nginx image with PageSpeed, brotli and Lua. nginx is rebuilt from the nginx.org source package, so paths, configuration layout and entrypoint behaviour are the same as in the official image.
Includes:
- nginx (mainline on
master, stable on thestablebranch), statically linked against a current OpenSSL - PageSpeed as a dynamic module, built from source against the exact nginx version (the maintained continuation of the archived Apache ngx_pagespeed)
- ngx_brotli with a statically built brotli
- ngx_devel_kit and lua-nginx-module with LuaJIT, lua-resty-core and lua-resty-lrucache
All versions are pinned at the top of the Dockerfile. Builds are available for linux/amd64 and linux/arm64.
docker pull hitko/nginx-pagespeed:latestImage tags follow nginx: odd minor versions (1.31.x) are mainline and tagged latest, mainline, x.x.x and x.x; even minor versions (1.30.x) are stable and tagged stable, x.x.x and x.x.
Serve a directory with PageSpeed enabled:
docker run --rm -p 80:80 \
-v /path/to/site:/usr/share/nginx/html:ro \
-v /path/to/default.conf:/etc/nginx/conf.d/default.conf:ro \
hitko/nginx-pagespeed:latestrestart: always ensures that the container is automatically restarted by Docker in cases like a Docker service or host restart or container exit. The PageSpeed cache lives on a volume so it survives restarts.
services:
nginx:
restart: always
image: hitko/nginx-pagespeed:latest
container_name: nginx
ports:
- "80:80"
volumes:
- /path/to/site:/usr/share/nginx/html:ro
- /path/to/default.conf:/etc/nginx/conf.d/default.conf:ro
- pagespeed-cache:/var/cache/ngx_pagespeed
volumes:
pagespeed-cache:docker compose up -d nginx
You're done!
Enable PageSpeed in /etc/nginx/conf.d/default.conf. Existing pagespeed directives from ngx_pagespeed keep working; see the PageSpeed documentation for the full list of filters and options.
server {
listen 80;
root /usr/share/nginx/html;
pagespeed on;
pagespeed FileCachePath /var/cache/ngx_pagespeed;
}Enable brotli compression alongside gzip:
server {
listen 80;
root /usr/share/nginx/html;
brotli on;
brotli_types text/plain text/css application/javascript application/json image/svg+xml;
brotli_static on;
}Run Lua in a location:
server {
listen 80;
location /hello {
default_type text/plain;
content_by_lua_block {
ngx.say("hello from ", jit.version)
}
}
}Bring your own nginx.conf. PageSpeed is a dynamic module and nginx only loads those through a load_module directive. The image's own nginx.conf has it, and on start a hook adds it to a mounted nginx.conf that lacks it:
load_module modules/ngx_pagespeed_module.so;
The hook edits the file in place, so a writable bind-mounted nginx.conf is changed on the host as well (once). A read-only mount (:ro) is left alone with a warning; add the line yourself in that case.
The variables of the official nginx image (templates, NGINX_ENTRYPOINT_QUIET_LOGS, ...) work unchanged. In addition:
- 1 => add
load_module modules/ngx_pagespeed_module.so;to/etc/nginx/nginx.confon start if it is missing - 0 => never touch
nginx.conf
The PageSpeed stage compiles the whole PageSpeed library with Bazel and is slow (tens of minutes) and memory hungry (roughly 1.5 GB per job). Cap it on small machines:
docker build --build-arg PAGESPEED_JOBS=4 -t nginx-pagespeed .For a multi-arch image:
docker buildx build --platform linux/amd64,linux/arm64 --build-arg PAGESPEED_JOBS=4 -t nginx-pagespeed --push .Releases are built and published by the GitHub Actions workflow on every v* tag: each platform builds on a native runner and the multi-arch manifest is assembled at the end.