Это конечно далеко не идеальная реализация docker-контейнера с email-сервером и сопутствующими сервисами, но мне она очень помогает в процессе разработки ПО, которое отсылает и/или получает email-сообщения различным адресатам.
Довольно часто при разработке такого ПО нужно проверить какие именно email отсылаются и получаются (адреса отправителя и получателя, заголовки и тело письма). При этом далеко не всегда удобно использовать на время тестов "подставные" тестовые email-адреса и какие-то "внешние сервисы". Также, бывает необходимо проверить сам протокол обмена данными в процессе отправки и получения email-сообщений.
Для облегчения этой задачи я собрал для себя набор сервисов, которые упаковал в docker-образ, чтобы любой желающий мог скачать и запустить его в себя на компьютере.
Основная особенность данного набора то, что он позволяет отправлять и получать email для абсолютно любых корректных email-адресов, например, вы можете отправить письмо (через smtp/smtps) с адреса mail1@company1.com на адрес mail2@company2.com, а потом подключиться к почтовому ящику (через imap/imaps/pop3d/pop3ds) mail2@company2.com и прочитать это письмо со всеми заголовками.
Для тестирования обработки писем, которые небыли доставлены, настроен (можно изменить) домен bad-domain.com. Письма на любой адрес этого домена будут возвращаться, как недоставленные (через некоторое время).
Для аутентификации на сервисах всегда в качестве логина используется полный email-адрес и часть адреса до символа @, в качестве пароля.
При настройке отправки email через smtp/smtps нужно обязательно использовать авторизацию по логину и паролю (с использованием ssl/tls или нет неважно), т.к. возможность пересылки сообщений (relay) на любой адрес включена только если отправитель аутентифицирован.
Образ содержит в себе:
- smtp (порт 25/tcp) и smtps (порт 465/tcp) сервер для отправки сообщений
- imap (порт 143/tcp) и imaps (порт 993/tcp) сервер для доступа к почтовым ящикам по протоколу imap
- pop3d (порт 110/tcp) и pop3ds (порт 995/tcp) сервер для доступа к почтовым ящикам по протоколу pop3d
- http (порт 80/tcp) сервер-заглушка для показа общей информации о проекте и реализации удобной возможности первоначальной загрузки сертификата CA (при использовании самоподписанного сертификата CA) в браузер или почтовый клиент.
- https (порт 443/tcp) сервер для доступа к почтовым ящикам через web gui (webmail) на базе RainLoop. В исходный код сервера я внес небольшое исправление, чтобы можно было входить в любой корректный почтовый ящик, указав полный email-адрес в качестве login name и часть адреса до символа @, в качестве пароля. Настраивать доступ индивидуально для каждого домена, как это реализовано в исходном продукте не нужно. После применения исправлений сервер считает, то доступен любой домен.
Чтобы появилась возможность использовать защищенные версии протоколов smtp, imap, pop3d и http необходимо установить в docker-контейнере секретный ключ и сертификаты сервера и CA.
В зависимости от варианта развертывания, эти файлы можно получить у внешнего поставщика (Центра сертификации) или создать самостоятельно. Я, обычно, разворачиваю сервисы доступные по dns mail.localhost и ip-адресу 127.0.0.1. В этом случае ключ и сертификат CA, а также ключ и сертификат сервера я создаю самостоятельно. Чтобы не забыть детали этого процесса, я сделал себе шпаргалку доступную тут.
Упаковывать их (сертификаты и ключ) в docker-образ считаю плохой идеей... Есть несколько вариантов поместить ключ и сертификаты в docker-контейнер, например, смонтировать каталог с этими файлами при запуске контейнера. Я выбрал вариант с использованием Docker secrets, который входит в состав Docker Swarm mode.
Для начала работы с Docker в режиме Swarm mode, его нужно вначале проинициализировать. Например, так
docker swarm init --advertise-addr 127.0.0.1
Создаем docker secrets для хранения сертификатов СА и сервера, а также зарытого ключа сервера
docker secret create dev-email-server-ca ca.cert.pem
docker secret create dev-email-server-cert mail.localhost.cert.pem
docker secret create dev-email-server-key mail.localhost.key.pem
Структуры с данными о почтовых ящиках сохраняются внутри каталога /var/mail
.
Служебные структуры с данными, которые образуются в процессе работы с webmail сохраняются внутри
каталога /var/www/rainloop/data
.
Оба этих каталогов можно объявить, как тома (volume) docker или отобразить (bind) на реальные каталоги
родительской системы, чтобы они сохранялись после уничтожения контейнера с образом и восстанавливались
при повторном запуске контейнера.
Для сборки данного образа можно использовать команду
docker build --tag hidiv/dev-email-server .
или загрузить готовый с dockerhub.
Для запуска сервиса с образом сервера (в режиме Docker Swarm) можно использовать команду
docker service create --replicas 1 --name dev-email-server \
-p 25:25/tcp -p 465:465/tcp -p 143:143/tcp -p 993:93/tcp \
-p 110:110/tcp -p 995:995/tcp -p 80:80/tcp -p 443:443/tcp \
--secret source=dev-email-server-ca,target=/etc/ssl/certs/ca.cert.pem,mode=0444 \
--secret source=dev-email-server-cert,target=/etc/ssl/certs/mail.cert.pem,mode=0444 \
--secret source=dev-email-server-key,target=/etc/ssl/private/mail.key.pem,mode=0400 \
--secret source=dev-email-server-ca,target=/var/www/html/ca.crt,mode=0444 \
--mount type=volume,source=dev-email-server-mail,target=/var/mail \
--mount type=volume,source=dev-email-server-data,target=/var/www/rainloop/data \
hidiv/dev-email-server
Для остановки и удаления сервиса с образом сервера можно использовать команду
docker service rm dev-email-server
В составе репозитория есть пример файла docker-compose.yml, с помощью которого можно более гибко настраивать параметры запуска docker-контейнера с образом данного сервера, в том числе, как сервис под управлением Docker Swarm. Например, для запуска в таком режиме можно воспользоваться командой docker stack deploy с указанием ссылки на файл docker-compose.yml с описанием деталей запуска
docker stack deploy -c docker-compose.yml dev-server
где dev-server
это наименование стека сервисов, которые должны быть развернуты.
Для прекращения работы всех сервисов данного стека можно использовать команду docker stack rm.
docker stack rm dev-server
Если по какой-то причине нет желания или возможности использовать Docker Swarm для хранения секретов с данными сертификатов и ключа шифрования сервера, то можно разместить эти файлы на родительской файловой системе и смонтировать (bind) их на файлы контейнера аналогично секретам.
Все логи, которые формируют части сервера, выводятся в общий лог docker. Его можно посмотреть с помощью docker logs.
Если текущий пользователь не имеет прав для запуска docker (не включен в группу docker),
то нужно добавить вначале в вызов sudo
.