Mailman 3 container
This Docker attempts to provide a simple standalone container for
the Mailman Core. Note that I made some arbitrary design decisions
--like using Postgres as the database, or preconfiguring the HyperKitty
If you intend to tweak a lot the set up, then it may be a good idea
to provide your own
docker-entrypoint.sh (see the
in order to adapt it to your needs.
docker-entrypoint.sh generates the configuration files and
executes the main application. If you have to make non-trivial changes
to the settings, then do it in a new
file is located at
/ (root directory) in the container, and is
executed as the
The Mailman Core will run standalone.
Postfix will be used as the MTA.
HyperKitty will be the one and only archiver. Is not included, but
can be reached through a normal HTTP (non-SSL) connection.
MAILMAN_SITE_OWNER contains the
(according to Mailman documentation) should "point to a human".
POSTGRES_USER The user that will be used to connect to the
Postgres database. Default is
POSTGRES_PASSWORD The password for the Postgres database. It
postgres, but please change it specially in deployment.
POSTGRES_DB The database that mailman will use. It
mailman. Of course, the POSTGRES_USER should have
been granted full permission to this database.
POSTGRES_HOST The hostname or IP for the Postgres server. It
POSTGRES_PORT Port for the Postgres server, by default
MAILMAN_ADMIN_USER Username for the Mailman webservice
(the Mailman API). Defaults to
MAILMAN_ADMIN_PASSWORD Password for the Mailman webservice.
mailman, but please change it specially in deployment.
HYPERKITTY_HOST Hostname or IP for the HyperKitty installation.
It defaults to
HYPERKITTY_PORT Port for the HyperKitty archiver API. Defaults
HYPERKITTY_ARCHIVER_API_KEY The HyperKitty's archiver API key.
enableflag for the
configuration. Defaults to
POSTFIX_HOST Postfix host for mail sending. Defaults to
POSTFIX_PORT Postfix port, defaults to
Remember that the defaults are here for testing for convenience, but in
most deployments they should be changed, specially the *_USER and
*_PASSWORD environment variables.
Be sure to read the official documentation.
The Transport maps will be available at the
inside the container, so it will be a good idea to set the docker to
mount this folder to the host.
CAUTION: The container DOES NOT run the
postmap command. Generally,
Mailman runs the
postmap binary in order to update the binary form,
but this has a lot of dependencies. The approach of this container is
ignore silently --by putting a mockup
postmap equivalent to the binary
true which always succeeds.
You should retrieve the plain form of the transport maps and feed them
postmap in order to use them.
The connection from Postfix to Mailman is prepared to be through the
LMTP protocol. This container uses port 8024 for LMTP and publishes
itself in this port (in the
var/data transport maps). On the other
side, Mailman container expects to be able to reach a Postfix in the
port 25. This typically means that the Postfix should have the Docker
mynetworks, or some equivalent "green card".
hostname of the docker container is very important. The
transport maps are done with the hostname of this container, and the
LMTP service will listen to the
hostname. If we decided to use
lmtp_host=0.0.0.0 then the transport maps will point to
which is an invalid destination. So be sure to use some sensible
hostname for this Mailman container and modify the
/etc/hosts in the
Postfix machine accordingly.
You should be familiar with regular Postfix configuration when setting
this up. There are a lot of settings, and most defaults tend to work
well with Mailman, but not always. Be ready to read some logs and
Prepare a file with all the environment variables that you will need. In
the following example I am not including the typical defaults, read the
section Environment Variables for more information about them.
# File sample_deploy.env POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres POSTGRES_DB=mailman MAILMAN_ADMIN_USER=mailman MAILMAN_ADMIN_PASSWORD=mailman MAILMAN_SITE_OWNER="firstname.lastname@example.org" HYPERKITTY_ARCHIVER_API_KEY=hyperkitty
First you need a Postgres server. Typical production deployment will
include a persistent database and a dedicated
mailman user. But, for
testing purposes, let's include a sample server.
docker run --name postgres-mailman-test -d \ --env-file sample_deploy.env \ postgres
Now we have a
postgres instance running. The mailman container can be
fired up with:
docker run --name mailman-test --hostname mailman-test \ -d -p 8024:8024 -p 8001:8001 \ -v `pwd`/mailman_var:/opt/mailman/var \ --link postgres-mailman-test:postgres \ --env-file sample_deploy.env \ alexbarcelo/mailman3
mailman3 container is ready to go. The ports it is listening on
are 8024 and 8001. A folder
mailman_var (feel free to change its
place and its name) will contain all data used by Mailman. This includes
data subfolder (which is needed by the MTA) and also temporal
folders and queues used internally.
The API endpoint is available (for the 3.1 tag) at the URL
http://localhost:8001/3.1 with the mailman admin username and password provided
in the environment.
Permissions in Mailman
mailman user is used inside the container, with UID and GID of 999.
This means that the
mailman-data folder (or whatever nanme you choose)
should have write permissions for that user. This container's entrypoint
ensures that by performing a
chown -R mailman:mailman /opt/mailman on
You should ensure that your mechanism (which may be a cron or whatever)
is able to read the transport map files and prepare them for Postfix.
Keep in mind that this is very specific to your deployment, and
your mileage will vary.
The idea is to have a modular setting which can potentially span
multiple nodes. The HyperKitty service requires plenty of storage for
archival purposes, and the Mailman service is expected to have high
throughput and availability. Keep that in mind when designing your own
production deployment plan.
I have not tested the clustering capabilities of this container and the
HyperKitty container. If the bottleneck is the input/output or the
network, it would seem reasonable to spawn multiple mailman containers
and let them receive and distribute mails. However, creation of new
lists and race conditions under those scenarios might get messy.
More knowledge on the mailman package would be required in order to
provide insight in this matter.