Dovecot, Spamassassin, et al can go in separate containers to postfix. Use LMTP for the connections and it’ll all work. This much is practical.
Now for the ideological bit. If you really wanted to do things ‘the docker way’, what would that look like.
Postfix is the difficult one. It’s not one daemon, but rather a cluster of different daemons that talk to each other and do different parts of the mail handling tasks. Some of the interaction between these component daemons is via files (e.g the mail queues), some is via sockets, and some is via signals.
When you start up postfix, you really start the ‘master’ daemon, which then starts the other daemon processes it needs using the rules in master.cf.
Logging is particularly difficult in this scenario. All the different daemons independently log to /dev/log, and there’s really no way to process those logs without putting a syslog daemon inside the container. “Not the docker way!”
Basically the compartmentalisation of functionality in postfix is very much a micro-service sort of approach, but it’s not based on containerisation. There’s no way for you to separate the different services out into different containers under docker, and even if you could, the reliance on signals is problematic.
I suppose it might be possible to re-engineer the ‘master’ daemon, giving it access to the docker process in the host, (or running docker within docker), and thus this new master daemon could coordinate the various services in separate containers. We can speculate, but I’ve not heard of anyone moving on this as an actual project.
That leaves us with the more likely option of choosing a more container friendly daemon than postfix for use in docker. I’ve been using postfix more or less exclusively for about the past decade, and haven’t had much reason to look around options till now. I’d be very interested if anyone can add commentary on possible more docker-friendly MTA options?
docker-postfix
Run postfix with SMTP authentication (sasldb) in a Docker container.
TLS and OpenDKIM support is optional. Fail2ban can be enabled.
Installation
- Pull image
$ docker pull danilsmirnov/postfix
Usage
- Create postfix container with smtp authentication
$ docker run -p 25:25 -e MAIL_DOMAIN=example.com -e SMTP_USER=user:pwd --name postfix -d danilsmirnov/postfix # Set multiple user credentials: -e SMTP_USER=user1:pwd1,user2:pwd2,...,userN:pwdN
- Set mail host defferent from mail domain
$ docker run -p 25:25 -e MAIL_DOMAIN=example.com -e MAIL_HOST=mail.example.com -e SMTP_USER=user:pwd --name postfix -d danilsmirnov/postfix
- Enable OpenDKIM: save your domain key
mail.private
in/path/to/domainkeys
$ docker run -p 25:25 -e MAIL_DOMAIN=example.com -e MAIL_HOST=mail.example.com -e SMTP_USER=user:pwd -v /path/to/domainkeys:/etc/opendkim/domainkeys --name postfix -d danilsmirnov/postfix # Set DKIM_SELECTOR variable if not okay with default "mail" selector
To sign more domains add their key file(s) named
$DKIM_SELECTOR._domainkey.$DOMAIN.private
, e.g.:mail._domainkey.subdomain.example.com.private mail._domainkey.*.example.com.private
(Wildcard subdomain refers to its parent domain’s DNS record.)
- Enable TLS(587): save your SSL certificates
mail.example.com.key
andmail.example.com.crt
to/path/to/certs
$ docker run -p 587:587 -e MAIL_DOMAIN=example.com -e MAIL_HOST=mail.example.com -e SMTP_USER=user:pwd -v /path/to/certs:/etc/postfix/certs --name postfix -d danilsmirnov/postfix
- Enable Fail2ban with
postfix-sasl
jail to ban brute-force attackers$ docker run -p 25:25 -e MAIL_DOMAIN=example.com -e MAIL_HOST=mail.example.com -e SMTP_USER=user:pwd -e FAIL2BAN=enabled --cap-add NET_ADMIN --name postfix -d danilsmirnov/postfix # Note: NET_ADMIN capability must be granted to the container # FAIL2BAN_BANTIME, FAIL2BAN_FINDTIME and FAIL2BAN_MAXRETRY could be set as well
- Add your custom configuration script
/configure.sh
$ docker run -p 25:25 -e MAIL_DOMAIN=example.com -e MAIL_HOST=mail.example.com -e SMTP_USER=user:pwd -v /path/to/script:/configure.sh --name postfix -d danilsmirnov/postfix
E.g., add an alias to forward mail to:
postconf -e "virtual_alias_maps = hash:/etc/postfix/virtual" echo "mailbox@${MAIL_DOMAIN} address@domain.com" > /etc/postfix/virtual postmap /etc/postfix/virtual
Note
- Login credential should be set to (
username@mail.example.com
,password
) in SMTP client - You can assign the port of MTA on the host machine to one other than 25 (postfix how-to)
- Read the reference below to find out how to generate domain keys and add public key to the domain’s DNS records