A monorepo of Dockerfiles and a Buildx orchestrator for the same web/mail/DB stack that powers deb.myguard.nl. The container images are built against the same hardened nginx, Angie, ModSecurity, PHP, Postfix, Dovecot, rspamd and openssl-nginx packages published at deb.myguard.nl — so what you run in a container matches what you'd get from apt install on a Debian/Ubuntu box pointed at the repo.
Want to chat, file bugs, suggest a module? Join the Discord: discord.gg/UQNsFg2y.
Numbers are derived from build/config.sh and docker-bake.hcl — run the commands yourself to confirm.
- Base distros: Ubuntu
resolute(rolling) and Debiantrixie, plus a few Alpine targets where it matters (nginx-alpine,redis6-scratch) - PHP versions:
5.6,7.4,8.0,8.2,8.4,8.5(six branches; seePHP_VERSIONSin build/config.sh) - Build targets: 92 —
grep -c '^target ' docker-bake.hcl - Source components: 31 subdirectories under src/
- Registry prefix:
docker.io/eilandert/<image>(seeDOCKER_REGISTRY_PREFIXinbuild/config.sh)
dockerized/
├── buildx.sh # wrapper → build/buildx-sequential.sh
├── generate.sh # wrapper → build/generate.sh
├── docker-bake.hcl # 92 targets + groups (base, phpfpm, nginx, angie, mail, db, …)
├── build/
│ ├── buildx-sequential.sh # orchestrator — builds one target at a time, in layer order
│ ├── generate.sh # walks src/<component>/.generate.sh in dependency order
│ ├── generate-lib.sh # shared template helpers
│ ├── config.sh # distro versions, PHP versions, registry prefix, version markers
│ └── monitor-builds.sh # tail/inspect helper for long bake runs
└── src/ # one directory per component (31 total)
├── base/ # ubuntu-base + debian-base
├── php-fpm/ # php-fpm 5.6 … 8.5, both distros
├── nginx/ # nginx + ModSecurity3 + PageSpeed (matches deb.myguard.nl nginx)
├── nginx-alpine/ # slim alpine variant
├── angie/ # Angie-nextgen build (matches deb.myguard.nl angie)
├── apache-phpfpm/ # Apache + PHP-FPM
├── mariadb/ # MariaDB (upstream mariadb-docker, repinnable)
├── redis/ redis6-scratch/ # Redis + a from-scratch redis6 image
├── valkey/ # Redis-compatible fork
├── postfix/ # SMTP, paired with the deb.myguard.nl postfix package
├── dovecot/ dovecot-ubuntu/ # IMAP/POP3 (one per distro family)
├── rspamd/ rspamd-git/ # stable + git/HEAD rspamd
├── roundcube/ roundcube-new/ roundcobe-old/ # webmail (current + legacy)
├── vimbadmin/ vimbadmin-ubuntu/ # mail admin UI
├── clamav-unofficial-signatures/ # AV signature feeder
├── unbound/ rbldnsd/ # recursive DNS + RBL DNS
├── openssh/ # ssh daemon image
├── aptly/ reprepro/ # APT repo tooling
├── letsencrypt/ # ACME client image
├── docker-cms/ # CMS bundle
├── psol-build/ # PageSpeed Optimization Library compile env
├── sitemap_warmup/ wosbotv4/ # support utilities
└── …
docker buildx bake --print will list every target and the groups they belong to.
Prereqs: Docker with Buildx (docker buildx version), Linux, network access to docker.io for base layers. Builds run sequentially so a laptop is fine — they're just slow.
# Regenerate Dockerfiles from templates (after editing src/<component>/Dockerfile-template*)
./generate.sh
# Build everything, one target at a time, in dependency order
./buildx.sh
# Build a single target
docker buildx bake -f docker-bake.hcl ubuntu-nginx-php84
# Build a group
docker buildx bake base
docker buildx bake phpfpm
docker buildx bake nginx angie
docker buildx bake mail
docker buildx bake db- base —
ubuntu-base,debian-base(one target per distro) - phpfpm + db + utilities — every PHP-FPM version against every base, plus
mariadb,redis,valkey - webservers + services —
nginx-*,angie-*,apache-phpfpm-*, mail stack - composed images —
roundcube,docker-cms, etc. that need a finished webserver
build/buildx-sequential.sh enforces this so a missing base never breaks a downstream build.
| Variable | Default | Effect |
|---|---|---|
PUSH |
on if hostname == build, off otherwise |
PUSH=1 forces --push; PUSH=0 forces it off |
LOAD |
0 |
LOAD=1 loads into the local docker daemon (only when PUSH is off) |
BUILDX_CACHE_DIR |
$XDG_CACHE_HOME/dockerized-buildx |
Persistent local buildkit cache |
BUILDX_BUILDER |
dockerized-build |
Name of the buildx builder created/used |
DOCKERIZED_PRUNE |
0 |
1 re-enables the old docker system prune -a between targets |
GENERATE_COMMIT |
0 |
1 makes generate.sh commit + push regenerated Dockerfiles |
MARIADB_UPSTREAM_REF |
master |
git ref pulled from MariaDB/mariadb-docker (pin to a tag for reproducibility) |
MARIADB_UPSTREAM_PATH |
10.11 |
directory inside the upstream repo |
MARIADB_TARGET_VERSION |
11.8 |
version string written into the rebuilt Dockerfiles |
Most public docker images for nginx/Angie ship the upstream binaries with the upstream defaults. These don't — they're built on top of the same Debian/Ubuntu packages published at deb.myguard.nl, with the same patches and modules. So:
- HTTP/3 + QUIC + kTLS out of the box on nginx and Angie. See Post-Quantum Cryptography with NGINX and Angie for what's actually wired up.
- Dedicated OpenSSL build (
openssl-nginx) tuned for nginx — RDRAND entropy, EC-NISTP 64-bit GCC backend, OpenResty session yield patch, no legacy ciphers. Background: OpenSSL-NGINX: A Dedicated OpenSSL Build for NGINX and Angie. - Audited dynamic modules. The full set shipped in the nginx image is documented at deb.myguard.nl/nginx-modules/; zstd in particular went through a deep audit — see We audited the zstd-nginx-module and found a lot of bugs.
- ModSecurity3 compiled in, with the same CRS exclusions used on the upstream site.
If you're running these containers in production, the matching server-side context lives in the articles at deb.myguard.nl/articles/.
mkdir src/<service>/and add either a staticDockerfileor aDockerfile-template*plus a.generate.sh.- Add a
target "<service>"block (and any per-distro variants) todocker-bake.hcl. - Add the target name to the appropriate
LAYERSentry inbuild/buildx-sequential.shso it builds in the right order. ./generate.sh && docker buildx bake <service>to test locally.- Commit, push.
For modifications to existing components, edit the template (not the generated Dockerfile) and re-run ./generate.sh — the per-component .generate.sh scripts under src/<component>/ are also runnable standalone for fast iteration.
# Generation
ls src/php-fpm/Dockerfile-template.* # template present?
./build/generate.sh -v # verbose generator
(cd src/nginx && bash ./.generate.sh) # regenerate one component in isolation
# Build
grep -A 5 'ubuntu-nginx-php84' docker-bake.hcl # inspect the target
docker buildx bake --print ubuntu-nginx-php84 # dry-run / show plan
docker buildx bake ubuntu-nginx-php84 # real buildIf a build fails on a base layer, rebuild that layer first — buildx-sequential.sh does this for you on a full run, but a single-target bake won't.
- Package repo & articles: deb.myguard.nl
- Module catalogue: deb.myguard.nl/nginx-modules/
- All articles: deb.myguard.nl/articles/
- Discord: discord.gg/UQNsFg2y
- Source: github.com/eilandert/dockerized