Що таке Docker і навіщо він потрібен звичайній людині
Є фраза, яку знає кожен, хто хоч раз торкався розробки чи адміністрування: «на моєму компі працює». Розробник написав код, на його ноутбуці все ідеально тестується, а коли намагаєшся запустити на іншій машині — нічого не працює. Версія бібліотеки інша, системна залежність відсутня, змінна оточення не налаштована. Знайомо?
Docker вирішує цю проблему радикально: він упаковує застосунок разом із усім, що йому потрібно для роботи, у один ізольований пакет. Цей пакет працює однаково на будь-якому комп’ютері з Docker — ноутбуці розробника, тестовому сервері чи хмарі.
Проблема / контекст: чому «на моєму компі працює» — це класика
До появи контейнерів було два основні підходи:
Варіант 1: встановлюємо все напряму на сервер. Поставили Node.js версії 18.7, PostgreSQL 15.3, ще купу бібліотек і залежностей. Все працює. Але коли треба розгорнути таке саме на іншому сервері, раптом з’ясовується, що там Debian іншої версії, і бібліотека libpq5 має інший хеш. І починається — «а чому ж не працює».
Варіант 2: віртуальна машина. Кожному застосунку — своя повноцінна віртуальна машина зі своєю операційною системою. Працює, але кожна VM важить кілька гігабайт, стартує хвилини, і коштує це дорого.
Docker пропонує третій шлях: контейнер має свою файлову систему і середовище, але використовує ядро хостової операційної системи. Це значно легше за віртуальну машину, але достатньо ізольовано, щоб сервіси не конфліктували між собою.
Як це працює простими словами
У світі Docker є кілька ключових понять, і вони досить логічні, якщо вивести правильну analogію.
Образ — це як інсталятор
Образ (image) — готовий пакет із застосунком, бібліотеками, конфігурацією та інструкцією з запуску. Його не потрібно «встановлювати» в класичному розумінні. Образ просто існує, і з нього можна запускати контейнери.
Офіційні образи існують для всього: від Nginx і PostgreSQL до Node.js і Python. Вони живуть на Docker Hub — публічному каталозі, як магазин застосунків.
Контейнер — це запущений застосунок
Контейнер — це конкретний екземпляр запущеного образу. Той самий образ можна запустити десять разів — буде десять незалежних контейнерів.
Проста аналогія: образ — це .exe файл або образ диска, а контейнер — це запущена програма. Ви можете запустити одну і ту ж програму в кількох вікнах — кожне вікно працює самостійно.
Dockerfile — рецепт збирання свого образу
Якщо готового образу немає, його можна зібрати. Dockerfile — це текстовий файл з інструкціями:
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Це буквально рецепт: «візьми Node.js 20, створи теку /app, скопіюй файли залежностей, встанови їх, скопіюй решту коду, відкрий порт 3000 і запусти застосунок».
Навіщо це потрібно на практиці
1. Немає більше «на моєму працює, а на сервері — ні»
Якщо застосунок працює в контейнері, він працюватиме будь-де, де встановлений Docker. Точка. Версію Node.js визначаєш ти в Dockerfile, а не системний адміністратор сервера.
2. Можна безпечно тестувати
Треба спробувати нову версію PostgreSQL? Завантажив образ і запустив — це ніяк не впливає на існуючу базу на хості. Коли тест закінчився, контейнер видалив разом із усім сміттям.
3. Декілька сервісів — один файл конфігурації
Вебсервер + база даних + кеш + черга повідомлень? Команда docker compose up запускає все одним файлом. Для домашніх серверів, pet-проєктів, демонстрацій — це один із найзручніших інструментів, які існують.
4. Ізоляція: якщо один сервіс зламався, інші працюють
Кожен контейнер ізольований. Якщо в одному сервісі трапився витік пам’яті, інші контейнери про це навіть не дізнаються. Це краще, ніж коли всі сервіси працюють на одному сервері й тягнуть один одного вниз.
5. Масштабування
Якщо навантаження виросло, можна просто запустити кілька копій одного контейнера. Не треба налаштовувати новий сервер, копіювати конфігурації й сподіватися на успіх.
Практичний приклад: запускаємо Nginx за 30 секунд
Щоб зрозуміти, як це виглядає на практиці, запустимо простий вебсервер:
docker run -d --name myweb -p 8080:80 nginx
Розберемо команду:
docker run— запустити контейнер;-d(detached) — працює у фоновому режимі;--name myweb— даємо йому зрозуміле ім’я;-p 8080:80— пробрасуємо порт: хост-порт 8080 → порт 80 всередині контейнера;nginx— беремо офіційний образ Nginx з Docker Hub.
Відкриваємо http://localhost:8080 — і бачимо сторінку Nginx. Все. Без встановлення пакетів, без конфігурації. Один рядок — і вебсервер працює.
docker compose: коли сервісів кілька
Один контейнер — це добре. Але реальні проєкти зазвичай мають 2-5 сервісів. Для цього є docker compose:
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
db:
image: postgres:17
environment:
POSTGRES_PASSWORD: mysecretpassword
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Запускається все одним рядком:
docker compose up -d
Тут два сервіси: Nginx і PostgreSQL. Nginx віддаватиме файли з локальної теки html, а база даних зберігатиме дані у volume під назвою pgdata.
Як перевірити, що все працює
Декілька команд, які знадобляться відразу:
docker ps— показує запущені контейнери;docker logs <ім'я>— логи контейнера;docker stop <ім'я>— зупинити;docker start <ім'я>— запустити знову;docker rm <ім'я>— видалити;docker compose down— зупинити й видалити все, що запущено через compose.
Типові помилки початківця
1. Зберігати дані всередині контейнера
Контейнер — це тимчасова річ. Видалив контейнер — дані зникли. Для даних завжди використовуй volume або монтування локальних тек. Інакше одного ранку прокинешся і знайдеш порожню базу.
2. Запускати все як root
Багато офіційних образів запускають процеси від root всередині контейнера. Для тестів це окей, для проду — нічого хорошого. Шукай варіанти з non-root користувачем або налаштовуй це сам у Dockerfile.
3. Забувати про оновлення образів
nginx:latest сьогодні — це одна версія. Через місяць — інша (або не інша, якщо ти не оновлюєш). Для проду краще фіксувати версії: nginx:1.27, postgres:17.2. Тоді деплой буде передбачуваним.
4. Монтувати занадто багато файлів
Коли через volumes монтується ціла тека проекту, це несе ризики: файли можуть конфліктувати з тим, що очікує контейнер, а права доступу — відрізнятися. Монтувай тільки те, що дійсно потрібно.
5. Ігнорувати ресурсні обмеження
Контейнер без обмежень може спожити всю пам’ять хоста. Додавай mem_limit і cpus у compose, якщо хост не потужний або на ньому працюють інші сервіси.
Висновок / план дії
Docker — це не складно. Це спосіб упакувати застосунок разом із усім, що йому потрібно, і гарантувати, що він працюватиме скрізь однаково.
Що зробити найближчим часом:
- Встанови Docker на свій комп’ютер або сервер.
- Запусти
docker run -d -p 8080:80 nginx— і переконайся, що бачиш сторінку Nginx. - Створи
docker-compose.ymlз двома сервісами (наприклад, Nginx + PostgreSQL) і запустиdocker compose up -d. - Пограйся зі зупинкою, видаленням і перезапуском — зрозумій різницю між
stopіdown. - Створи власний Dockerfile для простого застосунку (навіть якщо це просто статичний HTML).
Наступного разу, коли хтось скаже «на моєму працює», ти вже знатимеш, чого не вистачає в цій ситуації.