Dockerized Mail Server

While evaluation a new setup for a mail service including SMTP, IMAP, Web GUI, AntiSpam etc. someone kindly recommended mailcow-dockerized.

Please read the official documentation carefully, it’s not very complex, but very helpful.


After setting up the basics (Linux, Docker Engine and Compose, DNS for the FQDN) I cloned the Git Repo, generated the mailcow.conf and fired up the containers with docker-compose up -d.

In the beginning there was an error in the database setup of SOGo IIRC, but that was fixed within 1 or 2 days and led to a very flawless 2nd attempt with no further problems.


I’m using mailcow with SOGo for a few months now including at least 5 updates and except for additional restarts of the SOGo container after an update I see no problems.

TLS setup using Let’s Encrypt is included, and I use the web container of mailcow also as reverse proxy with TLS to my simple web page running in another container.


Additional configuration, e.g. for the web server, is located in the data/conf folder and you can even let the ACME container do the job on domain names not directly related to your mail services (i.e. SANs) by definition in mailcow.conf.


Persistent data including database files and mail folders is located in Docker Volumes as usual. My daily backup includes the volumes and Git Repo, so I can rollback and restore data in case of severe failures.


I recommend to use something like this for the regular updates:

  • Backup/Copy the Git Repo to a 2nd location for quick and fresh restore.
  • Consider a Snapshot if this is running in a VM.
  • Update the Git Repo: git pull
  • Build (approx. 5 minutes): docker-compose build --pull
  • Stop the running services (downtime start): docker-compose down
  • Start new containers: docker-compose up -d
  • Test
    • Send a test mail from somewhere else.
    • Check services on mobile.
    • Check admin login.
    • Check rspamd cockpit.
    • Check SOGo, restart the container on failure and test again.
    • Check logs (docker-compose logs) if you experience problems.
  • Rollback to previous version in case of failure.
    • Stop the running services: docker-compose down
    • Change to the fresh copy you have done in the first step.
    • Build: docker-compose build
    • Start containers: docker-compose up -d
    • Test again.
  • In case of ongoing failures, it’s about time to restore the snapshot or daily backup including repo and Docker’s data folder.
  • Under normal circumstances all goes well and you can prune images afterwards. Only the complete docker image prune --all deletes older releases, making the difference between unused and dangling (i.e. none tag only).

The build step will consume 5-10 minutes on a typical VM, all other docker-related steps are done within seconds.


Because nearly everything is deployed using Ansible on my VM, I added a role for mailcow to clone the repo, transfer of individual configuration files to data/conf and generate a mailcow.conf by template.