If you want full control of your email without paying per-mailbox fees, running a docker mail server is the shortest path from an empty VPS to a working mail system. The open-source docker-mailserver project packages Postfix, Dovecot, SpamAssassin, ClamAV, and more into a single, production-ready container image — so instead of hand-wiring half a dozen daemons, you configure one container and get a complete mail stack. This guide walks through the entire setup, from VPS prerequisites to your first sent and received test emails.
Prerequisites for a Docker Mail Server
Before touching Docker, make sure these are in place — skipping any of them is the source of most failed setups:
- A VPS with port 25 open. This is the deal-breaker. Many cloud providers block outbound port 25 by default, and without it your server cannot deliver mail to the internet. Providers like Contabo are popular for mail servers because SMTP ports are generally usable, but always confirm port 25 is open on your specific plan.
- A domain name with DNS control. You need to create A, MX, SPF, DKIM, and DMARC records. A cheap domain works fine — the reputation comes from correct configuration, not the TLD.
- A clean server. Use a fresh Ubuntu 24.04 LTS or Debian 12 machine. Nothing else should be listening on ports 25, 143, 465, 587, or 993.
- Docker Engine installed with the compose plugin, plus
gitandcurl.
Step 1 – Prepare the Docker Host
On a fresh Ubuntu 24.04 server, install Docker and the required tools:
sudo apt update && sudo apt install -y docker.io docker-compose-plugin git
sudo systemctl enable --now docker
Open the mail and certificate ports in the firewall:
sudo ufw allow 25/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 465/tcp
sudo ufw allow 587/tcp
sudo ufw allow 993/tcp
sudo ufw enable
Step 2 – Get Docker Mail Server Running with Compose
Clone the official project repository and set up a working directory. Throughout this guide, replace example.com and mail.example.com with your own domain:
git clone https://github.com/docker-mailserver/docker-mailserver.git
cd docker-mailserver
mkdir -p docker-data/dms
Create a compose.yaml file:
services:
mailserver:
image: ghcr.io/docker-mailserver/docker-mailserver:latest
container_name: mailserver
hostname: mail
domainname: example.com
env_file: mailserver.env
ports:
- "25:25"
- "143:143"
- "465:465"
- "587:587"
- "993:993"
volumes:
- ./docker-data/dms/mail-data/:/var/mail/
- ./docker-data/dms/mail-state/:/var/mail-state/
- ./docker-data/dms/mail-logs/:/var/log/mail/
- ./docker-data/dms/config/:/tmp/docker-mailserver/
cap_add:
- NET_ADMIN
- SYS_PTRACE
Then create mailserver.env with your core settings:
OVERRIDE_HOSTNAME=mail.example.com
SSL_TYPE=letsencrypt
ENABLE_CLAMAV=1
ENABLE_SPAMASSASSIN=1
SPOOF_PROTECTION=1
Start the stack:
docker compose up -d
The first start pulls the image and initializes all services. Give it a minute, then check the logs with docker compose logs -f to confirm Postfix and Dovecot started cleanly.
Step 3 – Add Email Accounts and Generate DKIM Keys
The repository ships with a setup.sh helper that manages everything inside the container:
./setup.sh email add admin@example.com
./setup.sh email list
./setup.sh config dkim
./setup.sh debug show-mail-logs
The first command prompts you to set a password for the new mailbox. The config dkim command generates DKIM keys and prints the DNS TXT record you must publish — copy that output, because you will need it in the next step. The last command tails the live mail logs, which is your best friend during troubleshooting.
Step 4 – DNS Records Your Docker Mail Server Needs
DNS is what makes other servers trust your mail. Create all five of these records at your DNS provider:
- A record:
mail.example.com→ your server's IP address. - MX record:
example.com→mail.example.comwith priority10. This tells the world where mail for your domain is delivered. - SPF record (TXT at
example.com):v=spf1 mx -all. This authorizes your mail server to send for the domain. - DKIM record (TXT): publish the exact record printed by
./setup.sh config dkim— typically under themail._domainkeyselector. DKIM cryptographically signs every outgoing message. - DMARC record (TXT at
_dmarc.example.com):v=DMARC1; p=none; rua=mailto:dmarc@example.com. Start withp=nonewhile testing, then move toquarantineand finallyrejectonce delivery is stable.
Separately, ask your VPS provider to set the reverse DNS (PTR) of your server IP to mail.example.com. Gmail and Outlook check that the PTR matches the HELO hostname, and a mismatch is one of the fastest ways to land in spam.
Step 5 – SSL/TLS for IMAP and SMTP
With SSL_TYPE=letsencrypt, the container automatically requests and renews certificates for your hostname — as long as port 80 is reachable and the A record resolves. If you prefer your own certificates, set SSL_TYPE=manual and place them in the mounted config/ssl/ directory. Once TLS is active, configure mail clients with authenticated SMTP on port 587 (STARTTLS) and IMAP on port 993 (implicit TLS).
Step 6 – Test Sending and Receiving
Watch the live logs while you test:
./setup.sh debug show-mail-logs
- Outbound test: connect a mail client (Thunderbird, Outlook, or your phone's mail app) to
mail.example.comwith your new account, and send a message to a Gmail address. Check the logs for astatus=sentline. - Inbound test: reply from Gmail back to
admin@example.com. You should see the message arrive in the logs and in your client's inbox. - Score the setup: send a message to
mail-tester.comto verify SPF, DKIM, DMARC, and reverse DNS all pass. Also check your IP on a blacklist checker like MXToolbox.
If mail-tester scores 9/10 or better and your IP is clean, your docker mail server is genuinely ready for production use.
Common Docker Mail Server Pitfalls
Port 25 is blocked by your provider
Providers such as AWS EC2, DigitalOcean, Hetzner, and Vultr block outbound port 25 by default on new accounts. You can open a support ticket requesting removal, or simply choose a provider that permits SMTP — RackNerd is a budget-friendly option many self-hosters use for mail servers. Test with telnet gmail-smtp-in.l.google.com 25 from your VPS before doing anything else.
Reverse DNS is missing or mismatched
Even with perfect SPF and DKIM, a missing PTR record will cause rejections or spam-folder delivery. The PTR must resolve to your mail hostname, and the forward A record must point back to the same IP.
DKIM or DMARC records were skipped
It is tempting to test with just MX and SPF, but major providers increasingly reject or spam-folder mail without valid DKIM signatures. Generate the keys with setup.sh config dkim and actually publish them.
ClamAV exhausts a tiny VPS
ClamAV alone wants around 1 GB of RAM on top of the mail stack. Use at least 2 GB of RAM, or set ENABLE_CLAMAV=0 in mailserver.env if you are on a 1 GB box.
Frequently Asked Questions
Does docker-mailserver include a webmail interface?
No — it is a pure mail server (SMTP, IMAP, POP3, Sieve, spam and virus filtering). If you want webmail, run a separate Roundcube container pointed at your mail server's IMAP and SMTP ports.
Can I host multiple domains on one docker mail server?
Yes. Simply add accounts under any additional domain with ./setup.sh email add user@otherdomain.com, then add the matching MX, SPF, DKIM, and DMARC records for that domain.
Can I migrate existing mailboxes into it?
Yes. Stop the container, copy your existing Maildir folders into the docker-data/dms/mail-data/ volume under the right account directories, fix ownership, and start the container again.
Key Takeaways
- A docker mail server gives you a complete Postfix + Dovecot + SpamAssassin + ClamAV stack in one container, configured through
compose.yamlandmailserver.env. - The only hard requirements are a VPS with open port 25, a domain with DNS control, and a clean Docker host.
- Publish all five DNS records — A, MX, SPF, DKIM, and DMARC — and set reverse DNS at your provider before testing deliverability.
- Use
setup.shfor account management, DKIM generation, and log debugging instead of poking around inside the container manually. - Score every new setup with mail-tester.com and verify your IP is not blacklisted before sending real mail.
- Start DMARC at
p=noneand tighten it torejectonly after confirmed stable delivery.
Related Guides
- Best VPS Providers with Open Port 25 — compare providers that allow SMTP so your mail server can actually deliver.
- How to Install PowerMTA on Ubuntu 24.04 — when you outgrow a general-purpose mail server and need a high-volume bulk sending MTA.
- How to Install Zimbra on CentOS 7 — a full collaboration suite with built-in webmail if you need more than just SMTP and IMAP.
