После перехода с CentOS 7 на Rocky или AlmaLinux 9 типичная проблема: «контейнер слушает порт, а снаружи не открывается» или наоборот — «порт торчит мимо firewalld». Docker сам правит цепочки netfilter, и без понимания правил легко получить дыру или «глухой» сервис.
DOCKER, DOCKER-USER и др.) и часто публикует -p 8080:80 так, что трафик проходит DNAT в обход ожидаемых правил зоны.Практичный подход: держать firewalld включённым, ограничивать публикацию портов и фильтровать вход через цепочку DOCKER-USER.
systemctl status firewalld --no-pager
firewall-cmd --state
firewall-cmd --get-active-zones
docker info | grep -i firewall
Если сервис идёт через Traefik во внутренней сети Docker, не делайте -p 80:80 на сам сервис. Достаточно сети traefik_network и ярлыков Traefik — тогда наружу торчит только 80/443 хоста (или только Traefik).
Для сервисов, которым всё же нужен прямой порт:
# пример: открыть 8080/tcp в зоне public
firewall-cmd --permanent --zone=public --add-port=8080/tcp
firewall-cmd --reload
Цепочка DOCKER-USER обрабатывается до правил Docker. Удобно запретить доступ к опубликованным портам отовсюду, кроме доверенной подсети:
# разрешить только LAN 192.168.100.0/24 к любому published-порту Docker
iptables -I DOCKER-USER -i eth0 -s 192.168.100.0/24 -j RETURN
iptables -I DOCKER-USER -i eth0 -j DROP
Правила iptables после перезагрузки пропадут. Для постоянства сохраните их через свой привычный способ (скрипт в systemd, iptables-save, или интеграцию с firewalld). На RHEL-подобных часто делают unit, который применяет правила после docker.service.
Пример unit:
cat > /etc/systemd/system/docker-user-firewall.service << 'EOF'
[Unit]
Description=DOCKER-USER firewall rules
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
ExecStart=/usr/sbin/iptables -C DOCKER-USER -i eth0 -s 192.168.100.0/24 -j RETURN || /usr/sbin/iptables -I DOCKER-USER -i eth0 -s 192.168.100.0/24 -j RETURN
ExecStart=/usr/sbin/iptables -C DOCKER-USER -i eth0 -j DROP || /usr/sbin/iptables -A DOCKER-USER -i eth0 -j DROP
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now docker-user-firewall.service
Подставьте свой интерфейс (ip -br a) и подсеть.
Варианты:
systemctl restart firewalld (иногда помогает, но это костыль).-p и ходить только через reverse proxy.iptables: false в /etc/docker/daemon.json и ручной проброс (сложнее, только если понимаете последствия).С другой машины:
nmap -Pn -p 22,80,443,8080 YOUR_SERVER_IP
Должны быть открыты только ожидаемые порты.
На Alma/Rocky 9 связка firewalld + Docker живёт спокойно, если:
-p;DOCKER-USER.Так домашний сервер остаётся доступным для себя и менее «шумным» для интернета.