See Mailu for a similar/better project
Dockerfile to build a multiple domain mail server using Postfix and Dovecot with IMAP and POP3 (like the one of a hosting provider).
This image is based on the ISPmail tutorial of Christoph Haas.
Additional the entrypoint of this images is based on GitLab Image of Sameer Naik.
There are some differences to the tutorial:
- Different MySQL tables: Usage of joins to reduce repetitions. (incompatible databases! see Database Structure)
- Improved SSL security: Deactivated SSLv3 and SSLv2 and enabled elliptic curve cryptography
- User defined alias address: enabled GMail like alias address with + separator
TODO: Docker compose
To avoid losing any data, you should mount a volume at:
/data
There you will find 3 subdirectories:
/data/maildir
- contains received and send emails/data/log
- contains logs of mail server/data/ssl
- contains SSL certificates of mail server
Volumes can be mounted in docker by specifying the -v
option in the docker run command.
docker run --name isp-mail -d \
-v /srv/docker/isp-mail:/data \
bboehmke/isp-mail:latest
If the server should be reachable from outside the host system, there are some ports that must be forwarded.
- SMTP (25 & 465): Send and receive mails. (communication between mail servers)
- POP3 (110 & 995): Access received mails on the server. (Delete on server)
- IMAP (143 & 993): Access received mails on the server. (No delete on server + folder support)
- Sieve (4190): Manage filter rules for received mails.
This mail server uses a database to store existing mail address and redirection. You can configure this image to use either MySQL or PostgreSQL.
Note: The structure of the database is shown in Database Structure
Assuming that the PostgreSQL server host is 192.168.1.42 with user mail
,
password password
and the dtabase name mailDB
docker run --name isp-mail -d \
-e DB_TYPE=postgresql \
-e DB_HOST=192.168.1.42 \
-e DB_NAME=mailDB \
-e DB_USER=mail \
-e DB_PASS=password \
-v /srv/docker/isp-mail:/data \
bboehmke/isp-mail:latest
If a postgresql container is linked, only the DB_TYPE
, DB_HOST
and
DB_PORT
settings are automatically retrieved using the linkage. You may
still need to set other database connection parameters such as the DB_NAME
,
DB_USER
, DB_PASS
and so on.
To illustrate linking with a postgresql container, we will use the official postgresql image. When using postgresql image in production you should mount a volume for the postgresql data store. Please refer the postgresql image for details.
First, start the postgresql container:
docker run --name mail-postgresql \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=mailDB \
-e POSTGRES_USER=mail \
postgres
The above command will create a database named mailDB
and also create a user
named mail
with the password password
with full/remote access to the
mailDB
database.
Now start the mail container:
docker run --name isp-mail -d \
--link mail-postgresql:postgresql \
-v /srv/docker/isp-mail:/data \
bboehmke/isp-mail:latest
Here the image will also automatically fetch the DB_NAME
, DB_USER
and
DB_PASS
variables from the postgresql container as they are specified in the
docker run
command for the postgresql container. This is made possible using
the magic of docker links and works with the following images:
Assuming that the MySQL server host is 192.168.1.42 with user mail
,
password password
and the dtabase name mailDB
docker run --name isp-mail -d \
-e DB_TYPE=mysql \
-e DB_HOST=192.168.1.42 \
-e DB_NAME=mailDB \
-e DB_USER=mail \
-e DB_PASS=password \
-v /srv/docker/isp-mail:/data \
bboehmke/isp-mail:latest
If a mysql container is linked, only the DB_TYPE
, DB_HOST
and DB_PORT
settings are automatically retrieved using the linkage. You may still need
to set other database connection parameters such as the DB_NAME
, DB_USER
,
DB_PASS
and so on.
To illustrate linking with a mysql container, we will use the official mysql image. When using mysql image in production you should mount a volume for the mysql data store. Please refer the README of the mysql image for details.
First, start the mysql container:
docker run --name mail-mysql \
-e MYSQL_PASSWORD=password \
-e MYSQL_DATABASE=mailDB \
-e MYSQL_USER=mail \
-e MYSQL_RANDOM_ROOT_PASSWORD=true \
mysql
The above command will create a database named mailDB
and also create a user
named mail
with the password password
with full/remote access to the
mailDB
database.
Now start the mail container:
docker run --name isp-mail -d \
--link mail-mysql:mysql \
-v /srv/docker/isp-mail:/data \
bboehmke/isp-mail:latest
Here the image will also automatically fetch the DB_NAME
, DB_USER
and
DB_PASS
variables from the mysql container as they are specified in the
docker run
command for the mysql container. This is made possible using the
magic of docker links and works with the following images:
This images requires a SSL certificate to secure the communication with the mail server.
The key file and the certificate should be stored in the /data/ssl
directory
with the name mail.key
and mail.crt
. Note: The name of the files can changed
with SSL_KEY
and SSL_CRT
.
The SSL of this image is configured to use perfect forward security. This
requires a dhparam file wich is automatically recreated on each container start.
The default size of this file is 1024 bits but you can increase this with
SSL_DH_PARAM_LENGTH
.
Please refer the docker run command options for the --env-file
flag where
you can specify all required environment variables in a single file.
This will save you from writing a potentially long docker run command.
Alternatively you can use docker-compose.
- DEBUG: Set this to
true
to enable entrypoint debugging. - DB_TYPE: Which type of database should be used: mysql or postgresql (Default: mysql).
- DB_HOST: Host name for database connection.
- DB_PORT: Database for database connection. (Default: 3306 for mysql & 5432 for postgresql)
- DB_NAME: Database for database connection.
- DB_USER: User name for database connection.
- DB_PASS: Password for database connection.
- MAIL_POSTMASTER_ADDRESS: Address of the postmaster of this server.
- MAIL_SERVER_HOSTNAME: Name used as mail server host name. (Default: host name of container).
- SSL_CERT: Name of the SSL/TLS certificate file in /data/ssl/. (Default: mail.crt)
- SSL_KEY: Name of the SSL/TLS key file in /data/ssl/. (Default: mail.key)
- SSL_DH_PARAM_LENGTH: Length of the DH parameters. (Default: 1024)
Note: This structure differs from the one of the tutorial!
The database of this mail server contains of 3 tables:
Table | Description |
---|---|
virtual_domains | List of domains that are handled by this mail server |
virtual_users | List of users (mail accounts) |
virtual_aliases | List of mail redirection |
Column | Description |
---|---|
id | Id of this domain (automatic created) |
name | Name of the domain (eg mail.com |
Column | Description |
---|---|
id | Id of this user (automatic created) |
domain_id | Id of the domain this user is for (must exist in virtual_domains ) |
name | Name of the user (eg if the address is [email protected] the name is user ) |
password | Hash of the user password |
Column | Description |
---|---|
id | Id of this alias (automatic created) |
domain_id | Id of the domain this user is for (must exist in virtual_domains ) |
source | Local name of the email address (eg if the address is [email protected] the source is admin ) |
destination | Destination of the redirection (eg [email protected] or an external address like [email protected] ) |
The database can be administered directly via a Web-based interface like phpPgAdmin (PostgreSQL) or phpMyAdmin (MySQL) or via a set of integrated shell-scripts.
All shell-scripts can be executed in an existing container:
docker exec -it <container> <...>
Or by a temporary container:
docker run -it --rm --link database:<mysql|postgresql> bboehmke/isp-mail <...>
Possible commands are described in the following sub-sections.
domains -l | -a <domain.xx> | -d <domain.xx>
- Options:
-l
- List Domains
-a <domain.xx>
- Add Domain
-d <domain.xx>
- Delete Domain
- Example:
docker exec -it <container> domains -a domain.xx
users -l | -a <[email protected][:password]> | -d <[email protected]>
- Options:
-l
- List all Users
-a <[email protected][:password]>
- Add User Account
name
fordomain.xx
- If
password
is omitted, the script will ask for a password.
- Add User Account
-p <[email protected][:password]>
- Change a User's Password
- If
password
is omitted, the script will ask for a password.
-d <[email protected]>
- Delete User Account
name
fordomain.xx
- Delete User Account
-D <[email protected]>
- Delete User's Mailbox Directory
- NOTE: This command doesn't check for existing user accounts!
- Example:
docker exec -it <container> users -a [email protected]:password
forwards -l | -a <[email protected]:[email protected]> | -d <[email protected]>
- Options:
-l
- List Aliases
-a <[email protected]:[email protected]>
- Add mail-forward from
[email protected]
to destination[email protected]
- Add mail-forward from
-d <[email protected]>
- Delete mail-forwards for
[email protected]
- Delete mail-forwards for
- Example:
docker exec -it <container> forwards -a [email protected]:[email protected]
Before you upgrade the image you should create a backup of the /data
volume
and the database.
To upgrade to a newer version of the image follow this steps:
- Step 1: Get the new docker image.
docker pull bboehmke/isp-mail:latest
- Step 2: Stop and remove the old container.
docker stop isp-mail
docker rm isp-mail
- Step 3: Start the new image.
docker run --name isp-mail -h isp-mail -d \
[OPTIONS] \
bboehmke/isp-mail:latest
The following features are planned for the future
- Automatic backup of mailboxes and database with a single command
- Automatic creation of self signed certificates if required
- Per user mailbox size (from database)
- Send only mail user