Docker для начинающих на Linux: от первой установки до работающего compose
Меня зовут Семёнов Евгений Сергеевич, и я руковожу компанией АйТи Фреш. За 15 лет в IT я не раз видел одно и то же: админы прямо-таки боятся 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. Обновить его было равносильно самоубийству для сайта — разработчик испарился года три назад, никаких контактов. Что мы предложили? Упаковали весь этот портал в три аккуратных контейнера: 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 на хосте, поэтому давайте осторожно.
