Docker-контейнер помогает запускать приложение вместе с его зависимостями в предсказуемой изолированной среде. На практике это означает меньше проблем с окружением, быстрый запуск сервисов и удобную доставку приложения от ноутбука разработчика до сервера.

Docker-контейнер упаковывает приложение в переносимую среду запуска
Docker-контейнер — это изолированная среда, в которой запускается приложение: веб-сервер, база данных, очередь задач, скрипт, API или любой другой процесс. Внутри контейнера находятся нужные библиотеки, настройки окружения, файловая система и команда запуска.
Официальная документация Docker описывает Docker Engine как технологию контейнеризации для сборки и запуска приложений. Docker Engine состоит из демона dockerd, API и командной строки docker, через которую пользователь управляет образами, контейнерами, сетями и хранилищами.
Самая простая аналогия: контейнер похож на аккуратно собранную рабочую коробку для приложения. В этой коробке уже лежит всё, что нужно программе для запуска. Разработчик может передать такую коробку другому человеку или запустить её на сервере, и поведение приложения будет намного предсказуемее.
Классический пример проблемы без Docker:
- у разработчика установлен Python 3.12;
- на сервере стоит Python 3.10;
- локально есть нужная версия библиотеки;
- на сервере библиотека отсутствует;
- в системе отличаются переменные окружения;
- приложение работает на ноутбуке и падает после деплоя.
Docker уменьшает такие расхождения. Окружение описывается в файлах проекта, а запуск выполняется одинаковыми командами.
Образ служит шаблоном, контейнер становится запущенным экземпляром
В Docker важно разделять два понятия: образ и контейнер.
| Понятие | Простое объяснение | Практический смысл |
| Образ | Шаблон для запуска контейнера | В нём описано, какие файлы, зависимости и команды нужны приложению |
| Контейнер | Запущенный экземпляр образа | Именно в контейнере работает процесс приложения |
| Dockerfile | Инструкция для сборки образа | В нём фиксируются шаги подготовки окружения |
| Registry | Хранилище образов | Оттуда образы скачиваются и туда могут публиковаться |
Образ можно сравнить с установочным шаблоном. Контейнер — это уже запущенное приложение на основе этого шаблона. Из одного образа можно создать много контейнеров. Например, из образа nginx можно запустить один контейнер для теста, второй для локальной разработки и третий для отдельного стенда.
Проверить базовую работу Docker можно командой:
docker run hello-worldЭта команда скачает тестовый образ, создаст контейнер и выведет сообщение о корректной работе Docker.
Запуск Nginx в контейнере показывает базовую механику Docker
Практический старт удобнее всего увидеть на примере Nginx. Команда ниже запускает веб-сервер в контейнере и публикует его наружу через порт 8080:
docker run --name demo-nginx -d -p 8080:80 nginx:latestРазберём команду по частям:
| Фрагмент | Значение |
docker run | создать и запустить контейнер |
--name demo-nginx | задать понятное имя контейнера |
-d | запустить в фоновом режиме |
-p 8080:80 | связать порт 8080 на компьютере с портом 80 внутри контейнера |
nginx:latest | использовать образ Nginx с тегом latest |
После запуска откройте в браузере:
http://localhost:8080Для просмотра запущенных контейнеров используется команда:
docker psДля просмотра логов:
docker logs demo-nginxДля остановки контейнера:
docker stop demo-nginxДля удаления остановленного контейнера:
docker rm demo-nginxЭти команды закрывают базовый цикл: запуск, проверка, чтение логов, остановка и удаление.
Контейнеры изолируют процессы, сеть и файловую систему
Контейнер создаёт для приложения отдельное окружение. У него есть собственная файловая система, собственные процессы и сетевые настройки. Изоляция помогает запускать разные версии сервисов на одной машине и снижает риск конфликтов между зависимостями.
Пример: на одном компьютере можно одновременно поднять несколько версий PostgreSQL, Redis, PHP или Node.js. Каждая версия будет работать в своём контейнере со своими настройками.
Изоляция полезна в нескольких сценариях:
- локальная разработка проекта;
- тестирование новой версии приложения;
- запуск временного сервиса;
- сборка окружения для CI/CD;
- развёртывание вспомогательных инструментов;
- обучение Linux, DevOps и backend-разработке.
Контейнеры используют ядро операционной системы хоста. Это делает их легче виртуальных машин. Виртуальная машина обычно запускает полноценную гостевую ОС, а контейнер запускает изолированный процесс с нужным окружением.
Порты связывают приложение внутри контейнера с внешним миром
Большинство серверных приложений слушают порт внутри контейнера. Для доступа с хоста нужно опубликовать этот порт.
Пример с Nginx:
docker run --name site -d -p 8080:80 nginxЗдесь порт 80 внутри контейнера связан с портом 8080 на компьютере. Пользователь открывает localhost:8080, а запрос попадает в Nginx внутри контейнера.
Если запустить два контейнера Nginx, им нужны разные порты на хосте:
docker run --name site-one -d -p 8081:80 nginx
docker run --name site-two -d -p 8082:80 nginxТеперь доступны два независимых контейнера:
http://localhost:8081
http://localhost:8082Это удобно для тестирования разных версий сайта, конфигураций Nginx или backend-приложений.
Тома сохраняют данные после пересоздания контейнера
Контейнеры часто пересоздаются: при обновлении образа, изменении конфигурации или перезапуске приложения. Данные, которые должны жить дольше контейнера, нужно хранить отдельно.
Docker предлагает volumes — управляемые Docker хранилища для данных. В официальной документации volumes называются предпочтительным механизмом для хранения данных, создаваемых и используемых контейнерами.
Пример запуска PostgreSQL с томом:
docker volume create pgdata
docker run --name demo-postgres \
-e POSTGRES_PASSWORD=secret_password \
-e POSTGRES_DB=demo \
-v pgdata:/var/lib/postgresql/data \
-d postgres:16В этой команде:
| Фрагмент | Значение |
docker volume create pgdata | создать том для данных |
-e POSTGRES_PASSWORD=secret_password | передать пароль через переменную окружения |
-e POSTGRES_DB=demo | создать базу данных demo |
-v pgdata:/var/lib/postgresql/data | подключить том к каталогу данных PostgreSQL |
postgres:16 | использовать образ PostgreSQL 16 |
Если контейнер удалить, том останется:
docker stop demo-postgres
docker rm demo-postgres
docker volume lsДанные можно подключить к новому контейнеру с тем же томом.
Bind mount ускоряет разработку с живыми файлами проекта
Bind mount подключает каталог с компьютера внутрь контейнера. Docker в документации описывает bind mount как способ смонтировать файл или каталог хоста в контейнер. Это особенно удобно для разработки, когда код меняется локально и сразу виден внутри контейнера.
Пример с Nginx и локальной HTML-страницей:
mkdir docker-demo
cd docker-demo
echo '<h1>Hello from Docker</h1>' > index.html
docker run --name html-demo \
-d \
-p 8080:80 \
-v "$PWD":/usr/share/nginx/html:ro \
nginxТеперь файл index.html из текущего каталога доступен внутри контейнера. Флаг :ro делает подключение только для чтения. Для статического сайта это безопаснее, потому что контейнер не сможет изменить исходный файл на хосте.
Откройте:
http://localhost:8080Измените index.html, обновите страницу в браузере и увидите новый результат.
Dockerfile фиксирует сборку собственного образа
Для собственного приложения обычно создают Dockerfile. Это текстовый файл с инструкциями сборки образа.
Пример минимального Node.js-приложения:
mkdir node-docker-demo
cd node-docker-demo
npm init -y
npm install expressСоздайте файл server.js:
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Hello from Docker container');
});
app.listen(port, () => {
console.log(`Server started on port ${port}`);
});Создайте Dockerfile:
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
ENV PORT=3000
EXPOSE 3000
CMD ["node", "server.js"]Соберите образ:
docker build -t node-docker-demo .Запустите контейнер:
docker run --name node-demo -d -p 3000:3000 node-docker-demoОткройте:
http://localhost:3000Такой подход позволяет описать окружение проекта один раз и запускать его одинаково на разных машинах.
Файл .dockerignore уменьшает образ и ускоряет сборку
При сборке Docker отправляет в контекст сборки файлы проекта. Лишние каталоги увеличивают размер контекста и замедляют сборку. Для исключений используется .dockerignore.
Пример .dockerignore для Node.js-проекта:
node_modules
npm-debug.log
.git
.gitignore
.env
coverage
distЭто помогает избежать попадания локальных зависимостей, служебных файлов и секретов в образ.
Особенно важно не копировать в образ .env, приватные ключи, резервные копии базы данных и токены доступа. Секреты лучше передавать через переменные окружения, secret-хранилища CI/CD или специализированные механизмы оркестрации.
Docker Compose описывает несколько сервисов одним YAML-файлом
Один контейнер удобен для простого примера. Реальные приложения часто состоят из нескольких сервисов: backend, база данных, Redis, очередь, reverse proxy. Для таких сценариев используется Docker Compose.
Официальная документация описывает Docker Compose как инструмент для определения и запуска многоконтейнерных приложений. Compose позволяет описать сервисы, сети и тома в одном YAML-файле, а затем запустить весь стек одной командой.
Пример compose.yaml для Node.js и PostgreSQL:
services:
app:
build: .
container_name: demo-app
ports:
- "3000:3000"
environment:
PORT: 3000
DATABASE_URL: postgres://demo:demo_password@db:5432/demo
depends_on:
- db
db:
image: postgres:16
container_name: demo-db
environment:
POSTGRES_USER: demo
POSTGRES_PASSWORD: demo_password
POSTGRES_DB: demo
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:Запуск:
docker compose up -dПросмотр контейнеров проекта:
docker compose psПросмотр логов:
docker compose logs -fОстановка:
docker compose downОстановка с удалением томов:
docker compose down -vКоманду с -v нужно использовать аккуратно: она удаляет данные томов, включая базу данных.
Практический сценарий для Laravel, Nginx и базы данных
Для backend-проектов Docker часто используют как локальное окружение. Например, Laravel-проект можно поднять с PHP-FPM, Nginx и PostgreSQL или MySQL.
Упрощённый пример compose.yaml для Laravel и PostgreSQL:
services:
app:
image: php:8.3-fpm
container_name: laravel-app
working_dir: /var/www/html
volumes:
- ./:/var/www/html
nginx:
image: nginx:latest
container_name: laravel-nginx
ports:
- "8080:80"
volumes:
- ./:/var/www/html:ro
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- app
db:
image: postgres:16
container_name: laravel-db
environment:
POSTGRES_DB: laravel
POSTGRES_USER: laravel
POSTGRES_PASSWORD: secret
volumes:
- laravel_pgdata:/var/lib/postgresql/data
volumes:
laravel_pgdata:Пример docker/nginx/default.conf:
server {
listen 80;
server_name localhost;
root /var/www/html/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}Такой пример подходит для понимания общей схемы. Для полноценной разработки Laravel обычно добавляют Composer, расширения PHP, Redis, очереди, планировщик задач и отдельный Dockerfile под PHP-образ проекта.
Частые команды Docker закрывают большую часть повседневных задач
| Задача | Команда |
| Показать запущенные контейнеры | docker ps |
| Показать все контейнеры | docker ps -a |
| Скачать образ | docker pull nginx |
| Запустить контейнер | docker run -d nginx |
| Остановить контейнер | docker stop container_name |
| Удалить контейнер | docker rm container_name |
| Показать образы | docker images |
| Удалить образ | docker rmi image_name |
| Открыть shell внутри контейнера | docker exec -it container_name sh |
| Посмотреть логи | docker logs -f container_name |
| Показать тома | docker volume ls |
| Показать сети | docker network ls |
| Запустить Compose-проект | docker compose up -d |
| Остановить Compose-проект | docker compose down |
Для контейнеров на базе Alpine Linux обычно используется sh:
docker exec -it demo-nginx shДля образов с Bash:
docker exec -it container_name bashБезопасность контейнеров зависит от образов, прав и секретов
Docker облегчает запуск приложений, но требует аккуратной настройки. Контейнер с опасными правами может создать проблемы для хоста и инфраструктуры.
Базовые рекомендации:
- используйте официальные или доверенные образы;
- фиксируйте версии образов, например
postgres:16,redis:7,node:22-alpine; - регулярно обновляйте базовые образы;
- не храните пароли, токены и приватные ключи в Dockerfile;
- не запускайте контейнеры с
--privilegedбез строгой необходимости; - ограничивайте открытые порты;
- используйте тома для данных;
- удаляйте старые контейнеры, образы и неиспользуемые тома после проверки;
- проверяйте, какие каталоги хоста подключаются через bind mount.
Команда очистки неиспользуемых объектов:
docker system pruneБолее агрессивная очистка с удалением неиспользуемых образов:
docker system prune -aПеред такой очисткой стоит проверить, какие контейнеры, образы и тома используются в проектах. Удалённый образ можно скачать заново, а удалённый том с базой данных может привести к потере данных.
Распространённые ошибки новичков мешают стабильному запуску
Одна из частых ошибок — хранение важных данных внутри контейнера без тома. Контейнер может быть удалён, и вместе с ним исчезнут файлы, которые не вынесены в volume или bind mount.
Вторая ошибка — публикация лишних портов наружу. Например, базу данных часто достаточно оставить доступной только внутри Docker-сети, а наружу публиковать только веб-приложение или reverse proxy.
Третья ошибка — использование тега latest для важных окружений. Такой тег может указывать на новую версию образа после обновления. Для воспроизводимости лучше фиксировать конкретную версию.
Четвёртая ошибка — сборка слишком большого образа. В образ часто случайно попадают node_modules, кеши, логи, .git, дампы и локальные файлы. Для контроля используется .dockerignore.
Пятая ошибка — запуск контейнеров от root без необходимости. Для production-образов лучше настраивать отдельного пользователя внутри контейнера, если приложение это поддерживает.
Docker особенно полезен в разработке, тестировании и доставке приложений
Docker хорошо подходит для задач, где важно быстро поднять одинаковое окружение:
- локальная разработка веб-приложений;
- запуск базы данных для тестов;
- изоляция разных версий языка или сервиса;
- сборка CI/CD pipeline;
- демонстрационные стенды;
- обучение DevOps-практикам;
- быстрый запуск инфраструктурных сервисов.
Для маленького статического сайта Docker может выглядеть избыточным. Для backend-проекта с базой данных, очередями, кешем и несколькими сервисами польза становится заметной быстрее: окружение фиксируется в файлах, новые участники команды запускают проект одной командой, а тестовые стенды собираются предсказуемо.
Первый практический маршрут начинается с Nginx, томов и Compose
Для уверенного старта достаточно пройти четыре шага.
Сначала запустите простой контейнер:
docker run --name demo-nginx -d -p 8080:80 nginxЗатем подключите локальный каталог через bind mount:
docker run --name html-demo \
-d \
-p 8081:80 \
-v "$PWD":/usr/share/nginx/html:ro \
nginxПосле этого соберите собственный образ через Dockerfile:
docker build -t my-app .
docker run --name my-app -d -p 3000:3000 my-appФинальный шаг — описать несколько сервисов в compose.yaml и запускать их одной командой:
docker compose up -dDocker-контейнеры помогают превратить окружение приложения в управляемую часть проекта. Начинать лучше с простых команд, затем добавлять volumes, Dockerfile, Compose и базовые правила безопасности. Такой путь быстро даёт практический результат и создаёт фундамент для более серьёзной инфраструктуры.
Где скачать Docker
Docker скачивают с официального сайта Docker: для Windows, macOS и настольного Linux удобнее брать Docker Desktop, который устанавливается как обычное приложение и уже включает Docker Engine, Docker CLI, Docker Compose и графический интерфейс для управления контейнерами.
Для серверов на Linux чаще устанавливают Docker Engine через официальный репозиторий дистрибутива: например, на Ubuntu это делается через apt, после чего Docker запускается как системная служба. Docker можно установить на Windows, macOS и Linux; для Ubuntu официально поддерживаются 64-битные версии Ubuntu 22.04 LTS, 24.04 LTS, 25.10 и 26.04 LTS, а также архитектуры x86_64/amd64, arm64, armhf, s390x и ppc64le.
На Windows важно учитывать системные требования Docker Desktop и поддержку WSL 2, на macOS — тип процессора Apple Silicon или Intel, на Linux — конкретный дистрибутив и способ установки. Начинать лучше с официальной страницы загрузки Docker, а для серверной установки использовать инструкцию именно для своей ОС, поскольку команды и пакеты отличаются между Ubuntu, Debian, Fedora, CentOS-подобными системами и другими дистрибутивами.