Hi all,
I’ve pushed a substantial update to my Virtualmin Docker module. The headline
addition since the last announcement is two-way Virtualmin integration: the
module now not only shows which of your virtual servers proxy to which container,
it can reconnect them when a container’s port changes — on both Apache and
Nginx.
It’s GPLv2, free, and installs like any other Webmin module.
Download: https://github.com/MrZaKaRiA/Virtualmin-Docker/releases/latest/download/docker.wbm.gz
Source: GitHub - MrZaKaRiA/Virtualmin-Docker: Webmin Virtualmin Docker · GitHub
Why this module
If you run apps in Docker behind Virtualmin virtual servers, you’re usually
juggling two panels: Virtualmin for the domain and reverse proxy, and a terminal
(or Portainer) for the containers. This module puts Docker under
Servers → Docker and teaches it about your Virtualmin domains, so the two
sides finally know about each other.
It’s also written to be safe to run as root — more on that at the bottom.
Virtualmin integration
See the link between domains and containers. The container list has a
“Proxied to” column showing the domain(s) whose Website Proxy points at each
container, matched by published port and linked through to the live site.
A new “Domains & Proxies” page shows the health of every domain proxy:
- Green — served correctly by a running container.
- Red — needs reconnecting. The domain’s own app is running, but on a
different port (e.g. a Compose update moved it from 3000 to 3001). The module
works out the correct port from the project’s compose file location and offers
a one-click Fix now. - Orange — not deployed. The domain proxies to a port with no container at
all. These are listed quietly as information, not flagged as errors, so a few
planned-but-not-yet-deployed subdomains don’t drown the page in red.
Reconnecting uses Virtualmin’s own API and reloads the web server for you. It
works with Apache (proxy balancers) and Nginx (sets the domain’s
proxy_pass and regenerates the config through the plugin). A per-domain
diagnose view shows exactly what Virtualmin reports if you want the detail.
You can also connect a domain to a container’s port directly from that
container’s Manage tab.
Docker Compose
- Project list showing each project’s status, config file and the Virtualmin
domain it belongs to. - One-click Update — pulls the image versions set in your
docker-compose.yml/.envand recreates the containers. (A plain restart
never applies a new version; this is the button that does.) Named volumes —
databases, uploads, settings — are kept. - Every action passes an explicit
--project-name, taken from
docker compose ls. This matters: without it, Docker can re-derive a different
project name and silently build a second stack with empty volumes instead of
upgrading the one you have. Pinning it guarantees the existing stack is
upgraded in place. - Old-copy detection — warns if a standalone container is running the same
app as a Compose project (the classic “why is my site still on the old
version?” situation, where the old copy still holds the domain and the data). - Restart / stop / start / down / logs / status, plus an advanced form to run an
action against any compose file by path. - Edit
.envin the browser — change a version tag, save (file ownership and
permissions are preserved), then click Update to apply it.
Containers
- List with live CPU/memory, ports, proxied domains and health.
- Start, stop, restart, pause, unpause, kill, remove, rename, update resources
(memory / CPUs / PID limit / restart policy), clone. - Bulk select-and-act across many containers.
- Per-container tabs:
- Logs — timestamps, “since” filter, text search, auto-refresh, download.
- Details — readable summary: image, state and health, created/started,
restart policy, Compose project, entrypoint/command, ports, mounts, networks,
environment. - Inspect — the raw JSON when you want it.
- Network — connect/disconnect the container to networks.
- Processes —
docker top. - Stats — CPU, memory, network and block I/O, PIDs.
- Exec — non-interactive command execution with quick-command buttons, plus
host ↔ container file copy.
Images, storage, backup and maintenance
Images — list, inspect, history, remove, pull, push, tag, build from an
inline Dockerfile, run a new container, Docker Hub search, and prune.
Storage — volumes and networks: list, inspect, create, remove, prune.
Backup & restore
- Images: save to / load from a host tar (
docker save/docker load). - Containers: commit to a new image, or export the filesystem.
- Volumes: back up and restore a local volume as a
.tar.gz.
Maintenance — system prune and build-cache prune, with a live preview of
exactly what would be deleted before you confirm: stopped containers, unused
volumes and leftover images, each tagged in red where it looks like a
DATABASE or belongs to domain X. Every destructive action explains its
consequences in plain language first.
Security scanning — image vulnerability scans via Docker Scout or
Trivy (the removed docker scan is not used).
Registry & contexts — log in to a private registry, and switch the Docker
context the module talks to (so rootless Docker works).
Monitoring — “Docker Up” and “Docker Container Up” monitor types for the
System and Server Status module, plus a Docker panel on the Webmin dashboard.
Built for people who aren’t Docker experts
Every risky button explains what it actually does, in plain words — e.g. that
Restart does not load a new version, that Stop takes the site offline but
deletes nothing, that Down removes containers but keeps volume data. Destructive
actions show a red confirmation listing precisely what will be removed.
The interface is built entirely from Webmin’s own UI components, so it inherits
your theme (Authentic or otherwise) and looks like the rest of the panel rather
than a bolted-on app.
Security
The module runs as root, so it’s written defensively:
- No shell injection. Webmin executes commands through
/bin/sh, so every
value that comes from a form, a config file or Docker output is single-quote
escaped before it goes near a command; constant flags stay literal. Values can
never be read as extra flags or shell metacharacters. - Allowlist validation of container/image/volume/network identifiers before
use — control characters, leading dashes and path traversal are rejected. - All state changes are POST-only, covered by Webmin’s trusted-referer check,
and recorded withwebmin_logso they show up in the Actions Log. - Registry passwords go to
docker login --password-stdinvia the child
process’s stdin — never on a command line, and not stored by the module. - Per-user ACLs: view, manage, create, delete, exec, prune, backup, proxy,
registry and context can each be granted or denied under
Webmin Users → user → Docker. - All Docker output is HTML-escaped before display.
Requirements
- Webmin (or Virtualmin) and the Docker engine + CLI
- Perl
JSON::PP(ships with Perl 5.14+) - Optional:
docker composev2 for the Compose features, anddocker scoutor
trivyfor scanning - The Virtualmin features are optional — on a plain Webmin host they simply don’t
appear.
Install
The quickest way: Webmin → Webmin Configuration → Webmin Modules →
From ftp or http URL, paste this and click Install Module:
https://github.com/MrZaKaRiA/Virtualmin-Docker/releases/latest/download/docker.wbm.gz
Or from the shell:
wget https://github.com/MrZaKaRiA/Virtualmin-Docker/releases/latest/download/docker.wbm.gz
/usr/share/webmin/install-module.pl docker.wbm.gz
Then open Servers → Docker. Upgrading over an existing install keeps your settings and per-user ACLs. The dashboard panel appears once the System and Server Status module is enabled.
Feedback, bug reports and feature requests are very welcome — issues and PRs at Issues · MrZaKaRiA/Virtualmin-Docker · GitHub
Hope it’s useful to everyone running Docker apps behind Virtualmin.