Привет, Хабр! Это продолжение серии про QA-собеседования. Уже разобрали тест-дизайн, API и Security, System Design и SQL. Теперь — Docker.
Если при слове «контейнер» в голове только грузовые суда — эта статья для вас.
Содержание
1. Зачем QA вообще Docker?
Коротко: Docker нужен QA, чтобы запускать одинаковое окружение локально, в CI и у коллег, быстро поднимать зависимости и воспроизводить баги без «у меня не повторяется».
Потому что «у меня всё работает» — это не баг-репорт, а крик о помощи.
Вот реальная ситуация. Тестировщик прогоняет автотесты на своей машине — всё зелёное. Пушит в CI — три теста красные. Начинает разбираться: на его машине PostgreSQL 15, а в CI — PostgreSQL 14. На его машине Node.js 20, в CI — 18. На его машине Redis запущен, в CI — нет. Потратил полдня на отладку окружения вместо тестирования.
Если бы тесты запускались в Docker — проблемы бы не было. Контейнер одинаковый везде: на ноутбуке, в CI, у коллеги. Это и есть главная идея.
Docker нужен QA для четырёх вещей:
# | Зачем | Пример |
|---|---|---|
1 | Одинаковое окружение | Локально, в CI, у коллеги — одна и та же версия всего |
2 | Быстрый старт зависимостей | Нужна БД для тестов? |
3 | Изоляция | Тест-сьют не ломает вашу систему, а контейнер можно удалить без следа |
4 | Воспроизведение багов | «Баг только на production» — подними такой же контейнер и проверь |
2. Что такое Docker (простыми словами)
Коротко: Docker упаковывает приложение и его зависимости в контейнер, который запускается одинаково на любой машине.
2.1 Аналогия
Представьте, что вы заказали пиццу. Вам привезли коробку, внутри — готовая пицца. Вам не нужно знать, какая печь на кухне, какая марка муки, какой рецепт теста. Вы открываете коробку — и едите.
Docker работает так же. Вместо того чтобы устанавливать PostgreSQL, Node.js, Redis и ещё 15 зависимостей на свою машину — вы запускаете контейнер, в котором всё это уже есть и настроено. Контейнер — это коробка с готовым приложением.
2.2 Три ключевых понятия
Понятие | Что это | Аналогия |
|---|---|---|
Image (образ) | Описание того, что внутри контейнера. Скачивается один раз | Рецепт / Класс |
Container (контейнер) | Работающий экземпляр образа | Готовое блюдо / Объект |
Dockerfile | Текстовый файл с инструкциями для создания образа | Кулинарная книга |
Из одного образа можно запустить 10 контейнеров — как из одного класса можно создать 10 объектов.
2.3 Docker vs виртуальная машина
Docker-контейнер | Виртуальная машина | |
|---|---|---|
Запуск | Секунды | Минуты |
Размер | Мегабайты | Гигабайты |
ОС | Общее ядро с хостом | Своя полная ОС |
Изоляция | На уровне процессов | Полная |
Для QA | Тестовые окружения, CI | Тестирование на другой ОС |
Для 95% задач тестировщика Docker — правильный выбор. VM нужна только если тестируете под другую ОС (например, Windows-прил��жение на Mac).
3. Установка Docker
Коротко: Для Windows и macOS чаще всего ставят Docker Desktop, для Linux — пакетами. После установки обязательно проверьте, что запускаются и сам Docker, и тестовый контейнер.
3.1 Windows / macOS
Скачайте Docker Desktop и установите. После установки в трее появится иконка кита. Если кит счастливый — Docker работает.
3.2 Linux
sudo apt-get update sudo apt-get install docker.io docker-compose sudo usermod -aG docker $USER
3.3 Проверка
После установки перезайдите в систему и проверьте:
docker --version
Если видите что-то вроде Docker version 27.x.x — всё работает.
docker run hello-world
Если видите Hello from Docker! — контейнеры запускаются. Можно двигаться дальше.
4. docker run — запускаем первый контейнер
Коротко: docker run — базовая команда, которая создаёт контейнер, задаёт ему имя, переменные окружения, порты и сразу запускает его.
4.1 Запуск PostgreSQL
Начнём с того, что нужно каждому тестировщику — поднять базу данных:
docker run --name test-db -e POSTGRES_PASSWORD=secret -p 5432:5432 -d postgres:16
4.2 Разбор команды
Часть | Что делает |
|---|---|
| Создать и запустить контейнер |
| Дать контейнеру имя (чтобы не запоминать ID) |
| Переменная окружения (пароль для БД) |
| Пробросить порт: порт_хоста:порт_контейнера |
| Запустить в фоне (detached) |
| Образ и версия |
4.3 Результат
Через 5 секунд у вас работает PostgreSQL. Подключитесь к нему через DBeaver, pgAdmin или из тестов:
Параметр | Значение |
|---|---|
Host | |
Port |
|
User |
|
Password |
|
⚠️ Ловушка: порт уже занят
-p 5432:5432 — порт слева это порт на вашей машине. Если 5432 уже занят (у вас локально стоит Postgres), используйте -p 5433:5432. Подключаетесь к localhost:5433, а внутри контейнера всё равно 5432.
4.4 Ещё примеры docker run
Что запускаем | Команда |
|---|---|
MySQL |
|
Redis |
|
MongoDB |
|
Nginx |
|
Обратите внимание: alpine в redis:7-alpine — это облегчённый образ. Вместо ~100MB получаете ~30MB. Для тестов — идеально.
5. Основные команды Docker
Коротко: Для ежедневной работы QA обычно хватает шести вещей: запустить контейнер, посмотреть список, остановить, удалить, посмотреть логи и зайти внутрь.
5.1 Жизненный цикл контейнера
docker run -d --name my-app nginx docker ps docker ps -a docker stop my-app docker start my-app docker restart my-app docker rm my-app docker rm -f my-app
Команда | Что делает |
|---|---|
| Создать + запустить контейнер |
| Список запущенных контейнеров |
| Все контейнеры (включая остановленные) |
| Остановить контейнер (SIGTERM → SIGKILL через 10с) |
| Запустить остановленный контейнер |
| Перезапустить контейнер |
| Удалить остановленный контейнер |
| Принудительно удалить (даже запущенный) |
5.2 Работа с образами
docker images docker pull nginx:latest docker rmi nginx:latest
Команда | Что делает |
|---|---|
| Список скачанных образов |
| Скачать образ из Docker Hub |
| Удалить образ |
5.3 Отладка — три главных инструмента QA
Команда | Что делает | Когда использовать |
|---|---|---|
| Посмотреть логи контейнера | Контейнер упал или сервис не отвечает |
| Следить за логами в реальном времени | Воспроизводите баг и хотите видеть, что происходит |
| Зайти внутрь контейнера | Проверить файлы, конфиги, переменные окружения |
| Подробная информация (сеть, порты, volumes) | Контейнеры не видят друг друга |
docker logs my-app docker logs -f my-app docker exec -it my-app bash docker inspect my-app
5.4 Очистка — когда диск забился
docker system df docker system prune docker system prune -a --volumes
Команда | Что делает |
|---|---|
| Показать, сколько места занимает Docker |
| Удалить остановленные контейнеры, неиспользуемые сети, повисшие образы |
| Удалить всё неиспользуемое (осторожно!) |
Задача с собеседования: тесты на CI падают с connection refused
«Тесты на CI падают с ошибкой connection refused к базе. Как дебажить?»
Ответ:
docker ps— убедиться, что контейнер с БД запущенdocker logs <имя>— проверить, нет ли ошибок при стартеdocker inspect <имя>— проверить, на каком порту и в какой сети контейнер
Частая причина: контейнер с приложением и контейнер с БД в разных Docker-сетях.
6. Dockerfile — создаём свой образ
Коротко: Dockerfile нужен, когда вы хотите не просто скачать готовый контейнер, а собрать собственный образ, например с автотестами и зависимостями проекта.
Для QA это актуально, когда нужно собрать образ с тестами. Например, упаковать Selenium-тесты в контейнер, чтобы запускать их в CI.
6.1 Пример Dockerfile для тестов
FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["pytest", "--tb=short", "-v"]
6.2 Разбор инструкций
Инструкция | Что делает | Пример |
|---|---|---|
| Базовый образ (на чём строим) |
|
| Рабочая директория внутри контейнера |
|
| Копировать файлы с хоста в контейнер |
|
| Выполнить команду при сборке образа |
|
| Команда по умолчанию при запуске |
|
| Задать переменную окружения |
|
| Документация: какой порт слушает приложение |
|
6.3 Сборка и запуск
docker build -t my-tests . docker run my-tests
-t my-tests — даём образу тег (имя). Точка . — контекст сборки (текущая папка, где лежит Dockerfile).
docker run my-tests pytest tests/test_login.py -v
Можно переопределить CMD и запустить конкретный тест.
6.4 Кэширование слоёв — почему порядок важен
Docker кэширует каждый слой (каждую инструкцию). Если слой не изменился — Docker не пересобирает его и использует готовый результат из кэша.
Что это значит на практике: если вы сначала копируете весь проект, а уже потом ставите зависимости, то любое изменение в коде ломает кэш и заставляет заново выполнять pip install.
Плохо: зависимости пересобираются почти при каждом изменении.
# ❌ Плохо — каждое изменение кода пересобирает зависимости COPY . . RUN pip install -r requirements.txt
Хорошо: сначала копируем файл зависимостей, потом ставим их, и только после этого копируем остальной код.
# ✅ Хорошо — зависимости кэшируются отдельно COPY requirements.txt . RUN pip install -r requirements.txt COPY . .
Правило: сначала копируйте то, что меняется редко (зависимости), потом — то, что меняется часто (код).
⚠️ Ловушка: latest-тег
# ❌ Сегодня Python 3.12, завтра 3.13 — тесты сломались FROM python:latest # ✅ Фиксированная версия FROM python:3.12-slim
Всегда указывайте конкретную версию. latest — это не версия, а указатель на «последнюю», и она меняется без предупреждения.
7. Docker Compose — поднимаем окружение целиком
Коротко: Docker Compose нужен, когда одного контейнера мало и нужно поднять сразу несколько сервисов: базу, API, Redis, фронтенд и тесты.
docker run — это один контейнер. Но для тестирования обычно нужно несколько: база, API, кэш, очередь. Запускать каждый руками — мучение. Docker Compose позволяет описать всё в одном файле и поднять одной командой.
7.1 Пример: API + PostgreSQL + Redis
Что здесь происходит:
Сервис | Роль | Главное, что нужно заметить |
|---|---|---|
| PostgreSQL | Есть |
| Кэш / очередь | Минимальный сервис, который просто поднимается на своём образе |
| Приложение | Ходит в базу по адресу |
services: db: image: postgres:16 environment: POSTGRES_DB: testdb POSTGRES_USER: tester POSTGRES_PASSWORD: secret ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U tester -d testdb"] interval: 5s timeout: 3s retries: 5 redis: image: redis:7-alpine ports: - "6379:6379" api: image: myapp/api:latest ports: - "8080:8080" environment: DATABASE_URL: postgresql://tester:secret@db:5432/testdb REDIS_URL: redis://redis:6379 depends_on: db: condition: service_healthy redis: condition: service_started
Как читать этот файл сверху вниз:
Поднимаем базу
dbи задаём ей переменные окруженияОткрываем порт
5432, чтобы к ней можно было подключиться с хостаПроверяем через
healthcheck, что база действительно готоваПоднимаем
redisкак отдельный сервисПоднимаем
api, передаём ему адреса зависимостей и ждём готовностиdb
7.2 Разбор ключевых параметров
Параметр | Что делает | Пример |
|---|---|---|
| Готовый образ из Docker Hub |
|
| Собрать образ из Dockerfile |
|
| Проброс портов наружу |
|
| Переменные окружения |
|
| Монтирование файлов/данных |
|
| Порядок запуска сервисов |
|
| Проверка готовности сервиса |
|
Обратите внимание: имена сервисов (db, redis, api) работают как DNS-имена внутри Docker-сети. API обращается к базе по адресу db:5432, а не localhost:5432.
7.3 Команды Docker Compose
Команда | Что делает | Когда использовать |
|---|---|---|
| Поднять всё в фоне | Начало работы |
| Статус всех сервисов | Проверить, что всё запустилось |
| Логи конкретного сервиса | Сервис не отвечает |
| Следить за всеми логами | Воспроизведение бага |
| Остановить и удалить контейнеры | Конец работы |
| То же + удалить volumes (данные) | Нужен чистый старт |
| Перезапустить один сервис | Изменили конфиг |
| Пересобрать образы и запустить | Изменили Dockerfile или код |
⚠️ Ловушка: down без -v
docker compose down не удаляет volumes. Если тесты записали мусор в БД — при следующем up данные останутся. Используйте down -v для чистого старта.
8. Volumes — данные, которые переживут контейнер
Коротко: Контейнеры одноразовые, а volumes позволяют сохранить данные между перезапусками или подмонтировать внутрь контейнера файлы с вашей машины.
Контейнер — штука одноразовая. Удалили контейнер — данные внутри пропали. Volumes решают эту проблему.
8.1 Два типа привязок
services: db: image: postgres:16 volumes: - db-data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql volumes: db-data:
Тип | Синтаксис | Когда использовать | Кто управляет |
|---|---|---|---|
Named volume |
| Данные БД, кэш | Docker |
Bind mount |
| Конфиги, init-скрипты, исходный код | Вы (файл на хосте) |
8.2 Практический пример
./init.sql:/docker-entrypoint-initdb.d/init.sql — файл с хоста монтируется внутрь контейнера.
Что произойдёт при запуске:
Docker поднимет контейнер с PostgreSQL
Файл
init.sqlокажется внутри контейнера в специальной папкеPostgreSQL автоматически выполнит этот SQL при первом запуске
Зачем это QA: так удобно быстро заполнить базу тестовыми данными без ручных INSERT-запросов после каждого старта.
8.3 Команды для работы с volumes
Команда | Что делает |
|---|---|
| Список всех volumes |
| Подробная информация о volume |
| Удалить конкретный volume |
| Удалить все неиспользуемые volumes |
9. Docker для тестов: практические сценарии
Коротко: На практике Docker у QA чаще всего используется для трёх вещей: тестовая БД, браузер для UI-тестов и полный стенд из нескольких сервисов.
9.1 Тестовая БД с начальными данными
Идея: вы поднимаете чистую PostgreSQL, а Docker сам заливает стартовые данные из init.sql.
Создайте файл init.sql:
CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, created_at TIMESTAMP DEFAULT NOW() ); INSERT INTO users (name, email) VALUES ('Atajan', 'atajan@test.com'), ('Maria', 'maria@test.com'), ('John', 'john@test.com');
И docker-compose.yml:
services: test-db: image: postgres:16 environment: POSTGRES_DB: testdb POSTGRES_USER: tester POSTGRES_PASSWORD: secret ports: - "5432:5432" volumes: - ./init.sql:/docker-entrypoint-initdb.d/init.sql
docker compose up -d
Результат: через 5 секунд у вас БД с тестовыми данными. Подключаетесь из тестов к localhost:5432 — и работаете. После тестов — docker compose down -v — и всё чисто.
Шаг | Что делаете | Что получаете |
|---|---|---|
1 | Пишете | Набор стартовых таблиц и тестовых данных |
2 | Монтируете файл в контейнер | PostgreSQL видит init-скрипт при старте |
3 | Запускаете | Готовую БД, к которой можно сразу подключаться |
9.2 Selenium-тесты в контейнере
services: chrome: image: selenium/standalone-chrome:latest ports: - "4444:4444" - "7900:7900" shm_size: "2g" tests: build: . depends_on: - chrome environment: SELENIUM_URL: http://chrome:4444/wd/hub
Параметр | Зачем |
|---|---|
| Chrome использует shared memory. Стандартных 64MB не хватает — тесты падают с непонятными ошибками |
Порт | WebDriver API — сюда подключаются тесты |
Порт | VNC — можно подключиться и наблюдать, что делает браузер (пароль: |
9.3 Полный тестовый стенд
Идея: вместо ручного запуска фронтенда, бэкенда, базы и тестов вы описываете всё в одном файле и поднимаете одной командой.
services: db: image: postgres:16 environment: POSTGRES_DB: appdb POSTGRES_USER: app POSTGRES_PASSWORD: secret healthcheck: test: ["CMD-SHELL", "pg_isready -U app -d appdb"] interval: 5s timeout: 3s retries: 5 api: build: ./backend ports: - "8080:8080" environment: DATABASE_URL: postgresql://app:secret@db:5432/appdb depends_on: db: condition: service_healthy frontend: build: ./frontend ports: - "3000:3000" environment: API_URL: http://api:8080 tests: build: ./tests depends_on: - api - frontend environment: BASE_URL: http://frontend:3000 API_URL: http://api:8080
Сервис | Зачем нужен |
|---|---|
| Хранит данные приложения |
| Бэкенд, который работает с базой |
| UI, через который тестируется пользовательский сценарий |
| Контейнер с автотестами, который ходит во фронтенд и API |
Запуск:
docker compose up --abort-on-container-exit tests
Одна команда — и весь стенд поднимается, тесты прогоняются, всё останавливается. Флаг --abort-on-container-exit завершает все сервисы, когда контейнер tests завершится.
10. Networking — почему контейнеры (не) видят друг друга
Коротко: Самая частая ошибка новичков — использовать localhost между контейнерами. В Docker сервисы общаются по именам, а не через localhost.
Это самый частый источник проблем. Разберёмся раз и навсегда.
10.1 Три правила Docker-сети
# | Правило | Что это значит |
|---|---|---|
1 | Контейнеры видят друг друга по имени сервиса | API обращается к базе по |
2 | localhost внутри контейнера = сам контейнер | Если API обращается к |
3 | Порты через | Контейнеры между собой общаются по внутренней сети без проброса |
10.2 Схема
┌─────────────────────────────────────────┐ │ Docker Network │ │ │ │ ┌─────────┐ ┌─────────┐ │ │ │ api │───5432──│ db │ │ │ │ :8080 │ │ :5432 │ │ │ └────┬────┘ └─────────┘ │ │ │ │ └───────┼─────────────────────────────────┘ │ -p 8080:8080 │ ┌────┴────┐ │ Host │ ← ваш ноутбук │ :8080 │ └─────────┘
10.3 Как достучаться до хоста из контейнера
Запомнить: если один контейнер хочет сходить к другому контейнеру — используйте имя сервиса. Если контейнер хочет сходить на вашу машину — используйте адрес хоста из таблицы ниже.
Платформа | Адрес хоста |
|---|---|
Docker Desktop (Windows/Mac) |
|
Linux |
|
Задача с собеседования: connection refused к БД
«Тесты подключаются к БД по localhost:5432, но получают connection refused. Контейнер с БД запущен. В чём проблема?»
Ответ: если тесты тоже в контейнере — нужно использовать имя сервиса (db:5432), а не localhost. Если тесты на хосте — нужно убедиться, что порт проброшен (-p 5432:5432).
11. Переменные окружения и .env
Коротко: Пароли, порты и URL-ы лучше выносить в .env, чтобы не хардкодить их в docker-compose.yml и проще переопределять в CI.
Не хардкодьте пароли и URL-ы в docker-compose.yml. Используйте .env.
11.1 Файл .env
# .env POSTGRES_USER=tester POSTGRES_PASSWORD=secret POSTGRES_DB=testdb API_PORT=8080
11.2 Использование в docker-compose.yml
services: db: image: postgres:16 environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} ports: - "${DB_PORT:-5432}:5432"
Как читать этот пример:
Docker Compose берёт значения из файла
.envПодставляет их в секцию
environmentЕсли
DB_PORTне задан, использует значение по умолчанию5432
11.3 Синтаксис подстановки
Синтаксис | Что делает | Пример |
|---|---|---|
| Подставить значение переменной |
|
| Если не задана — использовать default |
|
| Если не задана — ошибка |
|
Docker Compose автоматически подхватывает файл .env из текущей директории. Не нужно ничего дополнительно указывать.
12. Docker в CI/CD
Коротко: В CI Docker помогает повторить локальное окружение, но сервисы всё равно нужно дождаться, протестировать и в конце корректно убрать.
На CI Docker используется постоянно. Типичный пайплайн:
12.1 Пример для GitHub Actions
# .github/workflows/tests.yml name: Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Start services run: docker compose up -d - name: Wait for DB run: | until docker compose exec db pg_isready -U tester; do sleep 2 done - name: Run tests run: docker compose run tests - name: Cleanup if: always() run: docker compose down -v
12.2 Ключевые моменты
Как этот пайплайн работает по шагам:
Забираем код из репозитория
Поднимаем сервисы через Docker Compose
Ждём, пока база реально начнёт принимать соединения
Запускаем тесты в отдельном контейнере
В конце обязательно удаляем контейнеры и volumes
Что | Зачем |
|---|---|
| Контейнеры будут остановлены даже если тесты упали |
Wait for DB |
|
| Запускает одноразовый контейнер — отработал и остановился |
| Чистим volumes, чтобы следующий запуск был с нуля |
13. Задачи с реальных собеседований
Коротко: На собеседованиях обычно не просят глубокой DevOps-экспертизы. Чаще проверяют, понимаете ли вы причины типовых проблем и можете ли быстро их локализовать.
Задача 1: «У меня локально работает, а в CI нет»
Тесты используют API на localhost:8080. Локально всё работает. В CI (GitHub Actions) — connection refused. Docker Compose одинаковый. В чём может быть проблема?
Где запускаются тесты | Какой адрес использовать |
|---|---|
На хосте |
|
В контейнере |
|
Ответ: локально тесты запускаются на хосте и обращаются к порту, проброшенному через -p. В CI тесты, скорее всего, запускаются в контейнере — значит, localhost:8080 больше не работает. Нужно использовать имя сервиса api:8080 или запускать тесты через docker compose run, где сеть уже общая.
Задача 2: «Тесты влияют друг на друга»
Тесты по отдельности зелёные, а вместе — падают. Один тест создаёт пользователя с email test@test.com, другой тоже. При последовательном запуске второй ловит unique constraint violation. Как исправить с помощью Docker?
Проблема | Причина | Решение |
|---|---|---|
Тесты падают только вместе | Один тест оставляет данные, которые ломают следующий | Поднимать чистую БД перед прогоном или делать откат транзакций |
Ответ: самый прямой способ через Docker — поднимать чистую БД перед каждым набором тестов: docker compose down -v && docker compose up -d. Более аккуратный вариант — транзакции с ROLLBACK в конце теста. Но Docker-подход проще объяснить и проще воспроизвести на собеседовании.
Задача 3: «Контейнер стартует, но сервис не отвечает»
docker compose up -dпрошёл успешно,docker compose psпоказывает все контейнеры running. Но API возвращае�� 502. Как дебажить?
Ответ — пошаговый чек-лист:
Шаг | Команда | Что проверяем |
|---|---|---|
1 |
| Ошибки в логах API |
2 |
| БД запустилась без ошибок? |
3 |
| API отвечает изнутри контейнера? |
4 |
| Статус healthy vs running |
5 |
| Сеть и порты корректны? |
Задача 4: «Объясни, что делает этот docker-compose.yml»
Интервьюер показывает файл и просит объяснить каждую строку. Для этого нужно понимать:
Что спрашивают | Что нужно знать |
|---|---|
| Блок с описанием контейнеров |
| Готовый образ из Hub vs собрать из Dockerfile |
| Порядок запуска (не готовности!) |
| Проверка реальной готовности сервиса |
| Данные, которые переживут контейнер |
|
|
Задача 5: «Напиши docker-compose.yml для тестового окружения»
Нужно: PostgreSQL, Redis, бэкенд (образ
myapp/api:v2), запуск тестов (папка./tests, Dockerfile уже есть). Тесты должны запускаться после готовности API и БД.
services: db: image: postgres:16 environment: POSTGRES_DB: testdb POSTGRES_USER: tester POSTGRES_PASSWORD: secret healthcheck: test: ["CMD-SHELL", "pg_isready -U tester -d testdb"] interval: 5s timeout: 3s retries: 5 redis: image: redis:7-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 5 api: image: myapp/api:v2 environment: DATABASE_URL: postgresql://tester:secret@db:5432/testdb REDIS_URL: redis://redis:6379 depends_on: db: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 10s timeout: 5s retries: 5 tests: build: ./tests environment: API_URL: http://api:8080 DB_URL: postgresql://tester:secret@db:5432/testdb depends_on: api: condition: service_healthy
14. 5 ловушек, на которых валятся кандидаты
Коротко: Почти все ошибки в Docker у QA сводятся к пяти вещам: не тот адрес, не та готовность сервиса, временные данные, забытые volumes и путаница в командах запуска.
# | Ловушка | В чём проблема | Правильно |
|---|---|---|---|
1 | localhost ≠ хост |
| Между контейнерами — имя сервиса. До хоста — |
2 | depends_on ≠ готовность |
|
|
3 | Данные временные | Удалили контейнер — данные пропали | Volumes для сохранения. Для тестов часто это плюс |
4 | down ≠ down -v | Без |
|
5 | CMD ≠ ENTRYPOINT |
| Для тестов — |
15. Чек-лист: что знать перед собеседованием
Коротко: Если понимаете таблицу ниже и можете на практике поднять БД, посмотреть логи и объяснить docker-compose.yml, для большинства QA-собеседований этого уже достаточно.
Тема | Минимум |
|---|---|
Концепции | Image vs container, Dockerfile, Docker Compose, контейнер vs VM |
Команды |
|
Dockerfile | FROM, COPY, RUN, CMD, WORKDIR, порядок слоёв для кэширования |
Docker Compose | services, ports, environment, volumes, depends_on, healthcheck |
Networking | Почему |
Volumes | Named volumes vs bind mounts, зачем |
CI/CD | Как Docker решает «у меня работает», ожидание готовности |
Отладка |
|
Этого хватит для 90% QA-собеседований. Не нужно знать Kubernetes, Docker Swarm или multi-stage builds — это уже DevOps-территория.
16. Полезные ресурсы
Коротко: Ниже только те ресурсы, которые реально помогают быстро войти в тему: официальный старт, песочница, документация по Compose и хорошая подборка ссылок.
# | Ресурс | Описание |
|---|---|---|
1 | Официальный туториал. Хорошо структурирован, с примерами | |
2 | Браузерная песочница. Docker прямо в браузере, ничего не устанавливая | |
3 | Справочник по docker-compose.yml |
