Урок 4 из 8 · 20 мин · обновлено

Контейнеры: Docker

Зачем DevOps-инженеру контейнеры: проблема «у меня работает», Dockerfile для приложения, образы и реестр, Docker Compose для сайта с базой данных.

«У меня работает»

Разработчик «Чайной лавки» проверил новую версию у себя — всё отлично. На сервере сайт падает: там другая версия Python и не хватает одной библиотеки. Знакомая ситуация в любой команде.

Контейнер решает это: приложение упаковывается вместе со всем, что ему нужно, — нужной версией языка, библиотеками, настройками. Такой «ящик» работает одинаково на ноутбуке разработчика, в конвейере сборки и на сервере. Самый популярный инструмент для контейнеров — Docker. Подробный курс — «Docker для начинающих».

Dockerfile и образ

Инструкция, как собрать «ящик», — Dockerfile:

Dockerfile
FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "shop.wsgi"]

По шагам: взять готовый образ с Python, перейти в папку /app, установить библиотеки, скопировать код и запустить сайт.

По Dockerfile собирают образ — шаблон, а по образу запускают контейнеры:

Терминал
docker build -t shop:1.4.0 .
docker run -d -p 8000:8000 shop:1.4.0

Реестр и версии

Собранные образы хранят в реестре — хранилище образов. Конвейер из урока 3 после тестов собирает образ и отправляет его в реестр, а сервер забирает оттуда.

Каждый образ помечают версией: shop:1.4.0 или номером коммита. Если новая версия оказалась с ошибкой, откат — это просто запуск предыдущего образа, а не восстановление файлов по памяти.

Docker Compose: несколько контейнеров

Сайту «Чайной лавки» нужна база данных. Удобно описать оба контейнера в одном файле compose.yaml:

YAML
services:
  web:
    image: registry.example.ru/shop:1.4.0
    ports:
      - "8000:8000"
    environment:
      DATABASE_HOST: db
    depends_on:
      - db
  db:
    image: postgres:17
    env_file: .env
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

Одна команда поднимает всё сразу:

Терминал
docker compose up -d
Результат
 ✔ Container shop-db-1   Started
 ✔ Container shop-web-1  Started

Обратите внимание на две вещи:

  • volumes — данные базы лежат в томе db-data, отдельно от контейнера. Контейнер пересоздают при каждом обновлении, и всё, что было внутри, исчезает. Том — нет.
  • env_file: .env — пароль базы лежит в файле .env на сервере. Этот файл не добавляют в Git, как и любые секреты из урока 3.

Попробуйте сами. Добавьте в compose.yaml «Чайной лавки» кэш Redis — контейнер cache из образа redis:7, — и сделайте так, чтобы сайт запускался после него.

Пример ответа
YAML
services:
  web:
    image: registry.example.ru/shop:1.4.0
    ports:
      - "8000:8000"
    environment:
      DATABASE_HOST: db
      CACHE_HOST: cache
    depends_on:
      - db
      - cache
  cache:
    image: redis:7
  db:
    image: postgres:17
    env_file: .env
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

Порт кэша наружу не открываем: сайт обращается к нему по имени cache внутри общей сети Compose.

Мини-тест · 4 вопроса

Проверьте себя

Выберите вариант, который кажется вам правильным. В конце вы увидите свой результат и объяснение к каждому вопросу.

  1. Какую проблему решают контейнеры?

  2. Чем образ отличается от контейнера?

  3. Зачем помечать образы номером версии, а не только latest?

  4. Где хранить данные базы данных, запущенной в контейнере?