Що таке Docker і навіщо він потрібен

Docker — платформа контейнеризації, яка дозволяє упакувати застосунок разом із усіма залежностями в ізольований контейнер. Контейнер однаково запускається на ноутбуці розробника, CI-сервері та production — кінець ері "у мене все працює, а у вас — ні".

Придуманий у 2013 році, сьогодні Docker став стандартом індустрії. 87% DevOps-інженерів використовують його щодня.

Контейнери vs Віртуальні машини

ХарактеристикаКонтейнери (Docker)Віртуальні машини
Час запускусекундихвилини
Розмір образуMBGB
Ізоляціяпроцесна (ядро OS)повна (окреме ядро)
Споживання RAMмінімальнезначне
Переносимістьвисокасередня
Безпеканижча (спільне ядро)вища

Контейнери не замінюють ВМ повністю — вони доповнюють їх. Зазвичай на одній ВМ запускають багато контейнерів.

Основи Dockerfile

Dockerfile — текстовий файл з інструкціями для побудови образу. Приклад для Laravel-застосунку:

# Базовий образ
FROM php:8.4-fpm-alpine

# Встановлення залежностей
RUN apk add --no-cache \
    git curl libpng-dev libzip-dev \
    && docker-php-ext-install pdo_mysql zip gd

# Встановлення Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Робочий каталог
WORKDIR /var/www

# Копіювання файлів
COPY . .

# Встановлення залежностей PHP
RUN composer install --no-dev --optimize-autoloader

# Права доступу
RUN chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache

EXPOSE 9000
CMD ["php-fpm"]

Ключові інструкції Dockerfile

  • FROM — базовий образ (Alpine = легкий Linux)

  • RUN — виконати команду під час побудови образу

  • COPY — скопіювати файли з хоста в контейнер

  • WORKDIR — встановити робочий каталог

  • EXPOSE — оголосити порт (документація, не публікація)

  • CMD — команда запуску контейнера

Docker Compose: оркестрація локального середовища

docker-compose.yml дозволяє описати всі сервіси проекту та їхні зв'язки в одному файлі.

Реальний приклад: Laravel + MySQL + Redis + Nginx

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/var/www
      - ./storage:/var/www/storage
    environment:
      - DB_HOST=mysql
      - DB_DATABASE=laravel
      - DB_USERNAME=laravel
      - DB_PASSWORD=secret
      - REDIS_HOST=redis
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - app-network

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - .:/var/www
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - app
    networks:
      - app-network

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: secret
    volumes:
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - app-network

  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data
    networks:
      - app-network

volumes:
  mysql-data:
  redis-data:

networks:
  app-network:
    driver: bridge

Основні команди

# Запустити всі сервіси (фоновий режим)
docker compose up -d

# Зупинити
docker compose down

# Переглянути логи
docker compose logs -f app

# Виконати команду в контейнері
docker compose exec app php artisan migrate

# Перебудувати образ
docker compose build app

Переваги Docker для команд

  • Однакове середовище: junior відтворює production-умови за 5 хвилин замість дня налаштувань

  • Ізоляція проектів: Python 3.9 для одного і Python 3.12 для іншого — без конфліктів

  • Швидкий онбординг: docker compose up -d — і новий розробник готовий до роботи

  • Відтворюваність білдів: образ зібраний сьогодні = образ зібраний через рік

  • Горизонтальне масштабування: docker compose up --scale app=3

CI/CD з Docker

Docker ідеально інтегрується з GitHub Actions, GitLab CI, Jenkins:

# .github/workflows/deploy.yml (фрагмент)
- name: Build Docker image
  run: docker build -t myapp:${{ github.sha }} .

- name: Push to registry
  run: |
    docker tag myapp:${{ github.sha }} registry.example.com/myapp:latest
    docker push registry.example.com/myapp:latest

- name: Deploy to server
  run: |
    ssh deploy@server "docker pull registry.example.com/myapp:latest && \
    docker compose -f /srv/myapp/docker-compose.prod.yml up -d"

Docker Desktop vs Linux

Docker Desktop (Win/Mac)Docker на Linux
ВстановленняGUI-інсталяторapt/yum пакет
Продуктивністьнижча (гіпервізор)рідна, без накладних
Цінабезкоштовно для особистого/SMBбезкоштовно
Volume bindingповільніше (особливо Mac)швидко
Productionне використовуєтьсястандарт

Для Windows-розробки альтернатива Docker Desktop — WSL2 + Docker Engine напряму, що дає кращу продуктивність.

Типові помилки початківців

  1. Зберігати дані в контейнері — при перезапуску всі дані зникнуть. Використовуйте volumes.

  2. Запускати все в одному контейнері — один контейнер = один процес. PHP і Nginx — окремо.

  3. Ігнорувати .dockerignore — без нього в образ потрапляють node_modules та .git (сотні MB зайвого).

  4. Використовувати latest тегmysql:latest може зламати проект після оновлення. Фіксуйте версії: mysql:8.0.

  5. Зберігати секрети в Dockerfile — паролі та токени передавайте через environment змінні або Docker secrets.

Коли Docker НЕ потрібен

  • Простий статичний сайт на shared-хостингу

  • Команда з одного розробника на типовому LAMP стеку

  • Legacy PHP 5.x проекти — ризик несумісності вищий за вигоду

  • Embedded-системи з жорсткими обмеженнями ресурсів

Висновок

Docker вирішує реальні проблеми: "працює у мене", різні версії залежностей, складний онбординг, нестабільні деплої. Якщо у вас команда хоча б з двох розробників або ви деплоїте на власний сервер — Docker скупиться на собі за перший місяць.

Потрібна допомога з налаштуванням Docker для вашого проекту? Ми налаштуємо все — від локального dev-середовища до production CI/CD pipeline.