Первые контейнеры
В этом уроке вы запустите первые контейнеры и научитесь ими управлять. Шесть команд покрывают почти всю ежедневную работу: run, ps, logs, exec, stop и rm.
docker run
Заголовок раздела «docker run»Главная команда. Она создаёт контейнер из образа и запускает его:
docker run [опции] ОБРАЗ [команда]Начнём с самого простого:
docker run --rm alpine:3.22 echo "Привет из контейнера"Привет из контейнераЧто сделал Docker:
- Проверил, есть ли образ
alpine:3.22на вашем компьютере. Если нет, скачал его из Docker Hub. Это видно по строкамPulling from library/alpine. В следующий раз скачивания не будет. - Создал контейнер из образа.
- Запустил в нём команду
echo "Привет из контейнера". - Команда закончилась, и контейнер остановился.
- Из-за
--rmDocker удалил остановленный контейнер.
Alpine — очень маленький образ Linux (около 8 МБ). Его удобно брать для проверок.
Контейнер живёт, пока работает его главная команда. Закончилась команда — остановился контейнер. Это главное правило, и оно будет нужно дальше.
Полезные опции
Заголовок раздела «Полезные опции»| Опция | Что делает |
|---|---|
--rm | Удалить контейнер после остановки. Для одноразовых команд |
-d | Запустить в фоне (detached). Терминал остаётся свободным |
--name web | Дать контейнеру имя. Иначе Docker придумает случайное, например quirky_turing |
-p 8080:80 | Открыть порт. Разберём в уроке Порты и переменные |
-it | Интерактивный режим: можно вводить команды в контейнере |
-e NAME=value | Передать переменную окружения |
-v ... | Подключить папку или том. Разберём в уроке Тома |
Сервис в фоне
Заголовок раздела «Сервис в фоне»Одноразовые команды удобны, но чаще контейнер — это сервис: база данных, веб-сервер. Он должен работать долго. Запустим веб-сервер Nginx:
docker run -d --name web -p 8080:80 nginx:1.29Docker напечатает длинный идентификатор контейнера и вернёт вам терминал. Контейнер работает в фоне. Проверьте:
curl -s localhost:8080 | head -5<!DOCTYPE html><html><head><title>Welcome to nginx!</title><style>Вы получили страницу от Nginx, который работает внутри контейнера. Можно открыть http://localhost:8080 в браузере.
Порт 8080 занят?
Тогда Docker ответит port is already allocated. Возьмите другой порт слева: -p 8081:80, и открывайте http://localhost:8081. Подробности — в уроке Порты и переменные.
docker ps
Заголовок раздела «docker ps»Список контейнеров:
docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESee879a5aca06 nginx:1.29 "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp web| Столбец | Что значит |
|---|---|
CONTAINER ID | Короткий идентификатор |
IMAGE | Из какого образа запущен |
STATUS | Up — работает. Exited (0) — закончил без ошибки. Exited (1) и больше — ошибка |
PORTS | Какие порты открыты |
NAMES | Имя контейнера |
docker ps показывает только работающие контейнеры. Все, включая остановленные:
docker ps -aОстановленные контейнеры остаются на диске, пока вы их не удалите. Это частая причина странных ошибок: имя web уже занято остановленным контейнером.
Удобные варианты:
docker ps -q # только идентификаторыdocker ps --filter 'name=^web$' # точное имя. Без ^ и $ найдёт и web-2, и airflow-webserverdocker ps --format 'table {{.Names}}\t{{.Status}}' # только нужные столбцыdocker logs
Заголовок раздела «docker logs»Всё, что программа пишет в stdout и stderr, Docker сохраняет как логи:
docker logs web...2026/11/11 17:50:15 [notice] 1#1: start worker process 35192.168.65.1 - - [11/Nov/2026:17:50:17 +0000] "GET / HTTP/1.1" 200 896 "-" "curl/8.7.1" "-"Последняя строка — ваш запрос curl. Часто используют два варианта:
docker logs -f web # следить за логом в реальном времени (выход: Ctrl+C)docker logs --tail 20 web # только последние 20 строкЛоги — первое, что смотрят, когда контейнер не работает.
docker exec
Заголовок раздела «docker exec»Выполнить команду внутри уже запущенного контейнера:
docker exec web nginx -vnginx version: nginx/1.29.8Чтобы зайти внутрь и работать как в терминале, нужны опции -it:
docker exec -it web shВы увидите приглашение #. Это терминал внутри контейнера. Выполните ls /usr/share/nginx/html, посмотрите файлы. Выход: exit.
docker run | docker exec | |
|---|---|---|
| Что делает | Создаёт новый контейнер | Работает в существующем |
| Образ нужен | Да | Нет |
docker exec — главный способ посмотреть, что внутри. Например, зайти в контейнер с базой и выполнить psql.
Остановить и удалить
Заголовок раздела «Остановить и удалить»docker stop web # остановитьdocker start web # запустить сноваdocker restart web # перезапуститьdocker rm web # удалить остановленный контейнерПроверьте статус после остановки:
docker stop webdocker ps -a --filter 'name=^web$' --format '{{.Names}} | {{.Status}}'web | Exited (0) Less than a second agoКонтейнер остановлен, но существует. Его можно запустить командой docker start web. Удалите его:
docker rm webДве частые ошибки:
Error response from daemon: cannot remove container "web": container is running: stop the container before removing or force removeСначала остановите (docker stop web) или удалите принудительно: docker rm -f web.
docker: Error response from daemon: Conflict. The container name "/web" is already in use by container "c206c14b6d09...". You have to remove (or rename) that container to be able to reuse that name.Имя занято старым контейнером. Удалите его: docker rm web.
Чем stop отличается от kill?
docker stop просит программу завершиться (сигнал SIGTERM) и ждёт 10 секунд. Если она не завершилась, Docker убивает её. Так программа успевает сохранить данные. docker kill убивает сразу. Используйте stop.
Интерактивный контейнер
Заголовок раздела «Интерактивный контейнер»Можно запустить контейнер и сразу работать в нём:
docker run -it --rm alpine:3.22 shОпции:
-iоставляет ввод открытым.-tвключает терминал.--rmудалит контейнер после выхода.
Вы внутри Alpine. Попробуйте cat /etc/os-release, ls /, whoami. Выход: exit. Контейнер остановится и удалится.
Так же запускают Python без установки на компьютер:
docker run -it --rm python:3.12-slim pythonПрактика
Заголовок раздела «Практика»Выполняйте задания по порядку. Задания 2–5 используют один контейнер web.
Задание 1
Заголовок раздела «Задание 1»Запустите одноразовый контейнер Alpine и покажите первые две строки файла /etc/os-release. Контейнер должен удалиться сам.
Проверка:
NAME="Alpine Linux"ID=alpineРешение
docker run --rm alpine:3.22 head -2 /etc/os-releaseПроверка удаления: docker ps -a не показывает этот контейнер.
Задание 2
Заголовок раздела «Задание 2»Запустите Nginx в фоне с именем web на порту 8080. Проверьте командой curl, что он отвечает. Выведите только строку с заголовком страницы.
Проверка: <title>Welcome to nginx!</title>
Решение
docker run -d --name web -p 8080:80 nginx:1.29curl -s localhost:8080 | grep titleЕсли порт занят, используйте -p 8081:80 и localhost:8081.
Задание 3
Заголовок раздела «Задание 3»Найдите в логах контейнера web строку с вашим запросом curl.
Проверка: строка содержит "GET / HTTP/1.1" 200.
Решение
docker logs web | grep GETNginx пишет запросы в stdout, а ошибки в stderr. Чтобы искать сразу по всем логам, добавьте 2>&1: docker logs web 2>&1 | grep error.
Задание 4
Заголовок раздела «Задание 4»Не заходя в контейнер, узнайте версию Nginx внутри web. Затем зайдите в контейнер и посмотрите список файлов в папке /usr/share/nginx/html.
Проверка: версия nginx/1.29.<число>. Файлы: 50x.html и index.html.
Решение
docker exec web nginx -vdocker exec -it web shls /usr/share/nginx/htmlexitИли одной командой, без входа внутрь: docker exec web ls /usr/share/nginx/html.
Задание 5
Заголовок раздела «Задание 5»Остановите web. Проверьте, что он остановлен, но не удалён. Запустите его снова. Остановите и удалите совсем.
Проверка: после stop статус Exited (0). После start статус Up. После rm команда docker ps -a --filter 'name=^web$' показывает только строку заголовка.
Решение
docker stop webdocker ps -a --filter 'name=^web$'docker start webdocker ps --filter 'name=^web$'docker stop webdocker rm webdocker ps -a --filter 'name=^web$'Короткий вариант для последних двух шагов: docker rm -f web. Флаг -f останавливает и удаляет.
Задание 6
Заголовок раздела «Задание 6»Запустите интерактивный Python в контейнере. Посчитайте 2 ** 10. Выйдите.
Проверка: 1024. После выхода контейнер удалён (docker ps -a его не показывает).
Решение
docker run -it --rm python:3.12-slim pythonВ Python:
2 ** 10exit()Дальше: Образы и реестры.