Що таке Docker?¶
Docker — це платформа для запуску застосунків у контейнерах. Контейнер — це легковісне ізольоване середовище, яке містить все необхідне для роботи програми: код, бібліотеки, системні інструменти.
Контейнер vs Віртуальна машина¶
Найпростіше зрозуміти контейнери — порівняти їх з віртуальними машинами (VM):
┌─────────────────────────────────────────────────────────────────┐
│ ВІРТУАЛЬНІ МАШИНИ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ App A │ │ App B │ │ App C │ <- Застосунки │
│ ├─────────┤ ├─────────┤ ├─────────┤ │
│ │ Bins/ │ │ Bins/ │ │ Bins/ │ <- Бібліотеки │
│ │ Libs │ │ Libs │ │ Libs │ │
│ ├─────────┤ ├─────────┤ ├─────────┤ │
│ │ Guest │ │ Guest │ │ Guest │ <- Повна ОС │
│ │ OS │ │ OS │ │ OS │ (1-2 GB кожна) │
│ └─────────┘ └─────────┘ └─────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ Hypervisor │ <- Гіпервізор │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ Host OS │ <- ОС хоста │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ Hardware │ <- Залізо │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ КОНТЕЙНЕРИ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ App A │ │ App B │ │ App C │ <- Застосунки │
│ ├─────────┤ ├─────────┤ ├─────────┤ │
│ │ Bins/ │ │ Bins/ │ │ Bins/ │ <- Тільки потрібні│
│ │ Libs │ │ Libs │ │ Libs │ бібліотеки │
│ └─────────┘ └─────────┘ └─────────┘ (50-500 MB) │
│ ┌─────────────────────────────────────┐ │
│ │ Docker Engine │ <- Docker │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ Host OS │ <- Спільна ОС │
│ └─────────────────────────────────────┘ │
│ ┌─────────────────────────────────────┐ │
│ │ Hardware │ <- Залізо │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Головна різниця: контейнери використовують ядро (kernel) хостової ОС, а VM — повну операційну систему кожна.
| Характеристика | VM | Container |
|---|---|---|
| Розмір | 1-50 GB | 10-500 MB |
| Запуск | Хвилини | Секунди |
| Ізоляція | Повна | На рівні процесу |
| Використання RAM | Високе | Низьке |
| Накладні витрати | Значні | Мінімальні |
Навіщо Docker?¶
Проблема без Docker¶
Розробник: "Все працює на моїй машині!"
|
+-- Python 3.11 встановлено
+-- PostgreSQL 15 на порту 5432
+-- Redis працює
+-- Всі змінні середовища налаштовані
|
v
Сервер: "Нічого не працює..."
|
+-- Python 3.8 (стара версія)
+-- PostgreSQL 14 (інша версія)
+-- Redis не встановлено
+-- Змінні середовища? Які?
Рішення з Docker¶
Розробник: docker build -t myapp .
|
v
[Docker Image]
|
+-- Python 3.11 ✓
+-- PostgreSQL client ✓
+-- Redis client ✓
+-- Всі залежності ✓
+-- Змінні середовища ✓
|
v
Будь-який сервер: docker run myapp
|
v
"Працює ідентично скрізь!"
Основні концепції¶
Image (Образ)¶
Образ — це шаблон для створення контейнера. Як ISO-файл для встановлення ОС, тільки для застосунку.
- Образ незмінний (immutable)
- Складається з шарів (layers)
- Зберігається в реєстрі (Docker Hub, GitHub Container Registry)
# Завантажити образ
docker pull nginx:alpine
# Список локальних образів
docker images
Container (Контейнер)¶
Контейнер — це запущений екземпляр образу. Як процес у системі, але ізольований.
- Контейнер можна запускати, зупиняти, видаляти
- Кожен контейнер має свою файлову систему
- Можна запустити багато контейнерів з одного образу
┌──────────────────┐
│ Image: nginx │ <-- Один образ
└────────┬─────────┘
│
┌────┴────┐
│ │
v v
┌───────┐ ┌───────┐
│ web-1 │ │ web-2 │ <-- Багато контейнерів
└───────┘ └───────┘
Docker Hub¶
Docker Hub — це публічний реєстр образів. Як GitHub, тільки для Docker образів.
Популярні офіційні образи:
- nginx — веб-сервер
- postgres — база даних
- python — Python середовище
- node — Node.js середовище
- redis — кеш/черга
# Знайти образ
docker search nginx
# Завантажити конкретну версію
docker pull postgres:15-alpine
Базові команди¶
Запуск контейнера¶
# Базовий запуск
docker run nginx
# З параметрами
docker run -d --name webserver -p 8080:80 nginx
# │ │ │
# │ │ └── порт хоста:порт контейнера
# │ └── дати ім'я контейнеру
# └── запустити у фоні (detached)
Робота з контейнерами¶
# Список запущених контейнерів
docker ps
# Всі контейнери (включно з зупиненими)
docker ps -a
# Зупинити контейнер
docker stop webserver
# Запустити зупинений контейнер
docker start webserver
# Перезапустити
docker restart webserver
# Видалити контейнер
docker rm webserver
# Видалити працюючий контейнер примусово
docker rm -f webserver
Логи та діагностика¶
# Логи контейнера
docker logs webserver
# Логи в реальному часі
docker logs -f webserver
# Останні 100 рядків
docker logs --tail 100 webserver
# Виконати команду в контейнері
docker exec -it webserver bash
# │
# └── -i (interactive) + -t (tty) = інтерактивний термінал
Робота з образами¶
# Список образів
docker images
# Видалити образ
docker rmi nginx:alpine
# Очистити невикористані образи
docker image prune -a
# Перевірити використання диску
docker system df
Практичний приклад: запуск Nginx¶
Давайте запустимо веб-сервер Nginx і побачимо його в дії.
Крок 1: Запуск¶
# Завантажуємо та запускаємо nginx
docker run -d --name my-nginx -p 8080:80 nginx:alpine
Що означають параметри:
- -d — запустити у фоновому режимі
- --name my-nginx — назвати контейнер "my-nginx"
- -p 8080:80 — пробросити порт 80 контейнера на порт 8080 хоста
- nginx:alpine — образ nginx на базі Alpine Linux (мінімальний)
Крок 2: Перевірка¶
# Перевіряємо чи працює
docker ps
# Дивимось логи
docker logs my-nginx
# Відкриваємо в браузері
curl http://localhost:8080
Крок 3: Власний контент¶
# Створюємо свій HTML файл
mkdir -p /tmp/mysite
echo "<h1>Привіт від Docker!</h1>" > /tmp/mysite/index.html
# Запускаємо з монтуванням директорії
docker rm -f my-nginx
docker run -d --name my-nginx \
-p 8080:80 \
-v /tmp/mysite:/usr/share/nginx/html:ro \
nginx:alpine
# │
# └── :ro = read-only (тільки читання)
Крок 4: Заходимо всередину¶
# Зайти в контейнер
docker exec -it my-nginx sh
# Всередині контейнера:
ls /usr/share/nginx/html/
cat /etc/nginx/nginx.conf
exit
Крок 5: Очистка¶
# Зупинити та видалити
docker stop my-nginx
docker rm my-nginx
# Або одразу
docker rm -f my-nginx
Життєвий цикл контейнера¶
docker pull
│
v
┌───────────┐
│ Image │
└─────┬─────┘
│ docker run
v
┌───────────┐
│ Created │
└─────┬─────┘
│ docker start
v
┌───────────┐ docker stop ┌───────────┐
│ Running │ ───────────────> │ Stopped │
└───────────┘ └─────┬─────┘
│ │
│ docker rm │ docker rm
v v
┌───────────────────────────────────────┐
│ Removed │
└───────────────────────────────────────┘
Типові помилки¶
Порт вже зайнятий¶
# Помилка
Error: bind: address already in use
# Рішення: знайти що займає порт
lsof -i :8080
# або використати інший порт
docker run -p 8081:80 nginx
Контейнер одразу зупиняється¶
# Перевірити логи
docker logs container_name
# Частіше за все: команда в контейнері завершилась
# або помилка в конфігурації
"Permission denied" при монтуванні¶
# На Linux: SELinux може блокувати
docker run -v /path:/container/path:z nginx
# │
# └── :z для SELinux
# Або перевірити права на директорію
ls -la /path
Контейнер не бачить інші контейнери¶
# Контейнери повинні бути в одній мережі
docker network create mynet
docker run --network mynet --name db postgres
docker run --network mynet --name app myapp
Корисні аліаси¶
Додайте в ~/.bashrc або ~/.zshrc:
alias d='docker'
alias dps='docker ps'
alias dpsa='docker ps -a'
alias di='docker images'
alias dex='docker exec -it'
alias dlogs='docker logs -f'
alias dstop='docker stop $(docker ps -q)' # Зупинити всі
alias drm='docker rm $(docker ps -aq)' # Видалити всі зупинені
Див. також¶
- Docker Compose — запуск багатьох контейнерів
- Віртуалізація — порівняння підходів
- Docker команди — повна шпаргалка
Шлях: infrastructure/docker-basics.md