Zvláštny problém, pre ktorý som nikde nenašiel zmysluplné vysvetlenie, týkajúci sa spúšťania docker-compose skriptu a iptables firewallu na Arch Linux. Kroky na reprodukciu predpokladajú dostupné čisté iptables, Docker a docker-compose.
Krok 1. Spustite Docker #
Spustite docker.service cez systemctl.
Krok 2. Spustite iptables #
Spustite iptables.service s obsahom dodaným s balíčkom:
# Empty iptables rule file
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
Krok 3. Spustite docker-compose skript #
Teraz spustite docker-compose skript. Vyskúšal som aspoň štyri nesúvisiace a každý jeden spustil chybu. Vyskúšajte napríklad tento:
sudo docker-compose up -d
Chyba sa prejaví takmer okamžite nasledujúcim spôsobom:
ERROR: Failed to Setup IP tables: Unable to enable DROP INCOMING rule: (iptables failed: iptables --wait -I DOCKER-ISOLATION-STAGE-1 -i br-739fd632de27 ! -d 172.18.0.0/16 -j DROP: iptables: No chain/target/match by that name.
(exit status 1))
A služby sa nespustia. Pre záznam, tu sú verzie:
- iptables v1.8.7 (legacy)
- Docker version 20.10.7, build f0df35096d
- docker-compose docker-compose version 1.29.2, build unknown
Problém sa vyskytuje aj na viacerých verziách bežiacich na Arch.
Riešenie #
Na internete existuje veľa vlákien k vyššie uvedenej chybovej správe a riešením je zastaviť iptables a reštartovať Docker:
sudo systemctl stop iptables.service
sudo systemctl restart docker.service
Docker vyprázdni iptables pravidlá a pri reštarte ich znovu vytvorí. Keď iptables už nebeží, docker-compose skript sa spustí bez problémov.
Prečo je to problém? #
Stále som nenašiel riešenie pre jednoduchý firewall pre služby spúšťané cez
docker-compose. Naozaj, toto je dlhodobo nevyriešený problém pre Docker, čo
ďalej potvrdzuje množstvo ľudí žiadajúcich spoľahlivé riešenie, ktoré
funguje s ufw (Uncomplicated FireWall) v
#777 a
#690 medzi inými.
Keďže nemôžem spoľahlivo pracovať s ufw a nemôžem pracovať ani s čistým iptables (bez ohľadu na to, aký archaický je jeho systém pravidiel), ako môžem nastaviť firewall? Úprimne, neviem si s tým poradiť.
Mnoho ľudí hovorí, že vzdali boj s Dockerom a v tejto oblasti prešli na Podman, nehovoriac o tom, že Podman je od základu navrhnutý na prácu bez roota. Dúfam, že čoskoro budem môcť experimentovať s Podmanom, ale teraz si to rozhodne nemôžem dovoliť.
Aktualizácia 18-júla-2021 #
Ako
správne poukázal užívateľ MindOfJoe,
povolenie oboch služieb bez ich manuálneho spúšťania by malo poskytnúť
správny výsledok. Konkrétne docker.service musí byť spustený po
iptables.service. Preskúmanie grafu závislostí potvrdzuje, že tento
problém v skutočnosti nie je problém a systemd sa postará o správne poradie
pri štarte:
$ systemctl-analyze critical-chain docker.service
docker.service +6.440s
└─network-online.target @15.972s
└─systemd-networkd-wait-online.service @2.156s +13.815s
└─systemd-networkd.service @2.073s +80ms
└─network-pre.target @2.029s
└─iptables.service @1.359s +669ms
└─basic.target @1.352s
└─sockets.target @1.352s
└─docker.socket @1.348s +4ms
└─sysinit.target @1.344s
└─systemd-update-utmp.service @1.331s +13ms
└─systemd-tmpfiles-setup.service @1.209s +67ms
└─local-fs.target @1.207s
└─run-docker-netns-1d291c7c6a2b.mount @20.223s
└─local-fs-pre.target @583ms
└─systemd-tmpfiles-setup-dev.service @523ms
└─kmod-static-nodes.service @480ms +32ms
└─systemd-journald.socket @469ms
└─system.slice @411ms
└─-.slice @411ms
Keďže sú služby správne umiestnené v grafe závislostí, neexistuje riziko
race condition, pri ktorom by sa docker.service spustil pred
iptables.service, vyprázdnil Docker pravidlá a spôsobil nepredvídateľné
zlyhania služieb po niektorých reštartoch. Je dobré vedieť, že takéto veci
sa dajú ľahko overiť, ak viete kde hľadať.