Strona główna / Warto wiedzieć ! / Jak nie dać się zwariować z Dockerem w małej firmie? 3 pułapki

Jak nie dać się zwariować z Dockerem w małej firmie? 3 pułapki

Wprowadzenie

Docker stał się standardem w nowoczesnym web development. Obietnica „działa u mnie” znika, a zamienia się w „działa wszędzie”. Brzmi pięknie, prawda? Problem w tym, że w małych firmach – bez dedykowanego DevOpsa – Docker często staje się źródłem bólu, a nie oszczędności. Widziałem to wiele razy: zespół zaczyna z entuzjazmem, a kończy na debugowaniu tajemniczych błędów sieciowych, niepotrzebnie rozdętych obrazach i kosztach chmury, które rosną w tempie wykładniczym. W tym artykule pokażę trzy konkretne pułapki, które sam spotkałem w projektach, oraz jak ich uniknąć.

1. Grube obrazy, które tyją każdego dnia

Problem

Większość początkujących użytkowników Dockera tworzy obrazy bazujące na pełnej dystrybucji Linuksa, np. ubuntu:latest. Do tego doinstalowują wszystkie możliwe narzędzia „na zapas”. Efekt? Obraz waży 800 MB, a aplikacja to proste API w Node.js. W projekcie, który audytowałem, obraz zajmował 1,2 GB – przez zbędne zależności, wieloetapowy build bez czyszczenia cache’u, a także pozostawione klucze SSH.

Dlaczego to boli?

  • Wolne deploye: każda zmiana ciągnie za sobą pobranie 1 GB danych. CI/CD zwalnia, a developerzy czekają.
  • Koszty przechowywania: w rejestrze obrazów (np. Docker Hub, AWS ECR) płacisz za miejsce. Grube obrazy = wyższe rachunki.
  • Bezpieczeństwo: więcej warstw to większa powierzchnia ataku. Każda dodatkowa biblioteka to potencjalna podatność.

Rozwiązanie

  • Używaj wieloetapowych buildów (multi-stage). Każdy etap może używać innej bazy, a finalny obraz zawiera tylko to, co niezbędne do uruchomienia aplikacji.
  • Wybieraj lekkie bazy, np. alpine, slim warianty oficjalnych obrazów (np. node:18-alpine).
  • Usuwaj zbędne pliki tymczasowe w tej samej warstwie, w której je tworzysz (np. apt-get clean && rm -rf /var/lib/apt/lists/*).
# Przykład poprawnego Dockerfile dla Node.js
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Dzięki temu obraz schudł z 1,2 GB do 180 MB. Wdech, wydech.

2. Zaniedbane sieci i komunikacja między kontenerami

Problem

W teorii Docker Compose łączy serwisy automatycznie. W praktyce widziałem projekty, gdzie każdy kontener komunikował się przez localhost lub 127.0.0.1. Albo gorzej – używano network_mode: host, co zabija izolację. Zazwyczaj wynika to z lenistwa lub niewiedzy, ale konsekwencje są realne.

Dlaczego to boli?

  • Błędy w produkcji: aplikacja działa na lokalnym, ale na serwerze nagle nie może połączyć się z bazą danych. Dlaczego? Bo w kodzie zakodowano localhost, a kontenery są w różnych sieciach.
  • Brak skalowalności: z network_mode: host nie uruchomisz dwóch instancji tego samego serwisu na różnych portach – to blokada dla replikacji.
  • Problemy z DNS: Docker udostępnia wewnętrzny DNS, ale jeśli go nie używasz, tracisz elastyczność.

Rozwiązanie

  • Zawsze używaj nazw serwisów zdefiniowanych w docker-compose.yml jako hostname. Zamiast localhost:27017 pisz mongodb:27017.
  • Unikaj network_mode: host, chyba że masz konkretną potrzebę (np. wydajność sieci w specyficznych aplikacjach).
  • Twórz własne sieci, aby kontrolować izolację: np. backend i frontend.
version: '3.8'
services:
  app:
    build: .
    ports:
      - "3000:3000"
    depends_on:
      - db
    networks:
      - backend
  db:
    image: mongo:6
    volumes:
      - mongo-data:/data/db
    networks:
      - backend
networks:
  backend:
volumes:
  mongo-data:

Po tym zabiegu połączenia między serwisami stają się przewidywalne i łatwe do debugowania.

3. Brak strategii dla wolumenów i danych trwałych

Problem

Kontenery są efemeryczne – ich zamknięcie = utrata danych. Małe firmy często ignorują ten fakt i trzymają dane w kontenerze, licząc na cud. Przykład: uruchamiasz MySQL w kontenerze bez wolumenu, restartujesz go i… witaj, pustej bazie. Albo gorzej: używasz bind mount, ale przez nieodpowiednie uprawnienia kontener nie może zapisywać plików.

Dlaczego to boli?

  • Utrata danych: najgorsza opcja – backupów nie ma, bo „przecież to tylko testy”.
  • Problemy z uprawnieniami: przy bind mount, UID użytkownika w kontenerze nie zgadza się z UID na hoście, co powoduje błędy dostępu.
  • Opóźnienia w rozwoju: developerzy tracą czas na odtwarzanie danych testowych.

Rozwiązanie

  • Zawsze definiuj named volumes w docker-compose dla danych, które mają przetrwać restart kontenera.
  • Unikaj bind mount dla kodu źródłowego w produkcji (choć w dev to wygodne). Zamiast tego używaj wolumenów do dzielenia się danymi.
  • Ustal reguły backupu: np. rsync z wolumenu do zewnętrznego storage’u, albo regularne dumpy bazy.
services:
  db:
    image: postgres:15
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

Dzięki temu dane są bezpieczne, a Ty śpisz spokojnie.

Podsumowanie

Docker to potężne narzędzie, ale w małych firmach łatwo o popełnienie kosztownych błędów. Grube obrazy, złe zarządzanie sieciami i ignorowanie trwałości danych to trzy obszary, które przysparzają najwięcej problemów. Upraszczając: pamiętaj o multi-stage buildach, używaj nazw serwisów zamiast localhosta i zawsze deklaruj wolumeny dla danych. Wprowadzenie tych dobrych praktyk zajmie Ci godzinę, a może uratować tygodnie frustracji.

Potrzebujesz wsparcia przy optymalizacji infrastruktury kontenerowej? JurskiTech pomaga małym firmom wdrażać DevOps z głową – bez przesadnego skomplikowania i z realnym przełożeniem na biznes.

Tagi:

Zostaw odpowiedź

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *