{"id":2109,"date":"2026-06-11T07:00:44","date_gmt":"2026-06-11T07:00:44","guid":{"rendered":"https:\/\/news.jurskitech.pl\/blog\/uncategorized\/jak-nie-dac-sie-zwariowac-z-dockerem-w-malej-firmie-3-pulapki\/"},"modified":"2026-06-11T07:00:44","modified_gmt":"2026-06-11T07:00:44","slug":"jak-nie-dac-sie-zwariowac-z-dockerem-w-malej-firmie-3-pulapki","status":"publish","type":"post","link":"https:\/\/news.jurskitech.pl\/blog\/warto-wiedziec\/jak-nie-dac-sie-zwariowac-z-dockerem-w-malej-firmie-3-pulapki\/","title":{"rendered":"Jak nie da\u0107 si\u0119 zwariowa\u0107 z Dockerem w ma\u0142ej firmie? 3 pu\u0142apki"},"content":{"rendered":"<h2 id=\"wprowadzenie\">Wprowadzenie<\/h2>\n<p>Docker sta\u0142 si\u0119 standardem w nowoczesnym web development. Obietnica \u201edzia\u0142a u mnie\u201d znika, a zamienia si\u0119 w \u201edzia\u0142a wsz\u0119dzie\u201d. Brzmi pi\u0119knie, prawda? Problem w tym, \u017ce w ma\u0142ych firmach \u2013 bez dedykowanego DevOpsa \u2013 Docker cz\u0119sto staje si\u0119 \u017ar\u00f3d\u0142em b\u00f3lu, a nie oszcz\u0119dno\u015bci. Widzia\u0142em to wiele razy: zesp\u00f3\u0142 zaczyna z entuzjazmem, a ko\u0144czy na debugowaniu tajemniczych b\u0142\u0119d\u00f3w sieciowych, niepotrzebnie rozd\u0119tych obrazach i kosztach chmury, kt\u00f3re rosn\u0105 w tempie wyk\u0142adniczym. W tym artykule poka\u017c\u0119 trzy konkretne pu\u0142apki, kt\u00f3re sam spotka\u0142em w projektach, oraz jak ich unikn\u0105\u0107.<\/p>\n<h2 id=\"1grubeobrazyktretyjkadegodnia\">1. Grube obrazy, kt\u00f3re tyj\u0105 ka\u017cdego dnia<\/h2>\n<h3 id=\"problem\">Problem<\/h3>\n<p>Wi\u0119kszo\u015b\u0107 pocz\u0105tkuj\u0105cych u\u017cytkownik\u00f3w Dockera tworzy obrazy bazuj\u0105ce na pe\u0142nej dystrybucji Linuksa, np. <code>ubuntu:latest<\/code>. Do tego doinstalowuj\u0105 wszystkie mo\u017cliwe narz\u0119dzia \u201ena zapas\u201d. Efekt? Obraz wa\u017cy 800 MB, a aplikacja to proste API w Node.js. W projekcie, kt\u00f3ry audytowa\u0142em, obraz zajmowa\u0142 1,2 GB \u2013 przez zb\u0119dne zale\u017cno\u015bci, wieloetapowy build bez czyszczenia cache\u2019u, a tak\u017ce pozostawione klucze SSH.<\/p>\n<h3 id=\"dlaczegotoboli\">Dlaczego to boli?<\/h3>\n<ul>\n<li><strong>Wolne deploye<\/strong>: ka\u017cda zmiana ci\u0105gnie za sob\u0105 pobranie 1 GB danych. CI\/CD zwalnia, a developerzy czekaj\u0105.<\/li>\n<li><strong>Koszty przechowywania<\/strong>: w rejestrze obraz\u00f3w (np. Docker Hub, AWS ECR) p\u0142acisz za miejsce. Grube obrazy = wy\u017csze rachunki.<\/li>\n<li><strong>Bezpiecze\u0144stwo<\/strong>: wi\u0119cej warstw to wi\u0119ksza powierzchnia ataku. Ka\u017cda dodatkowa biblioteka to potencjalna podatno\u015b\u0107.<\/li>\n<\/ul>\n<h3 id=\"rozwizanie\">Rozwi\u0105zanie<\/h3>\n<ul>\n<li>U\u017cywaj <strong>wieloetapowych build\u00f3w<\/strong> (multi-stage). Ka\u017cdy etap mo\u017ce u\u017cywa\u0107 innej bazy, a finalny obraz zawiera tylko to, co niezb\u0119dne do uruchomienia aplikacji.<\/li>\n<li>Wybieraj lekkie bazy, np. <code>alpine<\/code>, <code>slim<\/code> warianty oficjalnych obraz\u00f3w (np. <code>node:18-alpine<\/code>).<\/li>\n<li>Usuwaj zb\u0119dne pliki tymczasowe w tej samej warstwie, w kt\u00f3rej je tworzysz (np. <code>apt-get clean &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/*<\/code>).<\/li>\n<\/ul>\n<pre><code class=\"dockerfile language-dockerfile\"># Przyk\u0142ad poprawnego Dockerfile dla Node.js\nFROM node:18-alpine AS builder\nWORKDIR \/app\nCOPY package*.json .\/\nRUN npm ci --only=production\n\nFROM node:18-alpine\nWORKDIR \/app\nCOPY --from=builder \/app\/node_modules .\/node_modules\nCOPY . .\nEXPOSE 3000\nCMD [\"node\", \"server.js\"]\n<\/code><\/pre>\n<p>Dzi\u0119ki temu obraz schud\u0142 z 1,2 GB do 180 MB. Wdech, wydech.<\/p>\n<h2 id=\"2zaniedbanesieciikomunikacjamidzykontenerami\">2. Zaniedbane sieci i komunikacja mi\u0119dzy kontenerami<\/h2>\n<h3 id=\"problem-1\">Problem<\/h3>\n<p>W teorii Docker Compose \u0142\u0105czy serwisy automatycznie. W praktyce widzia\u0142em projekty, gdzie ka\u017cdy kontener komunikowa\u0142 si\u0119 przez <code>localhost<\/code> lub <code>127.0.0.1<\/code>. Albo gorzej \u2013 u\u017cywano <code>network_mode: host<\/code>, co zabija izolacj\u0119. Zazwyczaj wynika to z lenistwa lub niewiedzy, ale konsekwencje s\u0105 realne.<\/p>\n<h3 id=\"dlaczegotoboli-1\">Dlaczego to boli?<\/h3>\n<ul>\n<li><strong>B\u0142\u0119dy w produkcji<\/strong>: aplikacja dzia\u0142a na lokalnym, ale na serwerze nagle nie mo\u017ce po\u0142\u0105czy\u0107 si\u0119 z baz\u0105 danych. Dlaczego? Bo w kodzie zakodowano <code>localhost<\/code>, a kontenery s\u0105 w r\u00f3\u017cnych sieciach.<\/li>\n<li><strong>Brak skalowalno\u015bci<\/strong>: z <code>network_mode: host<\/code> nie uruchomisz dw\u00f3ch instancji tego samego serwisu na r\u00f3\u017cnych portach \u2013 to blokada dla replikacji.<\/li>\n<li><strong>Problemy z DNS<\/strong>: Docker udost\u0119pnia wewn\u0119trzny DNS, ale je\u015bli go nie u\u017cywasz, tracisz elastyczno\u015b\u0107.<\/li>\n<\/ul>\n<h3 id=\"rozwizanie-1\">Rozwi\u0105zanie<\/h3>\n<ul>\n<li>Zawsze u\u017cywaj <strong>nazw serwis\u00f3w zdefiniowanych w docker-compose.yml<\/strong> jako hostname. Zamiast <code>localhost:27017<\/code> pisz <code>mongodb:27017<\/code>.<\/li>\n<li>Unikaj <code>network_mode: host<\/code>, chyba \u017ce masz konkretn\u0105 potrzeb\u0119 (np. wydajno\u015b\u0107 sieci w specyficznych aplikacjach).<\/li>\n<li>Tw\u00f3rz w\u0142asne sieci, aby kontrolowa\u0107 izolacj\u0119: np. <code>backend<\/code> i <code>frontend<\/code>.<\/li>\n<\/ul>\n<pre><code class=\"yaml language-yaml\">version: '3.8'\nservices:\n  app:\n    build: .\n    ports:\n      - \"3000:3000\"\n    depends_on:\n      - db\n    networks:\n      - backend\n  db:\n    image: mongo:6\n    volumes:\n      - mongo-data:\/data\/db\n    networks:\n      - backend\nnetworks:\n  backend:\nvolumes:\n  mongo-data:\n<\/code><\/pre>\n<p>Po tym zabiegu po\u0142\u0105czenia mi\u0119dzy serwisami staj\u0105 si\u0119 przewidywalne i \u0142atwe do debugowania.<\/p>\n<h2 id=\"3brakstrategiidlawolumenwidanychtrwaych\">3. Brak strategii dla wolumen\u00f3w i danych trwa\u0142ych<\/h2>\n<h3 id=\"problem-2\">Problem<\/h3>\n<p>Kontenery s\u0105 efemeryczne \u2013 ich zamkni\u0119cie = utrata danych. Ma\u0142e firmy cz\u0119sto ignoruj\u0105 ten fakt i trzymaj\u0105 dane w kontenerze, licz\u0105c na cud. Przyk\u0142ad: uruchamiasz MySQL w kontenerze bez wolumenu, restartujesz go i\u2026 witaj, pustej bazie. Albo gorzej: u\u017cywasz bind mount, ale przez nieodpowiednie uprawnienia kontener nie mo\u017ce zapisywa\u0107 plik\u00f3w.<\/p>\n<h3 id=\"dlaczegotoboli-2\">Dlaczego to boli?<\/h3>\n<ul>\n<li><strong>Utrata danych<\/strong>: najgorsza opcja \u2013 backup\u00f3w nie ma, bo \u201eprzecie\u017c to tylko testy\u201d.<\/li>\n<li><strong>Problemy z uprawnieniami<\/strong>: przy bind mount, UID u\u017cytkownika w kontenerze nie zgadza si\u0119 z UID na ho\u015bcie, co powoduje b\u0142\u0119dy dost\u0119pu.<\/li>\n<li><strong>Op\u00f3\u017anienia w rozwoju<\/strong>: developerzy trac\u0105 czas na odtwarzanie danych testowych.<\/li>\n<\/ul>\n<h3 id=\"rozwizanie-2\">Rozwi\u0105zanie<\/h3>\n<ul>\n<li>Zawsze definiuj <strong>named volumes<\/strong> w docker-compose dla danych, kt\u00f3re maj\u0105 przetrwa\u0107 restart kontenera.<\/li>\n<li>Unikaj bind mount dla kodu \u017ar\u00f3d\u0142owego w produkcji (cho\u0107 w dev to wygodne). Zamiast tego u\u017cywaj wolumen\u00f3w do dzielenia si\u0119 danymi.<\/li>\n<li>Ustal regu\u0142y backupu: np. rsync z wolumenu do zewn\u0119trznego storage\u2019u, albo regularne dumpy bazy.<\/li>\n<\/ul>\n<pre><code class=\"yaml language-yaml\">services:\n  db:\n    image: postgres:15\n    volumes:\n      - pgdata:\/var\/lib\/postgresql\/data\nvolumes:\n  pgdata:\n<\/code><\/pre>\n<p>Dzi\u0119ki temu dane s\u0105 bezpieczne, a Ty \u015bpisz spokojnie.<\/p>\n<h2 id=\"podsumowanie\">Podsumowanie<\/h2>\n<p>Docker to pot\u0119\u017cne narz\u0119dzie, ale w ma\u0142ych firmach \u0142atwo o pope\u0142nienie kosztownych b\u0142\u0119d\u00f3w. Grube obrazy, z\u0142e zarz\u0105dzanie sieciami i ignorowanie trwa\u0142o\u015bci danych to trzy obszary, kt\u00f3re przysparzaj\u0105 najwi\u0119cej problem\u00f3w. Upraszczaj\u0105c: pami\u0119taj o multi-stage buildach, u\u017cywaj nazw serwis\u00f3w zamiast localhosta i zawsze deklaruj wolumeny dla danych. Wprowadzenie tych dobrych praktyk zajmie Ci godzin\u0119, a mo\u017ce uratowa\u0107 tygodnie frustracji.<\/p>\n<p>Potrzebujesz wsparcia przy optymalizacji infrastruktury kontenerowej? JurskiTech pomaga ma\u0142ym firmom wdra\u017ca\u0107 DevOps z g\u0142ow\u0105 \u2013 bez przesadnego skomplikowania i z realnym prze\u0142o\u017ceniem na biznes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wprowadzenie Docker sta\u0142 si\u0119 standardem w nowoczesnym web development. Obietnica \u201edzia\u0142a u mnie\u201d znika, a zamienia si\u0119 w \u201edzia\u0142a wsz\u0119dzie\u201d. Brzmi pi\u0119knie, prawda? Problem w tym, \u017ce w ma\u0142ych firmach \u2013 bez dedykowanego DevOpsa \u2013 Docker cz\u0119sto staje si\u0119 \u017ar\u00f3d\u0142em b\u00f3lu, a nie oszcz\u0119dno\u015bci. Widzia\u0142em to wiele razy: zesp\u00f3\u0142 zaczyna z entuzjazmem, a ko\u0144czy na<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[482,117,118,570],"class_list":["post-2109","post","type-post","status-publish","format-standard","hentry","category-warto-wiedziec","tag-bledy-w-devops","tag-docker","tag-konteneryzacja","tag-mala-firma"],"_links":{"self":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts\/2109","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/comments?post=2109"}],"version-history":[{"count":0,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/posts\/2109\/revisions"}],"wp:attachment":[{"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/media?parent=2109"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/categories?post=2109"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/news.jurskitech.pl\/blog\/wp-json\/wp\/v2\/tags?post=2109"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}