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ť.