Prywatny pakiet, który na Twojej maszynie rozwiązuje się bez problemu, może zawieść wewnątrz builda z błędem 404 lub przekroczeniem limitu czasu, a Dockerfile rzadko jest przyczyną. Krok builda działa w innej przestrzeni nazw sieci, z innym widokiem DNS i innym magazynem poświadczeń niż powłoka, w której testowałeś. Przejdź te kontrole po kolei i zatrzymaj się na pierwszej, która zawiedzie, bo każda kolejna zakłada, że poprzednia się udała. Każdy krok nazywa polecenie, które rozstrzyga sprawę.

Zacznij od nazwania buildera, nie Dockerfile

BuildKit może być lokalny, działać w kontenerze lub na innej maszynie, a każdy z nich ma własną domyślną sieć. Uruchom docker buildx ls i przeczytaj węzeł oznaczony gwiazdką, zanim cokolwiek zmienisz. Jeden docker-container sterownik lub builder w chmurze nie dzieli prywatnej trasy na Twoim laptopie tylko dlatego, że wpisałeś tam polecenie. Jeśli aktywny builder jest zdalny, każda pozostała kontrola musi być wykonana na tym hoście, a nie na Twojej stacji roboczej.

Builder niesie też własną konfigurację resolvera i zmienne proxy. Oba są czytane w czasie builda i nie są dziedziczone z terminala, który go uruchomił.

Udowodnij trasę sieciową od wewnątrz kroku builda

Napisz jednorazowy etap, który rozwiązuje hosta zależności i otwiera do niego połączenie. To jedyny test, który odpowiada na pytanie w imieniu buildera, a nie Twojej powłoki.

FROM alpine:3.20
RUN apk add --no-cache curl bind-tools  && getent hosts registry.example.internal  && curl -sS -o /dev/null -w "%{http_code}
" https://registry.example.internal/simple/

Zbuduj ten plik tym samym builderem, trybem sieci i tymi samymi montażami sekretów, których używa Twój prawdziwy build: docker buildx build --builder remote0 -f Dockerfile.probe --progress=plain .. Jeśli getent nic nie wypisze, usterka leży w rozwiązywaniu nazw i żadne poświadczenia jej nie naprawią. Jeśli nazwa się rozwiązuje, ale curl zgłasza przekroczenie limitu czasu, przeszkodą jest trasa lub polityka wyjścia przed rejestrem.

Usuń sondę, gdy tylko odpowie. To etap diagnostyczny i nigdy nie powinien być oznaczany ani wypychany.

Zamontuj poświadczenie zamiast je kopiować

Gdy trasa działa, uwierzytelnianie jest następną usterką w kolejce. Montaż sekretu w BuildKicie udostępnia plik jednemu RUN krokowi bez zapisywania go w warstwie, i tego potrzebuje narzędzie zależności, a tego obraz nie może zachować.

RUN --mount=type=secret,id=npmrc,target=/root/.npmrc     npm ci --omit=dev

Sekret musi być dostarczony spoza Dockerfile: docker buildx build --secret id=npmrc,src=/home/me/.npmrc .. Plik zostaje u klienta i nigdy nie trafia do historii obrazu. Ani ARG ani ENV z tym samym tokenem nie wykonują tej pracy, bo oba są zapisywane w konfiguracji obrazu.

Obraz bez roota potrzebuje własnej ścieżki docelowej, na przykład /home/app/.npmrc lub odpowiedniego pliku dla pip, Mavena lub Cargo. Cel montażu musi odpowiadać użytkownikowi, który wykonuje polecenie, inaczej narzędzie zgłosi brakujący plik konfiguracyjny, który w rzeczywistości istnieje.

Sprawdź, co narzędzie zależności zostawia w obrazie

Tymczasowy montaż trzyma poświadczenie poza warstwą, ale nie powstrzymuje narzędzia przed zapisaniem czegoś innego. Menedżery pakietów zostawiają pliki lock, katalogi cache i czasem rozwiązany adres URL rejestru.

Czytaj gotowy system plików, zamiast ufać Dockerfile. docker history --no-trunc image:tag wymienia każde polecenie warstwy, a docker run --rm image:tag sh -c "ls -a /root" pokazuje, co przetrwało w działającym kontenerze. Nawet gdy plik był tylko zamontowany, token zapisany w wierszu logu podczas npm ci nadal jest wyciekiem.

Przeczytaj też log builda, ponieważ --progress=plain wypisuje dane wyjściowe poleceń dosłownie. Jeśli token się tam pojawi, obróć go przed wszystkim innym i przekazuj przez plik, który narzędzie czyta po cichu.

Upewnij się, że obraz uruchomieniowy nie potrzebuje już prywatnej trasy

Build i działająca aplikacja to dwa różnych konsumentów tej samej zależności, i tylko pierwszy potrzebuje prywatnej trasy. Gotowy obraz powinien się uruchomić, rozwiązać swoje zależności uruchomieniowe i obsługiwać ruch bez poświadczenia z builda.

Przetestuj to tam, gdzie prywatny rejestr jest nieosiągalny, albo po prostu uruchom kontener z --network none i potwierdź, że wystartuje bez zamontowanego sekretu. Kontener, który startuje tylko wtedy, gdy obecny jest sekret builda, wciąż jest sprzężony ze środowiskiem builda.

Jeśli kontener naprawdę potrzebuje rejestru w czasie działania, to osobna decyzja o dostępie i jej miejsce jest w magazynie sekretów orkiestratora, a nie w buildzie. Udokumentuj obie ścieżki osobno, żeby nikt nie próbował naprawić pobierania w czasie działania flagą builda. Gdy wszystkie pięć kontroli przejdzie, pierwotny objaw ma nazwaną przyczynę na każdej warstwie, zamiast domysłu o sieci Dockera.

Powiązane artykuły