---
title: "WooCommerce cURL error 28 w Dockerze: Furgonetka i hairpin | ASAPDevs"
description: "cURL error 28 przy podłączaniu Furgonetki do WooCommerce w Dockerze: kontener nie łączy się z własną domeną. Diagnoza jednym curlem, hairpin, Cloudflare i flush DNS."
url: https://asapdevs.it/blog/woocommerce-curl-error-28-furgonetka-docker
last_updated: 2026-10-12
---

# WooCommerce w Dockerze: cURL error 28 przy podłączaniu Furgonetki. NAT hairpin

WooCommerce Auth woła własną domenę z serwera, a kontener jej nie widzi. Jedno polecenie curl pokazuje, czy to hairpin, a po zmianie w Cloudflare trzeba jeszcze wyczyścić cache DNS na hoście.

Błąd `cURL error 28: Connection timed out after 10002 milliseconds` przy podłączaniu wtyczki Furgonetka do WooCommerce w Dockerze oznacza zwykle, że kontener nie może połączyć się z własną domeną. Winny jest NAT hairpin zablokowany przez politykę DROP na hoście, a nie wtyczka. Poniżej pokazujemy, jak to rozpoznać jednym poleceniem, dlaczego drugi sklep na tym samym serwerze działał przypadkiem i co naprawia flush DNS po zmianie w Cloudflare.

## Skąd bierze się cURL error 28 przy autoryzacji WooCommerce?

Podłączanie wtyczki kończyło się na adresie `/wc-auth/v1/access_granted/` błędem z timeoutem 10 sekund. WooCommerce Auth przy `access_granted` robi POST z serwera na przekazany `callback_url`. U nas adres zwrotny wtyczki leżał na domenie sklepu, więc potrzebna była działająca pętla zwrotna HTTP z kontenera z PHP.

## Dlaczego kontener nie łączy się z własną domeną?

DNS w kontenerze zwracał publiczny adres hosta, bo rekord w Cloudflare był w trybie bez proxy. Pakiet z sieci bridge Dockera na publiczny adres własnego hosta wraca jako ruch przychodzący na łańcuch INPUT, gdzie `policy DROP` go odrzuca. Ruch z zewnątrz działa, bo wchodzi łańcuchem DOCKER w FORWARD i omija INPUT.

| Ścieżka | Wynik |
| --- | --- |
| kontener do nginx po adresie wewnętrznym | 200, 0,16 ms |
| kontener do domeny sklepu (adres publiczny) | timeout, połączenie nigdy nie startuje |
| host do własnego adresu publicznego | 200, 2 ms |
| kontener do Google | 200 (wyjście na świat sprawne) |

W regułach zapory nie było akceptacji dla portów 80 i 443 w łańcuchu wejściowym (INPUT).

## Dlaczego drugi sklep na tym serwerze działał bez problemu?

To fałszywy trop. Drugi sklep robił pętlę zwrotną bez błędu, ale tylko dlatego, że miał włączony tryb proxy w Cloudflare. Ruch szedł wtedy do Cloudflare i wracał z zewnątrz, omijając hairpin. Nie był poprawnie skonfigurowany, tylko przypadkiem omijał wadę. To też nie regresja po innych zmianach: wada sieci istniała od zawsze, tylko nic wcześniej nie potrzebowało pętli zwrotnej.

## Jak szybko sprawdzić pętlę zwrotną z kontenera?

Pierwszy krok przy `cURL error 28` to test z wnętrza kontenera, nie przeglądanie wtyczki:

```
docker exec <kontener-wp> curl -s -o /dev/null \
  -w 'code:%{http_code} connect:%{time_connect} ip:%{remote_ip}\n' \
  --max-time 10 https://<domena>/wp-json/
```

Kod `000` przy `connect:0.000000` oznacza, że nie udało się nawiązać połączenia TCP, więc szukaj w sieci, DNS albo zaporze, a nie w PHP. Dodaj flagę `-v`, żeby zobaczyć komunikat błędu, i sprawdź, na jaki adres kontener naprawdę celuje:

```
docker exec <kontener-wp> getent ahostsv4 <domena>
```

**Masz ten sam problem?** Wtyczka nie łączy się z własną domeną w Dockerze? Sprawdzimy zaporę, DNS i sieć kontenerów. [Opisz sytuację →](https://asapdevs.it/offers/migracja-serwera)

## Jak naprawić pętlę zwrotną przez Cloudflare i flush DNS?

W jednym ze sklepów włączyliśmy tryb proxy w Cloudflare. Samo to nie wystarczyło, kontener nadal dostawał timeout, z dwóch powodów:

-   resolver zwracał świeży rekord AAAA, a kontener nie miał IPv6 (brak adresu i trasy), więc był bezużyteczny,
-   dla IPv4 zwracał stary, zakeszowany adres hosta, czyli wracaliśmy do hairpin.

W naszej konfiguracji (domyślny resolver Dockera przekazujący zapytania do systemd-resolved na hoście) stary rekord siedział w cache hosta. Naprawa to jedno polecenie, bez zmian w zaporze ani w compose:

```
resolvectl flush-caches
```

Po flushu kontener dostawał adresy Cloudflare, a pętla zwrotna odpowiadała 200 w 0,19 s. Callback wtyczki zwracał 401 po 0,26 s, a `access_granted` 401 po 0,22 s. Kod 401 jest tu poprawny: ścieżka jest drożna, a serwer odmawia bez tokenu. Wcześniej był timeout po 10 sekundach.

**Na przyszłość.** Jeśli kontenery używają resolvera hosta z systemd-resolved, po zmianie trybu rekordu w Cloudflare (bez proxy lub z proxy) wykonaj `resolvectl flush-caches` na hoście. Inaczej kontenery przez wiele minut trzymają stary rekord.

## Jak naprawić hairpin na stałe na wszystkich sklepach serwera?

Drugi sklep na serwerze, bez proxy, miał ten sam problem i ujawniłby się przy WooCommerce Auth, WP-Cron po HTTP albo webhookach zwrotnych. Są dwie drogi:

-   **Tryb proxy w Cloudflare** dla domeny, zero zmian na serwerze, najprostsze.
-   **Reguła zapory** dla mostów tworzonych przez docker compose (`br-*`), obejmująca wszystkie takie stacki na serwerze:

```
iptables -I INPUT -i br-+ -p tcp -m multiport --dports 80,443 -j ACCEPT
```

Reguła obejmuje mosty `br-*`, a nie interfejs zewnętrzny, więc nic nie wystawia na zewnątrz. Domyślny most `docker0` ma inną nazwę, więc ścieżkę pakietu i interfejs sprawdź na swoim serwerze, na przykład licznikami reguł. Wymaga utrwalenia (na przykład `iptables-persistent`), bo inaczej ginie po restarcie serwera.

## Kiedy zlecić to specjalistom?

Gdy wtyczki, które wołają własną domenę (Furgonetka, WooCommerce Auth, webhooki, WP-Cron), zgłaszają timeouty, a w logach PHP nie ma błędu. W ASAPDevs sprawdzamy sieć kontenerów, zaporę i DNS w ramach [migracji i konfiguracji serwera](https://asapdevs.it/offers/migracja-serwera) oraz stałej [opieki nad WordPressem](https://asapdevs.it/offers/opieka-wordpress). O innych awariach środowiska Docker piszemy w artykule o [sklepie offline przez pełny dysk](https://asapdevs.it/blog/woocommerce-521-pelny-dysk-updraftplus-redis).

Źródła: dokumentacja Docker, [Packet filtering and firewalls](https://docs.docker.com/engine/network/packet-filtering-firewalls/) (łańcuchy iptables, DOCKER-USER).

![Kamil Perzowski](https://asapdevs.it/assets/img/kamil-asapdevs-112.webp)

Kamil Perzowski

CEO i co-founder ASAPDevs. Programuje i utrzymuje sklepy, aplikacje webowe i serwery klientów. [LinkedIn](https://www.linkedin.com/in/kamil-perzowski/) · [Migracja i konfiguracja serwera](https://asapdevs.it/offers/migracja-serwera)

Masz ten sam problem?

## Wtyczka nie łączy się ze sklepem w Dockerze?

![Kamil Perzowski, ASAPDevs](https://asapdevs.it/assets/img/kamil-asapdevs-112.webp)

Kamil Perzowski

CEO & Co-founder, ASAPDevs

Sprawdzamy sieć kontenerów, zaporę i DNS, naprawiamy pętlę zwrotną i testujemy wtyczki, które wołają własną domenę.

★★★★★

> Rekomenduję. Jestem zadowolona ze współpracy. Firma jest terminowa, rzetelnie wywiązuje się ze zobowiązań. Pełen profesjonalizm i rzadka cecha u informatyków – empatia, życzliwe i cierpliwe wsparcie.

Beata M., opinia w Google

★★★★★

> Pan Kamil wspaniale pomógł nam i stworzył nasz sklep internetowy! Lepiej nie mogliśmy trafić! Serdecznie polecamy :)

Kwiaciarnia M., opinia w Google

FAQ

## Pytania i odpowiedzi

### Co oznacza cURL error 28 przy łączeniu wtyczki Furgonetka z WooCommerce?

Połączenie z serwera sklepu wygasło po 10 sekundach. WooCommerce Auth przy zatwierdzaniu dostępu wysyła żądanie POST z serwera na adres zwrotny wtyczki. Gdy ten adres leży na domenie sklepu, potrzebna jest działająca pętla zwrotna HTTP.

### Dlaczego sklep w Dockerze nie może połączyć się sam ze sobą po domenie?

DNS w kontenerze może zwracać publiczny adres hosta. Pakiet z sieci bridge na publiczny adres własnego hosta wraca jako ruch przychodzący, gdzie domyślna polityka DROP go odrzuca. Ruch z zewnątrz działa, bo wchodzi łańcuchem DOCKER i omija INPUT.

### Dlaczego drugi sklep na tym samym serwerze działa bez problemu?

Prawdopodobnie ma włączony tryb proxy w Cloudflare, więc ruch idzie do Cloudflare i wraca z zewnątrz, omijając hairpin. Nie jest poprawnie skonfigurowany, tylko przypadkiem omija wadę sieci.

### Po włączeniu proxy w Cloudflare kontener nadal ma timeout. Dlaczego?

U nas stary rekord siedział w cache resolvera hosta (systemd-resolved), z którego korzystał kontener. Po zmianie trybu rekordu w Cloudflare wykonaj na hoście resolvectl flush-caches.

### Jak szybko sprawdzić pętlę zwrotną z kontenera?

Wywołaj curl z wnętrza kontenera na własną domenę i odczytaj kod, czas połączenia oraz adres IP. Kod 000 i czas połączenia 0 oznaczają, że połączenie TCP się nie nawiązało: to problem sieci, DNS lub zapory, a nie PHP.

## Przeczytaj też

### [Migracja serwera →](https://asapdevs.it/offers/migracja-serwera)

Przeniesienie sklepu i konfiguracja środowiska.

### [Opieka nad WordPressem →](https://asapdevs.it/offers/opieka-wordpress)

Monitoring, aktualizacje i szybka reakcja na awarie.

### [Sklep offline przez pełny dysk →](https://asapdevs.it/blog/woocommerce-521-pelny-dysk-updraftplus-redis)

UpdraftPlus, Redis MISCONF i błąd 521.

### [PHP-FPM, 502 i opcache JIT →](https://asapdevs.it/blog/php-fpm-502-segfault-opcache-jit-wordpress)

Gdy panel WordPressa pada falami.
