Аннотация
В этой статье мы разберём ключевые понятия Docker —
Dockerfile
,Docker image
,Docker container
иDocker Compose
. Вы узнаете, как они работают, как между собой связаны и зачем нужны в современной DevOps- и Self-Hosting-инфраструктуре.
🔧 Что такое Docker?
Docker — это платформа для разработки, доставки и запуска приложений в изолированных средах, называемых контейнерами. Вместо того чтобы устанавливать приложение и его зависимости на хост-систему, Docker позволяет упаковать всё необходимое в легковесный, переносимый контейнер, который будет работать одинаково на любом совместимом хосте.
Официальное определение
“Docker — это платформа с открытым исходным кодом, которая автоматизирует развертывание приложений в легковесных, переносимых контейнерах.”
— Docker Documentation
Контейнеризация — не виртуализация. В отличие от виртуальных машин (VM), контейнеры используют ядро хост-системы напрямую, что делает их быстрее, легче и эффективнее по потреблению ресурсов.
🧱 Docker Image — “шаблон” приложения
Что это?
Docker image — это неподвижный (immutable), зафиксированный шаблон, содержащий всё необходимое для запуска приложения: операционную систему, зависимости, приложение, переменные окружения, команды запуска и т.д.
Образы создаются на основе Dockerfile
и хранятся в реестрах (registries), например:
- Docker Hub — публичный реестр
- GitHub Container Registry (GHCR)
- Приватные реестры (например, Harbor, Nexus)
Особенности образов
- Иммутабельны: один раз создан — не меняется.
- Слоистая структура (layers): каждый шаг в
Dockerfile
создаёт новый слой. Docker кэширует слои, что ускоряет сборку. - Переносимы: образ можно запустить на любом сервере с Docker, независимо от ОС (если архитектура совместима).
Пример: запуск образа
docker run nginx:alpine
Здесь nginx:alpine
— это образ, доступный на Docker Hub. Docker скачает его (если ещё не скачан) и запустит контейнер.
Подсказка
Образы часто имеют теги (
:latest
,:1.21
,:alpine
). Используйте конкретные теги вместо:latest
в production!
📦 Docker Container — запущенный экземпляр образа
Что это?
Контейнер — это запущенный экземпляр Docker-образа. Если образ — это класс в ООП, то контейнер — это объект.
Контейнер:
- Изолирован от хоста и других контейнеров (сеть, файловая система, процессы).
- Имеет собственное пространство имён, cgroups и root-файловой системы.
- Может быть запущен, остановлен, перезапущен, удалён.
Как создаётся контейнер?
docker run ubuntu:22.04 echo "Hello from container!"
- Docker проверяет, есть ли образ
ubuntu:22.04
локально. - Если нет — скачивает его с Docker Hub.
- Запускает контейнер на основе этого образа.
- Выполняет команду
echo
. - Контейнер завершает работу.
Отличие от виртуальной машины
ВМ эмулирует целое железо и ОС. Контейнер использует ядро хоста, но изолирует процессы, сеть и файловую систему. Это делает контейнеры быстрее и экономичнее.
Основные команды Docker
sudo systemctl start docker #start docker demon manually
docker ps #показывает список запущенных контейнеров
docker ps -a #показывает список запущенных и остановленных контейнеров
docker container ls #аналогично
docker images #показывает список локальных образов
docker run hello-world #создание контейнера из образа hellp-world
--name simple_name #задаем имя контейнеру
--rm #автоматичесское удаление после остановки
docker rm "ID/name" #удалить контейнер
docker --help #help
docker system prune # удалить из системы контейнеры, которые уже не используются, ненужные сети и образы без имен и меток
docker run -it --rm busybox #подключится интерактивно через терминал sh к контейнеру, который был создан на основе образа busybox
# --rm автоматическое удаление контейнера после остановки
hostname #показать ID контейнера
hostname -i #показывает ip, присвоенный этому контейнеру
docker stop "ID/name" #остановка контейнера
docker kill "ID/name" #убить контейнер
docker attach "ID/name" #подключится в командную оболочку запущенного контейнера
docker container prune #удаляет все остановленные контейнеры
Пример с контейнером nginx
docker run -d nginx #запустить контейнер nginx и подключится к нему в фоновом режиме
docker container inspect "ID/name" #все детали контейнера
docker logs "ID/name" #посмотреть логи
docker exec -it "ID/name" bash #запускаем процесс bash внутри контейнера
/usr/share/nginx/html/index.html # index page for nginx
docker cp server.py $CONTAINER_ID:/app #скопировать файл server.py в дирректорию app $CONTAINER_ID
docker cp $CONTAINER_ID:/app/server.py . #скопировать файл из контейнера на локальную машину
Mapping ports
Для открытия сервиса по определенному порту внутри контейнера
docker run -d -p 8080:80 nginx
# -p позволяет открыть порт 8080(внешний) на компе и пробросить его на порт 80(внутренний) внутри контейнера!
После этого можно в браузере переходить по 127.0.0.1:8080 и мы увидим index page for nginx
Mapping томов (valumes)
Замена содержимого папки /usr/share/nginx/html в контейнере на содержимое из ${PWD} на локальной машине
docker run -d -v ${PWD}:/usr/share/nginx/html nginx
# -v подлючение тома ${PWD} в контейнер по этому пути /usr/share/nginx/html
# PWD - переменная, содержащая текуший расположение в терминале, так же можно использовать абсолютные и относительные пути
Перенос строк
docker run \
--name simple_name \
-v ${PWD}:/usr/share/nginx/html \
-p 8080:80 \
-d \
--rm \
nginx
🛠️ Dockerfile — “рецепт” для сборки образа
Что это?
Dockerfile
— это текстовый файл с инструкциями, по которым Docker строит образ.
Каждая строка — это слой в образе. Docker кэширует слои, поэтому при повторной сборке не пересобирает всё с нуля.
Пример Dockerfile
# Базовый образ
FROM alpine:3.18
# Автор/владелец
LABEL maintainer="admin@selfops.ru"
# Установка зависимостей
RUN apk add --no-cache nginx
# Копируем конфиг
COPY nginx.conf /etc/nginx/nginx.conf
# Создаём директорию для статики
RUN mkdir -p /var/www/html
# Копируем HTML-файл
COPY index.html /var/www/html/
# Открываем порт
EXPOSE 80
# Команда запуска
CMD ["nginx", "-g", "daemon off;"]
Основные инструкции
Инструкция | Назначение |
---|---|
FROM | Базовый образ (обязательно первая) |
RUN | Выполняет команду во время сборки |
COPY / ADD | Копирует файлы из хоста в образ |
CMD | Команда по умолчанию при запуске контейнера |
ENTRYPOINT | Фиксирует исполняемый файл (можно дополнять аргументами) |
ENV | Устанавливает переменные окружения |
EXPOSE | Документирует, что контейнер слушает порт (не открывает!) |
WORKDIR | Устанавливает рабочую директорию |
Важно
EXPOSE
не открывает порт на хосте. Для этого нужно использовать-p
приdocker run
.
Создание Dockerfile
Docker image создается на основе Dockerfile (файл с инструкциями по созданию образа). Обычно Dockerfile помещают в корень приложения. При создании образа желательно указать имя и тег для образа. Используем Dockerfile когда билдим свой Docer image.
FROM python:alpine # базовый образ, alpine(тэг) - минимальная версия образа
WORKDIR /app # создаем рабочую дирректорию app в корне приложения
COPY . . # копирование фалов из локальной текущей папки в WORKDIR, и WORKDIR станет текущей папкой для всех последующих команд
CMD ["python", "main.py"] # команда, которая будет выполнена. Запустится процесс python с аргументом main.py
Сборка образа
docker build . -t my-calendar:4.1.3 # созданин image с именем my-calendar и тэгом 4.1.3 на основе Dockerfile в текщей директории
docker run my-calendar:4.1.3 # запустить контейнер на основе образа my-calendar:4.1.3
docker build . -t my-calendar:4.1.3; docker run my-calendar:4.1.3 # так же можно объединить команды для удобства
-t
— задаёт имя и тег образа..
— путь к контексту сборки (где лежит Dockerfile).
🔄 Docker Compose — оркестрация нескольких контейнеров
Зачем он нужен?
Когда приложение состоит из нескольких сервисов (например, веб-сервер, база данных, кэш), удобно управлять ими единым файлом конфигурации. Вот тут и приходит на помощь Docker Compose
.
Что такое docker-compose.yml
?
Это YAML-файл, описывающий:
- Какие сервисы запускать
- Какие образы использовать
- Порты, тома, переменные окружения
- Сети и зависимости между сервисами
Пример: WordPress + MySQL
version: '3.8'
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
volumes:
- db_data:/var/lib/mysql
networks:
- wp-network
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
depends_on:
- db
networks:
- wp-network
volumes:
db_data:
networks:
wp-network:
driver: bridge
Запуск
docker-compose up -d
-d
— в фоновом режиме (detached).- Все сервисы запускаются, сети и тома создаются автоматически.
Еще пример
docker-compose необходим для запуска и настройки нескольких контейнеров в одном файле, позволяет автоматически создать образ на основе Dockerfile.
Важно
docker-compose автоматически создает изолированную сеть для взаимодействия контейнеров и поднимает DNS для взаимодействия между контейнерами используя имена сервисов а не ip
version: '3'
services:
app:
build: ./app
restart: always
mongo:
image: mongo
restart: always
services:
frontend:
build: .
command: python3 server.py
volumes:
- type: bind
source: .
target: /app
environment:
PYTHONDONTWRITEBYTECODE: 1
ports:
- "8080:80"
docker-compose up -d # для запуска docker-compose и подключение к нему в фоновом режиме
docker-compose down # остановка и удаление всех контейнеров docker-compose
docker-compose up -d --build # перебилдить образы при изменении приложения
restart: always #перезапускать контейнер, если процесс остановился
docker compose build; docker compose up #собрать образ и запустить контейнер находясь в одной дирректории с docker-compose docker-compose
Еще раз про Mapping volumes
Для сохранения данных после перезапуска контейнеров используется Mapping volumes в одной из двух вариаций:
- расшарить папку из Хоста ОС (чтение - запись). Данный вариант называется “bind mounts”
- Создать и расшарить папку внутри Docker (чтение - запись), в таком случае возможно расшарить папку для разных контейнеров. В этом случае обычно “Mountpoint”: “var/lib/docker/volumes/…”
#подключение по варианту 1
version: '3'
services:
...
mysql:
image:mysql
...
volumes:
- /var/lib/mysql/exception_dir #папка иключение, которую не хотим перезапиывать
- ./mysql_data:/var/lib/mysql #mysql_data - папка на хосте
...
#подключение по варианту 2
version: '3'
services:
...
mysql:
image:mysql
...
volumes:
- /var/lib/mysql/exception_dir #папка иключение, которую не хотим перезапиывать
- mysql_data:/var/lib/mysql
...
volumes:
mysql_data: #создаем том внутри Docker
docker volume ls #показать все тома внутри Docker
docker inspect name_of_tom #детали о томе
🔗 Как всё это связано?
graph TB A[Dockerfile] -->|docker build| B[Docker Image] B -->|docker run| C[Docker Container] D[docker-compose.yml] -->|docker-compose up| C C -->|изолированно| E[Хост-система]
Dockerfile
→ создаёт →Docker image
Docker image
→ запускается как →Docker container
docker-compose.yml
→ управляет несколькими →Docker containers
✅ Преимущества Docker в Self-Hosting
Плюс | Объяснение |
---|---|
Изолированность | Сервисы не мешают друг другу |
Переносимость | Работает на любом Linux-сервере |
Воспроизводимость | Один и тот же образ везде работает одинаково |
Простота обновления | Пересобрал образ — перезапустил контейнер |
Экономия ресурсов | Нет накладных расходов виртуализации |
Для SelfOps
Используйте Docker + Docker Compose для развертывания таких сервисов, как:
📚 Полезные ресурсы
- 📄 Официальная документация Docker
- 📘 Docker — Get Started
- 🐳 Docker Hub
- 🧩 Awesome Docker — подборка образов и инструментов
- 🛠️ Docker Compose Specification
- 📃Отличные статьи по Docker на русском
🏁 Заключение
Docker — это не просто модная технология, а фундамент современной автоматизации и self-hosting. Понимание разницы между Dockerfile
, образом
, контейнером
и Docker Compose
— первый шаг к уверенному управлению своей инфраструктурой.
Success
Совет от SelfOps:
Начинайте с простого. Развернитеnginx
в контейнере, потом добавьтеdocker-compose
, потом — базу данных. Постепенно вы построите свою домашнюю облачную платформу.
Quote
“Сначала ты учишься Docker. Потом он учит тебя архитектуре, автоматизации и терпению.”
— Анонимный админ, 2025