Как отключить IPv6 в Poste.io Docker: Postfix, Dovecot, Nginx
Пошаговое руководство по отключению IPv6 в контейнере Poste.io на Docker. Решение ошибок привязки портов в Postfix, Dovecot, Nginx. Настройка daemon.json, sysctl, override конфигов для стабильной работы без IPv6.
Как отключить IPv6 в контейнере и конфигурации Poste.io при использовании Docker?
Poste.io запущен через Docker с практически стандартной конфигурацией. IPv6 на сервере отключен через GRUB, соответственно в Docker также недоступен. Однако внутренние сервисы Poste.io (Postfix, Nginx, Dovecot) пытаются привязаться к IPv6-адресам, что приводит к сбоям при запуске. В интернете не удалось найти вразумительного ответа на эту проблему.
Доступны только тома из конфигурации, в частности файл server.ini, о котором практически нет информации в сети.
Подскажите, что делать и в каком направлении искать решение?
Коротко: чтобы отключить IPv6 для Poste.io в Docker, выключите Docker IPv6 (через /etc/docker/daemon.json или sysctl) и/или отключите IPv6 на уровне сети Docker, а затем принудительно настроьте Poste.io — Postfix, Dovecot и Nginx — слушать только IPv4 (через /data/_override или монтируемые тома). Такой подход (Disable IPv6 + правки конфигов Poste.io Docker) решает ошибки привязки типа “Address family not supported” и стартовые сбои сервисов.
Содержание
- Быстрый план действий
- Диагностика: как понять, кто пытается привязаться к IPv6
- Отключение IPv6 на уровне Docker (Docker IPv6)
- Отключить IPv6 в Poste.io (Poste.io Docker): Postfix, Dovecot, Nginx
- Альтернативы и обходные пути (sysctl, docker-compose, патч образа)
- Полезные команды и примеры конфигураций и проверок
- Источники
- Заключение
Быстрый план действий
- Диагностика: проверьте логи и что именно пытается слушать IPv6 (Postfix/Dovecot/Nginx).
- Если в Docker включён IPv6 — отключите его (daemon.json / docker network).
- В Poste.io сделайте постоянные переопределения конфигураций через /data/_override: Postfix → inet_protocols=ipv4; Dovecot → слушать только 0.0.0.0; Nginx → убрать listen [::]:*.
- Перезапустите контейнер, проверьте логи, при необходимости — примените sysctl внутри контейнера или используйте модифицированный образ.
Коротко и по делу: сначала выясняете, потом правите либо Docker, либо приложения (лучше — приложения, если менять Docker неудобно).
Диагностика: как понять, где именно пытаются привязаться IPv6
Сначала убедитесь, что ошибка действительно от привязки к IPv6. Ищите в логах сообщения вроде “Address family not supported by protocol”, “can’t bind”, или явное упоминание портов на формате “:::”.
Полезные проверки:
- Просмотрите логи контейнера:
docker logs -f mailserver | sed -n ‘1,200p’
(или docker-compose logs -f mailserver). - Посмотрите, на какие адреса слушают процессы внутри контейнера:
docker exec -it mailserver ss -lnpt | egrep ‘:25|:80|:143|:443|:993|:465|:587’
Вывод с :::25 или :::143 означает попытку слушать IPv6. - Проверьте, включён ли IPv6 у Docker:
sudo cat /etc/docker/daemon.json
docker network inspect bridge | grep EnableIPv6 -A2 - Проверьте, действительно ли IPv6 отключён в ядре (на хосте):
sysctl net.ipv6.conf.all.disable_ipv6 || echo “sysctl not present / kernel may be built without ipv6”
lsmod | grep ipv6
Что это даёт? Если контейнер показывает слушание на :::порт — значит приложение пытается слушать IPv6. Если Docker network имеет EnableIPv6=true — можно убрать IPv6 на уровне сети. Если ядро полностью выдёрнуто из системы (через GRUB/blacklist ipv6), то приложения не смогут создать IPv6-сокет — и падения ожидаемы.
Отключение IPv6 на уровне Docker (Docker IPv6)
Иногда проще выключить IPv6 прямо у Docker. Это делается через /etc/docker/daemon.json или удаление ipv6-настроек в сетях.
Пример минимального /etc/docker/daemon.json (отключаем поддержку IPv6):
{
"ipv6": false
}
После редактирования перезапустите docker:
sudo systemctl restart docker
Внимание: это остановит все контейнеры — планируйте окно обслуживания.
Проверки:
- docker network ls
- docker network inspect
— смотрите EnableIPv6 и настройки fixed-cidr-v6. Если сеть была создана с IPv6, удалите/пересоздайте её без IPv6.
Если вы используете docker-compose и не можете менять демон, можно попытаться отключать IPv6 на уровне контейнера через sysctl (см. раздел с альтернативами).
Справочная документация по IPv6 в Docker: https://docs.docker.com/engine/daemon/ipv6/. Для примеров отключения в похожих проектах см. инструкции Mailcow: https://docs.mailcow.email/post_installation/firststeps-disable_ipv6/.
Отключить IPv6 в Poste.io (Poste.io Docker): Postfix, Dovecot, Nginx
Если менять Docker неудобно или рискованно, правьте непосредственно конфигурации Poste.io. Poste.io поддерживает переопределение файлов через /data/_override — это официальный способ изменить конфиги и сохранить правки при обновлениях/перезапуске: https://poste.io/doc/extending-mailserver и в описании сетевых сценариев: https://poste.io/doc/network-schemes.
Общий подход:
-
Подключитесь в контейнер и создайте каталог переопределений (обычно /data/_override или /mailserver-data-dir/_override):
docker exec -it mailserver bash
mkdir -p /data/_override/etc/postfix /data/_override/etc/dovecot /data/_override/etc/nginx -
Postfix — заставить слушать только IPv4:
- Скопируйте main.cf в override и добавьте/замените строку:
inet_protocols = ipv4 - Альтернатива: inet_interfaces = 0.0.0.0 (принудительно)
Примечание: Postfix по умолчанию может быть с inet_protocols = all; документация объясняет поведение: https://www.postfix.org/IPV6_README.html
- Dovecot — убрать IPv6-слушание:
В конфиге Dovecot найдите директиву listen или секции inet_listener и установите явный IPv4-адрес:
listen = 0.0.0.0
либо в секциях:
service imap-login {
inet_listener imap {
address = 0.0.0.0
port = 143
}
inet_listener imaps {
address = 0.0.0.0
port = 993
ssl = yes
}
}
Скопируйте изменённый файл в /data/_override/etc/dovecot/conf.d/ и перезапустите контейнер. Сообщество отмечало, что установка listen=* иногда оставляет попытки слушать IPv6 — поэтому лучше явный 0.0.0.0.
- Nginx — убрать IPv6 listen и отключить возврат AAAA через резолвер:
- В конфиге замените строки вида
listen [::]:80наlisten 0.0.0.0:80и аналогично для 443. - Если Nginx делает upstream-resolve, можно добавить
resolver 1.1.1.1 ipv6=off;в upstream, чтобы dns не возвращал AAAA/не использовал IPv6 при соединении (пример и обсуждение: https://serverfault.com/questions/527317/disable-ipv6-in-nginx-proxy-pass, и подробное объяснение см. https://www.baeldung.com/linux/nginx-disable-ipv6).
После правок перезапустите контейнер: docker restart mailserver и внимательно смотрите логи: docker logs -f mailserver. Если в логах исчезли ошибки привязки — вы на правильном пути.
Нюанс с persist: правьте конфиги через /data/_override, иначе при пересоздании контейнера изменения пропадут. Poste.io документирует именно этот механизм https://poste.io/doc/extending-mailserver.
Альтернативы и обходные пути (sysctl, docker-compose, патч образа)
-
Вариант быстрый (если можно менять команду запуска): запуск контейнера с --sysctl net.ipv6.conf.all.disable_ipv6=1 — это отключит IPv6 в сетевом неймспейсе контейнера и часто предотвращает падения приложений. Пример:
docker run --sysctl net.ipv6.conf.all.disable_ipv6=1 …
Для docker-compose используйте полеsysctls:(если ваша версия compose это поддерживает). См. обсуждение: https://stackoverflow.com/questions/30750271/disable-ip-v6-in-docker-container и https://stackoverflow.com/questions/74012541/disable-ipv6-in-docker-compose. -
Если вы не хотите править Poste.io вручную, есть community-образы/postfix-обертки, где авторы уже отключили IPv6 (пример: https://github.com/Starbix/docker-poste.io). Можно использовать готовый форк или собрать свой образ, который в entrypoint выставляет нужные конфигурации.
-
Вариант “включить ipv6 модуль в ядре”: иногда проще разрешить ядру иметь поддержу IPv6 (не обязательно внешнего адреса), тогда сервисы смогут успешно привязываться к ‘::’ и продолжать работать. Это работает, но не всегда желаемо с точки зрения политики хоста. См. проблему с Dovecot при полностью отключённом ipv6 (Red Hat): https://access.redhat.com/solutions/36788.
-
Если хотите сохранить IPv6 на приложениях, но хост не имеет внешнего IPv6, можно использовать IPv6 NAT/псевдо-NAT проекты (но это сложнее): https://github.com/robbertkl/docker-ipv6nat и обсуждение в poste.io docs: https://poste.io/doc/network-schemes.
Полезные команды и примеры конфигураций и проверок
Проверка прослушиваемых сокетов внутри контейнера:
docker exec -it mailserver ss -lnpt
# или
docker exec -it mailserver netstat -tulpen | egrep 'LISTEN|:25|:143|:993|:80|:443'
Проверка Docker-config/сети:
cat /etc/docker/daemon.json
docker network inspect bridge
Пример автоматического добавления inet_protocols для Postfix (в /data/_override):
docker exec -it mailserver bash -c "mkdir -p /data/_override/etc/postfix && cp /etc/postfix/main.cf /data/_override/etc/postfix/main.cf"
# затем на хосте отредактируйте /path-to-mail-data/_override/etc/postfix/main.cf:
# добавьте или замените строку:
inet_protocols = ipv4
Пример замены listen в Nginx (в override):
server {
listen 0.0.0.0:80 default_server;
# уберите строки listen [::]:80;
...
}
Пример простого изменения Dovecot (поместить в /data/_override/etc/dovecot/conf.d/10-master.conf или dovecot.conf):
# добавьте/переписать:
listen = 0.0.0.0
Рестарт контейнера:
docker restart mailserver docker logs -f mailserver
Если после всех правок проблема остаётся — найдите точную строку ошибки в логах и гуглите её текст. Часто в сообществе уже есть точные советы (StackOverflow, GitHub issues).
Источники
- https://docs.docker.com/engine/daemon/ipv6/
- https://poste.io/doc/network-schemes
- https://poste.io/doc/extending-mailserver
- https://docs.mailcow.email/post_installation/firststeps-disable_ipv6/
- https://www.postfix.org/IPV6_README.html
- https://serverfault.com/questions/527317/disable-ipv6-in-nginx-proxy-pass
- https://www.baeldung.com/linux/nginx-disable-ipv6
- https://stackoverflow.com/questions/30750271/disable-ip-v6-in-docker-container
- https://stackoverflow.com/questions/74012541/disable-ipv6-in-docker-compose
- https://access.redhat.com/solutions/36788
- https://github.com/Starbix/docker-poste.io
Заключение
Если кратко: начните с диагностики (lsof/ss/логи), затем либо выключите Docker IPv6 (Docker IPv6 / Disable IPv6), либо, что обычно проще и безопаснее, принудительно запретите IPv6 в конфигурациях Poste.io — Postfix (inet_protocols = ipv4), Dovecot (listen = 0.0.0.0) и Nginx (убрать listen [::]:* / resolver ipv6=off). Для постоянных правок используйте /data/_override, как описано в документации Poste.io. Если потребуется — можно дополнительно применить --sysctl net.ipv6.conf.all.disable_ipv6=1 или использовать готовый форк образа с отключённым IPv6.