Установка Docker и первые команды

Установка Docker и первые команды

Нам нужен базовый набор команд, чтобы не паниковать при слове «контейнер». В этом уроке - установка, первый запуск и 10 команд, которые покрывают 90% ежедневной работы.

Установка

<ComparisonTable title="Docker Desktop vs Docker Engine" headers={["", "Docker Desktop", "Docker Engine"]} rows={[ ["Платформа", "macOS, Windows, Linux GUI", "Linux (сервер)"], ["Интерфейс", "GUI + CLI", "Только CLI"], ["Ресурсы", "Больше (VM под капотом на Mac/Win)", "Минимальные"], ["Лицензия", "Бесплатно для личного/образования", "Бесплатно (open source)"], ["Когда использовать", "Локальная разработка", "Серверы и CI"] ]} />

Выбери свою ОС:

Скачай Docker Desktop с официального сайта и установи .dmg. В комплекте - Docker Engine, CLI, Compose и GUI.

# Проверка через Homebrew (опциональная альтернатива)
brew install --cask docker

После установки запусти Docker Desktop из Launchpad - без этого CLI работать не будет.

# Установка Docker Engine + Compose-плагин
sudo apt update
sudo apt install -y docker.io docker-compose-plugin

# Чтобы запускать docker без sudo
sudo usermod -aG docker $USER
newgrp docker   # или перелогиниться
  1. Включи WSL2 (wsl --install в PowerShell от админа).
  2. Скачай Docker Desktop с официального сайта и установи .exe.
  3. В настройках Docker Desktop включи интеграцию с твоим WSL-дистрибутивом.

Чисто Windows-команды (PowerShell) работают, но удобнее работать из WSL - там команды точно такие же, как во вкладке Linux.

Проверка установки

docker --version          # Docker version 27.x
docker compose version    # Docker Compose version v2.x
docker info               # подробная информация о демоне
Старый `docker-compose` (через дефис) - отдельная утилита (v1), устарела. Новый `docker compose` (через пробел) - встроенный плагин (v2). Всегда используй `docker compose`.

Первый запуск

docker run --rm hello-world

Что произошло:

  1. Docker ищет образ hello-world локально - не находит
  2. Скачивает из Docker Hub (registry по умолчанию)
  3. Создаёт контейнер из образа
  4. Запускает процесс внутри контейнера (вывод текста)
  5. --rm - удаляет контейнер после завершения

Жизненный цикл контейнера

Жизненный цикл Docker-контейнера: Образ → create → Created → start → Running → stop → Stopped → rm

На практике docker run = create + start в одной команде.

# Запустить и сразу удалить после выхода
docker run --rm nginx:alpine

# Запустить в фоне (-d = detach)
docker run -d --name web nginx:alpine

# Остановить
docker stop web

# Удалить
docker rm web

# Запустить + остановить + удалить - всё в одном
docker run --rm -d -p 8080:80 --name web nginx:alpine

10 команд на каждый день

Работа с контейнерами

docker ps                       # запущенные контейнеры
docker ps -a                    # все (включая остановленные)
docker logs web                 # логи контейнера
docker logs -f --tail=50 web    # follow + последние 50 строк
docker exec -it web sh          # зайти внутрь контейнера
docker stop web                 # остановить (SIGTERM, 10с, SIGKILL)
docker rm web                   # удалить остановленный контейнер

Работа с образами

docker images                   # список локальных образов
docker pull nginx:alpine        # скачать образ
docker rmi nginx:alpine         # удалить образ
  • -d - detach (фон)
  • -p 8080:80 - проброс порта (хост:контейнер)
  • --name web - дать имя контейнеру
  • --rm - удалить после остановки
  • -it - интерактивный терминал (для exec/run)
  • -e KEY=VALUE - переменная окружения
  • -v /host/path:/container/path - монтирование тома

Проброс портов

Контейнер по умолчанию изолирован от сети хоста. Чтобы достучаться, пробрасываем порт:

# Формат: -p ПОРТ_ХОСТА:ПОРТ_КОНТЕЙНЕРА
docker run -d -p 8080:80 --name web nginx:alpine
# Теперь http://localhost:8080 → nginx внутри контейнера на порту 80

Можно пробросить несколько портов:

docker run -d -p 8080:80 -p 8443:443 --name web nginx:alpine
`Error: port is already allocated` - значит на порту 8080 уже что-то слушает. Либо останови другой контейнер, либо используй другой порт: `-p 9090:80`.

Переменные окружения

docker run --rm -e POSTGRES_PASSWORD=secret -e POSTGRES_DB=mydb postgres:16-alpine

Несколько переменных - несколько флагов -e. Для большого числа переменных удобнее --env-file:

docker run --rm --env-file .env postgres:16-alpine

Очистка системы

Docker накапливает остановленные контейнеры, неиспользуемые образы и volumes:

docker system df              # показать, сколько места занято
docker system prune           # удалить всё неиспользуемое (контейнеры, сети, кэш)
docker system prune -a        # + удалить образы без контейнеров
docker volume prune           # удалить неиспользуемые volumes
`docker system prune -a` удалит все образы, которые не используются запущенным контейнером. После этого потребуется заново скачивать и пересобирать образы. Используй осознанно.

Мини-задание

  • Запусти nginx: docker run -d -p 8080:80 --name web nginx:alpine
  • Открой http://localhost:8080 - увидишь страницу nginx
  • Посмотри логи: docker logs web
  • Зайди внутрь: docker exec -it web sh
  • Внутри контейнера: ls /usr/share/nginx/html/, cat /etc/nginx/nginx.conf, exit
  • Останови и удали: docker stop web && docker rm web

Итог

  • Docker Desktop - для разработки (macOS/Windows), Docker Engine - для серверов (Linux).
  • docker compose (v2, через пробел) вместо устаревшего docker-compose.
  • Жизненный цикл: create → start → stop → rm. docker run = create + start.
  • 10 команд (ps, logs, exec, stop, rm, images, pull, rmi, run, build) покрывают 90% ежедневной работы.
  • --rm для временных контейнеров, -d для фоновых, -p для проброса портов.

Типичная ошибка

Забываешь остановить контейнер перед удалением - docker rm web не работает, если контейнер запущен. Нужно сначала docker stop web, потом docker rm web. Или используй docker rm -f web - принудительное удаление.

Другая ошибка - запускать контейнеры без --rm для тестов. Через неделю docker ps -a показывает 50 остановленных контейнеров. Для одноразовых запусков всегда --rm.

Мини-практика (10-15 минут)

Подними PostgreSQL в контейнере и подключись к нему:

# Запусти PostgreSQL
docker run -d --name pg \
 -e POSTGRES_PASSWORD=secret \
 -e POSTGRES_DB=testdb \
 -p 5432:5432 \
  postgres:16-alpine

# Подожди пару секунд, проверь готовность
docker logs pg

# Подключись изнутри контейнера
docker exec -it pg psql -U postgres -d testdb

# Внутри psql:
# CREATE TABLE users (id serial, name text);
# INSERT INTO users (name) VALUES ('Docker');
# SELECT * FROM users;
# \q

# Очистка
docker stop pg && docker rm pg

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

Зарегистрируйтесь бесплатно, чтобы пройти квиз, решить задание с автопроверкой и вести прогресс.