docker-mailserver (DMS) bundles Postfix, Dovecot, and Rspamd into one container with no database and no web interface. Everything is configuration files and a setup command, which makes it small, auditable, and a poor fit if you want to click things.
1. Before you start
Port 25 must be open, reverse DNS must point at your mail hostname, and your DNS must be yours to edit. Our guide on what running your own mail server actually takes covers all of it.
You also need Docker installed.
The project recommends 1 core and 1 to 2 GB of RAM with swap enabled. It runs on 512 MB only with ClamAV disabled, and even 1 GB without swap can cause problems. Your host also needs a static IP address.
One thing their documentation is explicit about: the server's hostname has nothing to do with the domains it serves. A server running as mail.example.com can handle mail for barbaz.org as long as that domain's MX record points at it. The hostname matters for the TLS certificate, not for the addresses.
2. Get the files
DMS is configured through a compose file and an environment file that you download and edit:
$ mkdir -p /opt/dms && cd /opt/dms $ DMS_GITHUB_URL="https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master" $ wget "${DMS_GITHUB_URL}/compose.yaml" $ wget "${DMS_GITHUB_URL}/mailserver.env"
In compose.yaml, set the hostname to your mail server's fully qualified name. Your MX record points at this value:
hostname: mail.example.com
The image is ghcr.io/docker-mailserver/docker-mailserver:latest, and the four bind mounts under ./docker-data/dms/ hold your mail, state, logs, and config. It is also published on Docker Hub as docker.io/mailserver/docker-mailserver.
On tags: latest is the current stable release, edge is built from the master branch, and version tags like 15.1, 15, and 15.1.0 are all published. Use latest unless you have a reason to pin.
3. Use Rspamd, not the older stack
The example compose file that most guides copy still enables the older anti-spam services. The project now encourages Rspamd instead, and says it will become the default in a future release.
Three rules for mailserver.env before you edit it, all from their documentation: only plain VAR=VAL lines work, do not quote your values, and variable substitution is not supported. Writing OVERRIDE_HOSTNAME=$HOSTNAME.$DOMAINNAME does not do what it looks like.
Enable Rspamd and turn off everything it replaces:
ENABLE_RSPAMD=1 ENABLE_OPENDKIM=0 ENABLE_OPENDMARC=0 ENABLE_POLICYD_SPF=0 ENABLE_AMAVIS=0 ENABLE_SPAMASSASSIN=0 ENABLE_POSTGREY=0 RSPAMD_GREYLISTING=1 ENABLE_CLAMAV=1
Leaving both stacks enabled wastes memory and produces confusing results. ENABLE_CLAMAV=1 is optional and works alongside Rspamd; set it to 0 on a small plan.
4. Start it and add an account within two minutes
$ docker compose up -d $ docker exec -ti mailserver setup email add [email protected]
You have two minutes
On first start, DMS shuts down and restarts if no email account exists. Run the setup email add command right after up -d. If the container restarts before you finish, start it again and add the account sooner.
Then add the postmaster alias and generate your DKIM key:
$ docker exec -ti mailserver setup alias add [email protected] [email protected] $ docker exec -ti mailserver setup config dkim $ docker exec -ti mailserver setup help
The DKIM command writes a public key under your config directory and prints where it put it. Publish those contents as a TXT record. The exact path differs depending on whether Rspamd or OpenDKIM is signing, so read the command's output rather than assuming a location. setup help lists every management command; there is no other interface.
Use up and down, never start and stop
The documentation is explicit about this: docker compose start and stop leave the container in an inconsistent state and cause startup problems. Use docker compose up -d and docker compose down. Pressing Ctrl+C is not supported either.
5. DNS, and which resolver you use
Publish MX, SPF, DKIM, and DMARC as usual; our DNS records guide covers the syntax.
One thing specific to spam filtering: DNS blocklists need a recursive resolver. Large public resolvers like Cloudflare, Quad9, and Google are blocked by the blocklist providers, so if your server uses one, blocklist lookups fail without an error message and your spam filtering gets worse. DMS does not ship its own resolver, so this is a host-level thing you configure yourself.
6. Spam filtering
Rspamd runs as a milter and scores each message using symbols. The RBL module is on by default, which is where the resolver note above matters. DMS turns off several Rspamd modules it considers unnecessary for a standard setup, including clickhouse, elastic, neural, and reputation.
Two variables worth knowing:
RSPAMD_GREYLISTING=1turns on greylisting, which is opt-in. It temporarily refuses mail from unknown senders; real servers retry, most spam software does not.RSPAMD_CHECK_AUTHENTICATEDdefaults to 0, so mail from your own authenticated users is not scanned. Set it to 1 if you want outgoing mail checked too, which catches a compromised account before it damages your reputation.
Everything else is configured with files under your config directory, and the project's Rspamd documentation covers custom rules.
7. LDAP has no maintainer
If you were planning to authenticate against LDAP, know that the project states plainly it currently has no LDAP maintainers, and the core team will most likely not be able to help with LDAP issues. Everything else is actively maintained. Use the built-in file-based accounts unless you have a reason not to.
8. Back it up
Everything lives in one directory:
$ cd /opt/dms $ tar --gzip -cf "backup-$(date +%F).tar.gz" ./docker-data/dms
Copy that file off the server. Restoring is extracting it back into place.
Quick reference
| Task | Command |
|---|---|
| Add account | docker exec -ti mailserver setup email add [email protected] |
| Add alias | setup alias add [email protected] [email protected] |
| Generate DKIM | setup config dkim |
| All commands | setup help |
| Start and stop | docker compose up -d and down, never start and stop |
| Backup | tar --gzip -cf backup.tar.gz ./docker-data/dms |
Testing your setup
Their documentation points at five external checkers. Run them before you trust the server: MX Toolbox, mail-tester.com, multiRBL.valli.org, internet.nl, and a DMARC analyzer.
Where to go next
Publish your DKIM record, then send a test message in each direction. If you want a web interface for managing accounts, this is not the platform; our comparison guide covers the ones that have one.