Nethence NEWDOC OLDDOC Lab Webmail Your IP BBDock  

Setting up Postfix as a Docker container

Dockerizing a strong anti-spam Postfix MX

Introduction

The container is ideally data-independend and possibly load-balance-ready. So the shared Docker volume may also be some NFS or shared disk fs on the Docker host side.

Liberating port 25 from the Docker host

We are going to setup an MX inside a container, therefore the smtp port needs to be freed from the Docker host.

You should see e.g. that port 25 is taken,

netstat -antpe --inet --inet6|grep LISTEN

Assuming it’s an RHEL/CentOS docker host, disable Postfix from it,

service postfix stop
chkconfig postfix off

and check again.

Launching the container

Make sure that either the shared volume doesn’t or does exist whether it’s a fresh installation or not,

sudo ls -alhF /data/postfixprod/

Run the container based on the custom Ubuntu Docker image,

app=postfixprod
docker ps -a | grep $app
docker run -d --name $app -h $app \
    -p 25:25 -p 587:587 -p 143:143 \
    -v /data/$app:/home \
    custom/ubuntu
docker exec -ti postfixprod bash

Note. in case you need to link some Postfix & Dovecot mappings to MariaDB,

    --link mariadbprod:mariadb \

Note. (optional) also if you like to,

    -v /data/postfixprod.conf:/etc/postfix \
    -v /data/postfixprod.spool:/var/spool/postfix \

And proceed with the Postfix guide.

Ready to go

Write the new init for the Docker container to start the daemons,

cd ~/
cat > init.bash <<-EOF
#!/bin/bash
/usr/sbin/rsyslogd
cp -pf /etc/resolv.conf /etc/hosts /etc/services /var/spool/postfix/etc/
tail -F /var/log/mail.err &
#/usr/lib/postfix/sbin/master -w
/usr/sbin/postfix start
/usr/sbin/dovecot
while true; do sleep 120; done
EOF
chmod +x init.bash

and run it,

/root/init.bash

Note. master without -w if you want it to be the remaining process of the container’s entrypoint (CMD). See man 8 master. I prefer to use a fake init as remaining process so I can eventually really restart the postfix daemon while keeping the container up and running (e.g. for dovecot).

See the the Postfix guide to run some checks.

Everything’s fine? Then commit to an image from the Docker host and change the entrypoint against the new init,

docker commit --change='CMD ["/root/init.bash"]' -p postfixprod postfixprod.`date +%s`.ready

or if the good entrypoint already has been applied, simply,

docker commit -p postfixprod postfixprod.`date +%s`.ready

Ref. https://docs.docker.com/engine/reference/commandline/commit/#/commit-a-container-with-new-cmd-and-expose-instructions

You can then launch the container with its new init,

app=postfixprod
docker ps -a | grep $app
docker run -d --name $app -h $app \
    -p 25:25 -p 587:587 -p 143:143 \
    -v /data/$app:/home \
    postfixprod.<datetag>.ready
docker logs $app
docker exec -ti $app ps auxfw
#docker exec -ti $app bash

Trash

Host Integration

Configure the System D service,

cd /etc/systemd/system
vi postfixprod.service

[Unit]
Description=postfixprod container
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker start -a postfixprod
ExecStop=/usr/bin/docker stop -t 30 postfixprod

[Install]
WantedBy=default.target

systemctl daemon-reload

Eventually restart the shit using System D now,

#docker stop postfixprod
#systemctl start postfixprod
#systemctl status postfixprod

Enable the shit at startup,

systemctl enable postfixprod
systemctl status postfixprod

Ref. https://docs.docker.com/engine/admin/host_integration/