Docker для начинающих на Linux: от первой установки до работающего compose
Меня зовут Семёнов Евгений Сергеевич, я руковожу компанией АйТи Фреш. За 15 лет я перевидал как админы боятся Docker, пока не поставят его один раз руками и не поднимут свой первый контейнер. У нас на практике Docker в инфраструктуре почти везде: на 8 серверах Dell Xeon Platinum 8280 в дата-центре МТС Москва, на клиентских виртуалках, на ноутбуках разработчиков. Эта статья — первый шаг для тех, кто админит Linux, но ещё не работал с контейнерами.
Зачем вообще нужен Docker
Контейнеризация решает старую головную боль: «у меня работает, у тебя нет». Упаковали приложение со всеми библиотеками в образ — и он одинаково запускается на ноуте разработчика, на стейджинге и на боевом сервере. Никаких плясок с зависимостями, разными версиями Python или libc.
Практические выигрыши, которые я вижу у клиентов:
- Разворачивание нового сервиса — 30 секунд вместо часа ручной настройки.
- Откат при проблемах — одной командой возвращаем предыдущий образ.
- Плотность: на одном VPS живут 10–15 сервисов без конфликтов зависимостей.
- Легче отдавать подрядчикам — они получают готовый compose-файл и не трогают продакшн.
Установка Docker на Ubuntu 22.04 / Debian 12
Не ставьте apt install docker.io, там обычно старая версия. Берите официальный репозиторий Docker. Последовательность одинаковая для Ubuntu и Debian, меняется только дистрибутив в URL.
sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
# Перезайдите в систему, чтобы группа применилась
Проверяем:
docker version
docker run --rm hello-world
Первые команды: образ, контейнер, логи
Коротко о терминологии. Образ (image) — это шаблон, неизменяемая файловая система. Контейнер — запущенный инстанс образа с добавленным писчим слоем. Образы живут в реестре (Docker Hub, GitLab Registry, свой Harbor). Запуск контейнера скачивает образ, если его нет локально.
# Скачать образ без запуска
docker pull nginx:1.27-alpine
# Запустить в фоне с пробросом порта
docker run -d --name web -p 8080:80 nginx:1.27-alpine
# Посмотреть бегущие контейнеры
docker ps
# Логи
docker logs -f web
# Зайти внутрь
docker exec -it web sh
# Остановить и удалить
docker stop web && docker rm web
Флаг --rm говорит Docker удалить контейнер после остановки — удобно для разовых команд. -it — интерактивный TTY для shell-а. Я всегда даю контейнерам имена через --name, иначе Docker генерирует забавные, но неудобные hungry_turing.
Тома и постоянные данные
Файловая система контейнера пропадает вместе с ним. Чтобы сохранить базу, загрузки, настройки — используйте volume или bind mount.
| Тип | Где хранится | Когда применять |
|---|---|---|
| Named volume | /var/lib/docker/volumes/ | Продакшн, базы данных, чистые бэкапы |
| Bind mount | Любой путь хоста | Разработка, доступ к коду, логи наружу |
| tmpfs | ОЗУ | Секреты, временные кеши |
# Named volume — рекомендую для продакшна
docker volume create pgdata
docker run -d --name pg \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
-p 5432:5432 postgres:16
# Bind mount — удобно на разработке
docker run -d --name web \
-v /srv/sites/mysite:/usr/share/nginx/html:ro \
-p 80:80 nginx:alpine
Сети Docker
По умолчанию Docker создаёт bridge-сеть, где контейнеры видят друг друга по IP. Для удобства делайте именованные сети — тогда контейнеры резолвятся по именам.
docker network create app-net
docker run -d --name db --network app-net \
-e POSTGRES_PASSWORD=secret postgres:16
docker run -d --name api --network app-net \
-e DB_HOST=db -p 8000:8000 myapp:latest
Из контейнера api база доступна по имени db — DNS работает автоматически. Это база для микросервисов.
Dockerfile: свой образ за 5 минут
Dockerfile — рецепт сборки образа. Начинаем с базового, копируем файлы, ставим зависимости, задаём точку входа. Пример для простого Python-приложения:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
docker build -t myapp:0.1 .
docker run -d --name myapp -p 8000:8000 myapp:0.1
Правила, которые экономят часы в будущем: ставьте зависимости ДО копирования кода (кеш слоёв), фиксируйте версии базовых образов (python:3.12-slim, а не python:latest), используйте .dockerignore, чтобы не тащить в образ .git, node_modules и виртуалки.
Docker Compose: оркестрация для маленьких
Запускать по пять docker run подряд неудобно. Compose описывает все сервисы в одном YAML. Файл docker-compose.yml:
services:
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
api:
build: .
restart: unless-stopped
depends_on: [db]
environment:
DB_HOST: db
ports:
- "8000:8000"
volumes:
pgdata:
docker compose up -d
docker compose logs -f
docker compose down
Реальный кейс: миграция самописного PHP на Docker
Однажды в 2024 году мы забирали на обслуживание небольшую логистическую компанию в Химках, 42 рабочих места. У клиента был самописный PHP-портал заказов на стареньком CentOS 7. Обновить CentOS без риска уронить сайт было нельзя — разработчик исчез три года назад. Мы упаковали всё в три контейнера: php-fpm 8.1, nginx, mariadb 10.11. Dockerfile собрался за вечер, миграция базы заняла 40 минут.
Результаты: портал переехал на свежий Ubuntu 22.04 с полной поддержкой безопасности. Срок работ — 4 рабочих дня, стоимость 78 000 руб. Через полгода клиент сам попросил перенести в контейнеры 1С веб-клиент, потому что понравилась простота обновлений.
Грабли, на которые наступают все новички
- Забитый
/var/lib/docker. Старые образы и контейнеры копятся. Командаdocker system prune -af --volumesчистит, но будьте аккуратны с--volumes. - Запуск под root внутри контейнера. Лучше добавить в Dockerfile
USER appuser, иначе уязвимость в приложении даёт рута в контейнере. - latest в продакшне. Без явной версии вы не знаете, что обновилось. Фиксируйте теги.
- Логи в stdout, а не в файл. Docker умеет json-file/journald/syslog-драйверы — настройте ротацию в
/etc/docker/daemon.json, иначе логи съедят диск. - Игнор healthcheck. Без
HEALTHCHECKcompose не понимает, что контейнер поднялся — может быть гонка при depends_on.
Поможем перевести инфраструктуру на Docker
У нас 8 серверов Dell Xeon Platinum 8280 с 40G Mellanox в дата-центре МТС Москва. Упакуем ваши приложения в контейнеры, настроим compose или Swarm, организуем логирование и бэкапы. Бесплатный аудит по telegram — за час.
Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш
FAQ — частые вопросы по Docker
- Чем Docker отличается от виртуальной машины?
- Контейнер Docker использует ядро хоста и изолирует только процессы и файловую систему через namespaces и cgroups. Виртуалка эмулирует железо и запускает своё ядро. Контейнер стартует за секунду, весит десятки мегабайт, ВМ — за минуту и гигабайты.
- Можно ли ставить Docker в продакшн на Ubuntu Server?
- Да, это стандартная практика. Docker CE на Ubuntu LTS (22.04, 24.04) работает стабильно. Ставьте из официального репозитория docker.com, а не apt-овский docker.io — там версия отстаёт.
- Что делать, если контейнер завис и не останавливается?
- Сначала пробуем
docker stop— он шлёт SIGTERM и ждёт 10 секунд. Если не помогло —docker killшлёт SIGKILL. В крайнем случае можно перезапустить демонsystemctl restart docker, но это убьёт все контейнеры. - Куда Docker складывает данные?
- По умолчанию — в
/var/lib/docker. Там образы, контейнеры, тома. Если диск маленький — перенесите на отдельный раздел через daemon.json:"data-root": "/data/docker". - Нужен ли root для работы с Docker?
- Для команд docker — не обязательно. Добавьте пользователя в группу docker (
usermod -aG docker user) и перезайдите. Но помните: членство в этой группе фактически равно root на хосте, поэтому давайте осторожно.