Форум программистов, компьютерный форум, киберфорум
Mr. Docker
Войти
Регистрация
Восстановить пароль

Docker: Руководство для начинающих по созданию первого приложения

Запись от Mr. Docker размещена 16.03.2025 в 09:51
Показов 1192 Комментарии 0
Метки devops, docker

Нажмите на изображение для увеличения
Название: 161fa8af-7c96-4808-b160-43001517a3c6.jpg
Просмотров: 49
Размер:	163.9 Кб
ID:	10416
Docker — это платформа, которая упаковывает ваше приложение и все его зависимости в стандартизированные блоки, называемые контейнерами. Эти контейнеры изолированы друг от друга и от основной системы, что обеспечивает согласованное выполнение приложения независимо от окружения.

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

К кому обращено это руководство? Прежде всего, к начинающим разработчикам, которые хотят понять, что такое Docker и как его использовать. Если вы уже слышали о Docker, но не знаете, с чего начать — эта статья для вас. Мы разберем, как создать и запустить свое первое приложение в контейнере Docker, избегая типичных ошибок новичков. Также это руководство будет полезно опытным разработчикам, которые хотят освежить свои знания или заполнить пробелы в понимании Docker. Мы рассмотрим не только базовые концепции, но и затронем некоторые продвинутые темы, такие как оптимизация образов и работа с Docker Compose.

Docker может показаться сложным на первый взгляд, но поверьте, освоить его базовые принципы может каждый. И как только вы начнете использовать Docker в своих проектах, вы удивитесь, как раньше обходились без него. Он не только облегчает развертывание приложений, но и упрощает процесс разработки и тестирования.

Основы Docker



Прежде чем мы перейдем к практике, давайте разберемся с основными понятиями Docker. В мире контейнеризации существует немало терминов, которые могут запутать новичка, но как только вы разберетесь с базовыми концепциями, все встанет на свои места.

Контейнеры vs виртуальные машины



Первое заблуждение, с которым сталкиваются многие: Docker — это что-то вроде виртуальной машины. На самом деле это не так. Хотя и контейнеры, и виртуальные машины предназначены для изоляции приложений, подход у них принципиально разный. Виртуальная машина (ВМ) эмулирует всю компьютерную систему, включая операционную систему. Это как компьютер внутри компьютера. Каждая ВМ требует собственной ОС и ресурсов, что делает их довольно тяжеловесными.

Контейнер же использует ядро хостовой ОС, но работает в своем изолированном пространстве. Представьте, что у вас есть многоквартирный дом (хостовая ОС), где каждая квартира (контейнер) изолирована от других, но все они используют одну и ту же инфраструктуру здания. Эта разница делает контейнеры более легкими и быстрыми по сравнению с ВМ. Они потребляют меньше ресурсов, запускаются за секунды (а не минуты) и позволяют запускать больше приложений на одном физическом сервере.

Ключевые понятия: образы, контейнеры, Dockerfile



В Docker существует три основных понятия, которые нужно понять:
  • Образы (Images) — это шаблоны, на основе которых создаются контейнеры. Образ содержит все необходимое для запуска приложения: код, библиотеки, переменные окружения и конфигурационные файлы. Образы доступны только для чтения, их нельзя изменить после создания. Если вам нужно внести изменения, вы создаете новый образ.
  • Контейнеры (Containers) — это запущенные экземпляры образов. Контейнер — это процесс с собственной файловой системой, сетевыми настройками и изолированным пространством. Вы можете создать, запустить, остановить, переместить или удалить контейнер.
  • Dockerfile — это текстовый файл с инструкциями по созданию образа Docker. В нем вы указываете базовый образ, копируете файлы, устанавливаете зависимости и настраиваете параметры запуска приложения.

Как установить Docker на разные ОС



Установка Docker отличается в зависимости от операционной системы, но процесс достаточно прост на всех платформах.

Windows:
1. Скачайте Docker Desktop с официального сайта.
2. Запустите установщик и следуйте инструкциям.
3. После установки вам может потребоваться настроить Windows Subsystem for Linux (WSL) версии 2.

macOS:
1. Загрузите Docker Desktop для Mac.
2. Перетащите приложение Docker в папку Applications.
3. Запустите Docker и дождитесь, пока иконка в строке меню не перестанет анимироваться.

Linux:
На различных дистрибутивах Linux установка может отличаться. Например, на Ubuntu:

Bash
1
2
3
4
sudo apt update
sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker
После установки проверьте, что Docker работает корректно, выполнив команду:

Bash
1
2
docker --version
docker run hello-world
Если вы видите версию Docker и приветственное сообщение от контейнера hello-world, значит, установка прошла успешно.

Архитектура Docker: клиент, демон, реестр



Docker использует архитектуру клиент-сервер. Компоненты Docker взаимодействуют между собой следующим образом:
  • Docker Daemon (dockerd) — это фоновый процесс, который управляет объектами Docker: образами, контейнерами, сетями и томами. Демон ожидает запросы от клиента Docker через API.
  • Docker Client (docker) — основной интерфейс, через который пользователи взаимодействуют с Docker. Когда вы выполняете команду docker run, клиент отправляет команду демону, который затем выполняет операцию.
  • Docker Registry — хранилище Docker-образов. Docker Hub — это публичный реестр, который любой может использовать. Docker по умолчанию ищет образы на Docker Hub. Вы также можете создать свой приватный реестр.

Когда вы выполняете команду, например, docker pull ubuntu, клиент отправляет запрос демону, который затем загружает образ Ubuntu из Docker Hub.

Сетевое взаимодействие в Docker



Docker обеспечивает несколько сетевых драйверов для контейнеров. По умолчанию контейнеры могут подключаться к сетям, созданным с использованием драйвера bridge.

Bridge Network — это сеть по умолчанию для контейнеров. Контейнеры в одной bridge-сети могут взаимодействовать друг с другом через внутренние IP-адреса, но изолированы от контейнеров в других сетях.

Host Network — контейнер использует сетевой стек хоста. Это означает, что контейнер не имеет собственного IP-адреса и использует сетевой интерфейс хоста.

Overlay Network — позволяет соединять несколько демонов Docker и обеспечивает общение между контейнерами на разных хостах. Это особенно полезно в сценариях с несколькими хостами, например, при использовании Docker Swarm.

Macvlan Network — позволяет назначить MAC-адрес контейнеру, делая его видимым как физическое устройство в сети.

None Network — отключает все сетевые возможности контейнера. Используется для полной изоляции.

Чтобы увидеть доступные сети, выполните:

Bash
1
docker network ls
Понимание основ сетевого взаимодействия в Docker крайне важно при разработке приложений, особенно многокомпонентных, где различные сервисы должны общаться между собой. Это базовые понятия Docker, которые помогут вам начать работу с контейнеризацией. В следующих разделах мы углубимся в создание и настройку контейнеров, а также рассмотрим практические примеры использования Docker в реальных проектах.

Теперь, когда мы познакомились с основными концепциями Docker, давайте подробнее рассмотрим, как эта технология может быть полезна разработчикам и администраторам.

Docker контейнер для Laravel 5 приложения потребовал ext-tidy
Всем привет. Создаю docker контейнер для Laravel 5.5.18 приложения с настройкамиweb/Dockerfile.yml : FROM php:7.1-apache RUN apt-get...

Docker, (Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?)
До появления ошибки работал с Docker, запускал контейнеры, останавливал и удалял их. Но внезапно в один момент, у меня перестал он работать. Выполняю...

Запуск и откладка приложения в Docker из IDEA
Подобно тому, как Android Studio дает запускать и отлаживать приложение сразу на телефоне, хочется запускать и отлаживать приложение spring boot в...

Деплой приложения Node.js с использованием strapi в Docker
Всем здравствуйте! Я пытаюсь развернуть приложение на Node.js, которое использует Strapi, в контейнере Docker. После успешного прохождения всех...


Преимущества Docker для разработчиков



Docker решает реальные проблемы в процессе разработки и развертывания приложений. Вот ключевые преимущества, которые оценят разработчики:
  • Согласованность среды разработки. Как часто вы слышали фразу "у меня на компьютере это работает"? Docker практически исключает такие ситуации, поскольку все разработчики используют идентичные контейнеры.
  • Изоляция. Каждое приложение работает в собственной среде, не мешая другим приложениям. Это особенно полезно при работе с несколькими проектами, требующими разных версий языков программирования или библиотек.
  • Переносимость. Если приложение работает в контейнере на вашей машине, оно будет работать в точно таком же контейнере на любом другом компьютере с Docker. Это упрощает переход от разработки к тестированию и производству.
  • Эффективность ресурсов. Контейнеры используют меньше ресурсов по сравнению с виртуальными машинами, что позволяет запускать больше приложений на одном сервере и быстрее выполнять операции разработки.
  • Быстрое масштабирование. Добавление новых экземпляров приложения для обработки возросшей нагрузки становится простым делом благодаря контейнерам.
  • Быстрое развертывание. Обновление приложения происходит безболезненно: просто замените старый контейнер новым, содержащим обновленную версию.
  • Универсальность. Docker работает с приложениями на любом языке программирования и с любым стеком технологий, что дает разработчикам свободу выбора инструментов.

Исследование, проведенное JetBrains в 2020 году, показало, что более 70% DevOps-специалистов используют Docker в своих проектах, что демонстрирует его широкое принятие в индустрии.

Основные команды Docker



Для работы с Docker важно знать основные команды командной строки. Вот некоторые из наиболее часто используемых команд:

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Загрузка образа из Docker Hub
docker pull имя_образа[:тег]
 
# Просмотр имеющихся образов
docker images
 
# Создание и запуск контейнера
docker run [опции] имя_образа [команда]
 
# Просмотр запущенных контейнеров
docker ps
 
# Просмотр всех контейнеров (включая остановленные)
docker ps -a
 
# Остановка контейнера
docker stop id_контейнера
 
# Запуск остановленного контейнера
docker start id_контейнера
 
# Удаление контейнера
docker rm id_контейнера
 
# Удаление образа
docker rmi имя_образа
 
# Просмотр логов контейнера
docker logs id_контейнера
 
# Выполнение команды внутри запущенного контейнера
docker exec -it id_контейнера команда
Эти команды являются фундаментом при работе с Docker. По мере углубления в тему вы познакомитесь с более продвинутыми опциями и возможностями.

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



Понимание жизненного цикла контейнера помогает эффективнее управлять приложениями в Docker:
1. Создание контейнера – происходит с помощью команды docker create или как часть docker run.
2. Запуск контейнера – контейнер начинает выполнение с помощью docker start или docker run.
3. Приостановка/возобновление – можно приостановить работу контейнера с помощью docker pause и возобновить с помощью docker unpause.
4. Остановка контейнера – контейнер прекращает работу с помощью docker stop (плавное завершение) или docker kill (немедленное).
5. Перезапуск контейнера – `docker restart` останавливает и сразу запускает контейнер.
6. Удаление контейнера – после остановки контейнер можно удалить с помощью docker rm.

Важно понимать, что при удалении контейнера все изменения, внесенные в его файловую систему, теряются, если они не сохранены в томе (volume) или в новом образе.

Работа с Docker Hub



Docker Hub – это облачный реестр, где хранятся образы Docker. Он работает как GitHub для кода, но для Docker-образов. Вот как с ним работать:

1. Создайте аккаунт на Docker Hub (hub.docker.com).
2. Войдите в систему через командную строку:
Bash
1
   docker login
3. Создайте тег для локального образа:
Bash
1
   docker tag локальный_образ:тег ваше_имя_пользователя/название_репозитория:тег
4. Загрузите образ в Docker Hub:
Bash
1
   docker push ваше_имя_пользователя/название_репозитория:тег
5. Скачайте образ с Docker Hub:
Bash
1
   docker pull ваше_имя_пользователя/название_репозитория:тег
Docker Hub содержит тысячи готовых образов для популярных сервисов и приложений – от простых образов операционных систем до полностью настроенных стеков приложений.

Docker и микросервисная архитектура



Docker особенно хорошо подходит для микросервисной архитектуры, где приложение разбивается на небольшие независимые сервисы. Каждый сервис может быть размещен в отдельном контейнере и масштабироваться независимо. Такой подход имеет ряд преимуществ:
  • Улучшенная изоляция: сбой в одном сервисе не влияет на другие.
  • Независимое развертывание: обновление одного сервиса не требует перезапуска всего приложения.
  • Гибкость в выборе технологий: разные сервисы могут использовать разные языки и фреймворки.
  • Лучшая масштабируемость: нагруженные сервисы можно масштабировать независимо.
Для координации работы нескольких контейнеров в микросервисной архитектуре часто используют оркестраторы, такие как Kubernetes или Docker Swarm, но это уже тема для отдельного обсуждения.

Типичные сценарии использования Docker



Docker можно эффективно применять в разных сценариях:

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

Непрерывная интеграция и доставка (CI/CD)
Docker идеален для автоматизации тестирования и развертывания в пайплайнах CI/CD. Каждый сборщик может использовать один и тот же контейнер для тестирования, что гарантирует согласованность между средами.

Разработка кросс-платформенных приложений
Контейнеры помогают разрабатывать приложения, которые будут работать на разных платформах. Разработчики могут создавать и тестировать приложения в среде, идентичной целевой среде развертывания.

Изоляция устаревших приложений
Docker позволяет упаковать устаревшие приложения вместе с их зависимостями и запускать их на современных системах без конфликтов с другими приложениями.

Освоив основы Docker, вы заложите хороший фундамент для дальнейшего изучения контейнеризации и связанных технологий. В следующем разделе мы перейдем к практике и создадим наш первый Dockerfile — основу для построения образа Docker.

Создание первого Dockerfile



Dockerfile – это текстовый файл с инструкциями, которые Docker использует для сборки образа. Он состоит из набора команд, каждая из которых создает новый слой в образе. Давайте разберем его структуру и основные команды.

Структура файла



Dockerfile обычно начинается с указания базового образа, а затем следует последовательность команд, которые настраивают образ для вашего приложения. Финальный образ представляет собой многослойную систему, где каждый слой – результат выполнения одной команды. Название файла чувствительно к регистру и обычно пишется как Dockerfile без расширения. Он должен находиться в корне вашего проекта, хотя вы можете указать другое расположение при сборке образа.

Базовые команды Dockerfile



Вот наиболее часто используемые команды:

FROM – задает базовый образ, на основе которого будет строиться ваш образ. Это единственная обязательная команда в любом Dockerfile.

Bash
1
FROM node:14
WORKDIR – устанавливает рабочий каталог для следующих команд в Dockerfile. Если указанный каталог не существует, Docker создаст его.

Bash
1
WORKDIR /usr/src/app
COPY – копирует файлы или директории с хоста в файловую систему контейнера. Первый параметр – путь источника на хосте, второй – путь назначения в контейнере.

Bash
1
2
COPY package.json .
COPY . .
ADD – похожа на COPY, но обладает дополнительными возможностями. Может распаковывать локальные tar-архивы и загружать файлы по URL.

Bash
1
ADD https://example.com/sample.tar.gz /opt/
RUN – выполняет команду в новом слое поверх текущего образа. Часто используется для установки пакетов.

Bash
1
2
RUN npm install
RUN apt-get update && apt-get install -y python3
ENV – устанавливает переменные окружения, которые будут доступны в контейнере.

Bash
1
2
ENV NODE_ENV=production
ENV PORT=3000
EXPOSE – указывает, что контейнер слушает указанный порт при запуске. Это не открывает порт автоматически – для этого нужно использовать флаг -p при запуске контейнера.

Bash
1
EXPOSE 3000
CMD – определяет команду по умолчанию для выполнения при запуске контейнера. В Dockerfile может быть только одна команда CMD.

Bash
1
CMD ["node", "app.js"]
ENTRYPOINT – похож на CMD, но определяет исполняемый файл, который будет запускаться при старте контейнера. Часто используется в сочетании с CMD.

Bash
1
2
ENTRYPOINT ["npm"]
CMD ["start"]

Пример простого Dockerfile для веб-приложения



Давайте рассмотрим пример создания Dockerfile для простого Node.js приложения:

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Используем официальный образ Node.js как базовый
FROM node:14
 
# Устанавливаем рабочую директорию в контейнере
WORKDIR /usr/src/app
 
# Копируем файлы package.json и package-lock.json
COPY package*.json ./
 
# Устанавливаем зависимости
RUN npm install
 
# Копируем исходный код приложения
COPY . .
 
# Открываем порт, который будет использовать приложение
EXPOSE 3000
 
# Запускаем приложение при старте контейнера
CMD ["node", "app.js"]
А вот как может выглядеть простое приложение Node.js, с которым мы будем работать:

JavaScript
1
2
3
4
5
6
7
8
9
10
11
// app.js
const http = require('http');
 
const server = http.createServer((req, res) => {
  res.end('Привет, Docker!');
});
 
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
  console.log(`Сервер запущен на порту ${PORT}`);
});

Порядок команд и оптимизация слоев



Порядок команд в Dockerfile имеет значение для эффективности сборки. Docker кэширует слои, и если файл не изменился с предыдущей сборки, Docker повторно использует существующий слой вместо пересоздания. Хорошей практикой является размещение редко изменяемых команд в начале Dockerfile (например, установка зависимостей), а часто меняющихся файлов (например, код приложения) ближе к концу. Это позволяет максимально использовать кэширование. Например, в нашем примере мы сначала копируем файлы package.json, затем устанавливаем зависимости и только после этого копируем остальной код. Если ваш код меняется часто, но зависимости остаются прежними, Docker сможет использовать кэшированные слои для установки зависимостей, что ускорит сборку.

Комментарии в Dockerfile



Комментарии в Dockerfile начинаются с символа #. Они помогают объяснить, что делает каждая команда, и могут быть полезны для других разработчиков или для вас в будущем.

Bash
1
2
3
4
5
# Этот слой устанавливает все необходимые зависимости
RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*
Теперь вы знаете, как создать базовый Dockerfile для вашего приложения. В следующем разделе мы рассмотрим лучшие практики составления Dockerfile и познакомимся с концепцией многоэтапной сборки для оптимизации размера образов.

Лучшие практики составления Dockerfile и многоэтапная сборка



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

Минимизируйте количество слоёв



Каждая инструкция в Dockerfile создаёт новый слой в образе. Чем больше слоёв, тем больше метаданных и тем сложнее управлять образом. Старайтесь объединять связанные команды в одну инструкцию RUN:

Bash
1
2
3
4
5
6
7
8
9
10
11
# Плохо
RUN apt-get update
RUN apt-get install -y python3
RUN apt-get install -y nodejs
RUN apt-get clean
 
# Хорошо
RUN apt-get update && \
    apt-get install -y python3 nodejs && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
Обратите внимание, что в примере выше мы также удаляем кеш установщика пакетов, чтобы уменьшить размер образа.

Используйте .dockerignore файл



Подобно .gitignore, файл .dockerignore позволяет указать, какие файлы и директории не должны попадать в контекст сборки. Это особено важно, когда в вашем проекте есть большие папки (например, node_modules), которые не нужны в образе:

Bash
1
2
3
4
5
node_modules
npm-debug.log
.git
.gitignore
.env
Использование .dockerignore ускоряет процесс сборки и помогает избежать случайного включения конфиденциальных файлов в образ.

Не запускайте приложения от имени root



По умолчанию процессы в контейнере запускаются с привилегиями root, что создаёт потенциальные риски безопасности. Лучше создать пользователя с ограниченными правами:

Bash
1
2
RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser
После директивы USER все последующие команды будут выполняться от имени указанного пользователя.

Используйте конкретные теги образов



Избегайте использования тегов latest для базовых образов. Это может привести к непредсказуемым результатам, когда образ обновляется. Всегда указывайте конкретную версию:

Bash
1
2
3
4
5
# Не рекомендуется
FROM node:latest
 
# Рекомендуется
FROM node:14.17.0-alpine3.13

Оптимизируйте кеширование при сборке



Docker кеширует слои образа для ускорения повторных сборок. Чтобы максимально использовать этот механизм, размещайте редко изменяемые инструкции в начале Dockerfile, а часто изменяемые — в конце:

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM node:14-alpine
 
WORKDIR /app
 
# Сначала копируем только файлы зависимостей
COPY package*.json ./
 
# Установка зависимостей (этот слой будет кеширован)
RUN npm install
 
# Теперь копируем изменяемый код приложения
COPY . .
 
CMD ["npm", "start"]

Используйте многоэтапную сборку



Многоэтапная сборка (multi-stage builds) позволяет значительно уменьшить размер итогового образа. Суть подхода заключается в использовании нескольких образов "FROM" в одном Dockerfile, где финальный образ содержит только необходимые для работы приложения файлы. Рассмотрим пример многоэтапной сборки для Node.js приложения:

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Этап сборки
FROM node:14 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
 
# Финальный этап
FROM node:14-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm install --only=production
EXPOSE 3000
CMD ["node", "dist/main.js"]
В этом примере:
1. Используем первый образ (builder) для установки всех зависимостей и сборки приложения.
2. Используем второй, более легкий образ на основе Alpine Linux.
3. Копируем только необходимые файлы из этапа сборки с помощью COPY --from=builder.
4. Устанавливаем только production-зависимости.

Такой подход особенно эффективен для приложений с шагом компиляции (TypeScript, Java, Go) или требующих множество инструментов для сборки, которые не нужны для запуска.

Многоэтапная сборка для разных языков



Java (Spring Boot)



Bash
1
2
3
4
5
6
7
8
9
10
FROM maven:3.8-openjdk-11 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests
 
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

Go



Bash
1
2
3
4
5
6
7
8
9
FROM golang:1.16 AS builder
WORKDIR /go/src/app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build -o /go/bin/app
 
FROM alpine:3.14
COPY --from=builder /go/bin/app /usr/local/bin/app
CMD ["/usr/local/bin/app"]

Python (с использованием пакета)



Bash
1
2
3
4
5
6
7
8
9
10
11
12
FROM python:3.9 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt
COPY . .
RUN python setup.py bdist_wheel
 
FROM python:3.9-slim
WORKDIR /app
COPY --from=builder /app/dist/*.whl .
RUN pip install *.whl
CMD ["python", "-m", "myapp"]

Используйте опциональные аргументы сборки



Аргументы сборки позволяют создавать более гибкие Dockerfile. С помощью директивы ARG вы можете определить переменные, значения которых могут быть переданы во время сборки:

Bash
1
2
3
4
5
6
7
8
9
10
11
FROM python:3.9
 
ARG ENV=production
ARG LOG_LEVEL=info
 
ENV APP_ENV=${ENV}
ENV LOG_LEVEL=${LOG_LEVEL}
 
RUN echo "Building for ${ENV} environment with log level ${LOG_LEVEL}"
 
# Остальные инструкции...
При сборке образа значения можно передать через флаг --build-arg:

Bash
1
docker build --build-arg ENV=development --build-arg LOG_LEVEL=debug -t myapp .

Указывайте HEALTHCHECK для контроля состояния приложения



Директива HEALTHCHECK позволяет Docker проверять, работает ли ваше приложение корректно внутри контейнера:

Bash
1
2
3
4
5
6
7
8
9
10
FROM node:14
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["node", "server.js"]
 
# Каждые 30 секунд проверять, что сервер отвечает на запросы
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:3000/ || exit 1
Это особенно полезно при использовании оркестраторов вроде Docker Swarm или Kubernetes, которые могут автоматически перезапускать неисправные контейнеры.

Используйте COPY вместо ADD



Обычно предпочтительнее использовать COPY вместо ADD, так как директива COPY более предсказуема — она просто копирует файлы из контекста сборки в образ. ADD имеет дополнительную функциональность (распаковка архивов, скачивание по URL), которая может привести к неожиданным результатам. Используйте ADD только когда вам нужна эта дополнительная функциональность:

Bash
1
2
3
4
5
# Для простого копирования файлов
COPY ./app /app
 
# Только для специфических случаев, например распаковки
ADD ./archive.tar.gz /opt/

Сократите время сборки с помощью BuildKit



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

Bash
1
export DOCKER_BUILDKIT=1
Или при запуске сборки:

Bash
1
DOCKER_BUILDKIT=1 docker build -t myapp .
BuildKit не только ускоряет сборку, но и добавляет новые возможности, например монтирование секретов:

Bash
1
2
3
4
5
6
# syntax=docker/dockerfile:1.2
FROM node:14
WORKDIR /app
COPY . .
RUN --mount=type=secret,id=npm_token \
    NPM_TOKEN=$(cat /run/secrets/npm_token) npm install
И запуск с передачей секрета:

Bash
1
docker build --secret id=npm_token,src=$HOME/.npm_token -t myapp .
Применение этих практик и многоэтапной сборки позволит вам создавать более эффективные, компактные и безопасные Docker-образы. В следующем разделе мы рассмотрим, как собрать и запустить контейнер из нашего Dockerfile.

Сборка и запуск контейнера



После того, как мы создали Dockerfile, настало время собрать Docker-образ и запустить контейнер. Этот процесс превращает набор инструкций в готовый к использованию контейнер с работающим приложением.

Команда docker build



Для создания образа используется команда docker build. Основной синтаксис выглядит так:

Bash
1
docker build -t имя_образа:тег путь_к_контексту_сборки
Разберём ключевые параметры:
-t (--tag) позволяет задать имя и тег образа
Последний аргумент – путь к контексту сборки (обычно текущая директория, обозначаемая точкой .)

Например, чтобы собрать образ для нашего Node.js приложения:

Bash
1
docker build -t my-nodejs-app:1.0 .
Во время выполнения этой команды Docker пошагово выполняет каждую инструкцию из Dockerfile, создавая слой за слоем. В терминале вы увидите процесс выполнения каждой инструкции:

Bash
1
2
3
4
5
6
7
8
9
Sending build context to Docker daemon  8.192kB
Step 1/7 : FROM node:14
 ---> a8967e76fb15
Step 2/7 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 2c8b680f15b0
Step 3/7 : COPY package*.json ./
 ---> a72820395fdb
...

Дополнительные опции сборки



Docker build имеет множество полезных опций:
  • --no-cache — принудительно пересобирает все слои, игнорируя кеш.
  • --build-arg KEY=VALUE — передаёт значения для ARG в Dockerfile.
  • --file, -f — указывает путь к Dockerfile, если он не в корне контекста или имеет другое имя.

Bash
1
2
3
4
5
6
7
8
# Пересборка без использования кеша
docker build --no-cache -t my-app .
 
# Использование Dockerfile из другой директории
docker build -f ./docker/prod.Dockerfile -t my-app:prod .
 
# Передача аргументов сборки
docker build --build-arg NODE_ENV=production -t my-app .

Команда docker run



После того как образ собран, можно запустить контейнер с помощью команды docker run:

Bash
1
docker run [опции] имя_образа [команда]
Например, чтобы запустить наше Node.js приложение:

Bash
1
docker run -p 3000:3000 my-nodejs-app:1.0
Здесь -p 3000:3000 связывает порт 3000 контейнера с портом 3000 хост-машины, что позволяет обращаться к приложению по адресу http://localhost:3000.

Основные опции команды run



Команда docker run имеет более 50 опций, но вот наиболее часто используемые:
-d, --detach — запуск в фоновом режиме (daemon)
-p, --publish host_port:container_port — проброс портов
-v, --volume host_path:container_path — монтирование томов
--name — задаёт имя контейнера вместо автоматически сгенерированного
-e, --env KEY=VALUE — устанавливает переменные окружения
--rm — автоматически удаляет контейнер после завершения работы
--network — подключает контейнер к заданной сети
-it — запуск в интерактивном режиме с привязкой к терминалу

Примеры использования:

Bash
1
2
3
4
5
6
7
8
9
10
11
# Запуск в фоновом режиме с заданным именем
docker run -d --name my-nodejs-server my-nodejs-app:1.0
 
# Запуск с переменными окружения
docker run -e NODE_ENV=production -e LOG_LEVEL=debug my-nodejs-app:1.0
 
# Запуск с монтированием локальной директории
docker run -v $(pwd)/data:/usr/src/app/data my-nodejs-app:1.0
 
# Комбинирование опций
docker run -d --name api-server -p 8080:3000 -e NODE_ENV=staging --rm my-nodejs-app:1.0

Проверка работы приложения



После запуска контейнера необходимо убедиться, что приложение работает корректно. Есть несколько способов:

1. Проверка логов:
Bash
1
   docker logs имя_контейнера
Чтобы следить за логами в реальном времени, добавьте флаг -f (follow):
Bash
1
   docker logs -f имя_контейнера
2. Проверка статуса контейнера:
Bash
1
   docker ps
Показывает список запущенных контейнеров с информацией о состоянии, портах и т.д.

3. Проверка через браузер или curl:
Если ваше приложение имеет веб-интерфейс, вы можете открыть его в браузере или выполнить запрос через curl:
Bash
1
   curl http://localhost:3000
4. Выполнение команды внутри запущенного контейнера:
Bash
1
   docker exec -it имя_контейнера /bin/bash
Это позволяет войти внутрь контейнера и выполнять команды, например, для проверки файлов или процессов.

Частые ошибки новичков



При работе с Docker начинающие разработчики часто сталкиваются с определенными проблемами:

1. Файлы не сохраняются после перезапуска контейнера

Проблема: Все изменения внутри контейнера теряются при его остановке.
Решение: Используйте тома (volumes) для хранения данных:
Bash
1
   docker run -v /host/data:/container/data my-app
2. Приложение не доступно через localhost

Проблема: Пользователи забывают сделать проброс портов.
Решение: Используйте флаг -p:
Bash
1
   docker run -p 8080:3000 my-app
3. Контейнер мгновенно завершает работу

Проблема: Основной процесс в контейнере завершается, что приводит к остановке контейнера.
Решение: Удостоверьтесь, что ваша команда CMD в Dockerfile запускает долгоживущий процесс, а не скрипт, который быстро завершается.

4. Нехватка места на диске

Проблема: Docker накапливает неиспользуемые образы и контейнеры, которые занимают место на диске.
Решение: Периодически очищайте неиспользуемые ресурсы:
Bash
1
2
3
4
5
6
7
8
   # Удаление всех остановленных контейнеров
   docker container prune
   
   # Удаление неиспользуемых образов
   docker image prune
   
   # Удаление всех неиспользуемых ресурсов
   docker system prune
5. Контейнер не имеет доступа к интернету

Проблема: Неправильная настройка сети.
Решение: Проверьте настройки сети и DNS в контейнере:
Bash
1
2
   docker exec -it my-container ping 8.8.8.8
   docker exec -it my-container cat /etc/resolv.conf

Жизненный цикл управления контейнерами



После запуска контейнера вы можете выполнять различные операции управления:

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Остановка контейнера (плавное завершение)
docker stop имя_контейнера
 
# Принудительная остановка (аналог SIGKILL)
docker kill имя_контейнера
 
# Перезапуск контейнера
docker restart имя_контейнера
 
# Приостановка работы контейнера
docker pause имя_контейнера
 
# Возобновление работы приостановленного контейнера
docker unpause имя_контейнера
 
# Удаление контейнера (должен быть остановлен)
docker rm имя_контейнера
 
# Удаление образа
docker rmi имя_образа:тег

Просмотр использования ресурсов



Для мониторинга ресурсов, используемых контейнерами, Docker предоставляет команду stats:

Bash
1
2
3
4
5
# Показывает статистику использования ресурсов для всех запущенных контейнеров
docker stats
 
# Для конкретного контейнера
docker stats имя_контейнера
Вы увидите информацию о CPU, памяти, сетевом трафике и операциях ввода-вывода для каждого контейнера:

Bash
1
2
CONTAINER ID   NAME            CPU %     MEM USAGE / LIMIT   MEM %     NET I/O          BLOCK I/O        PIDS
a1b2c3d4e5f6   my-nodejs-app   0.25%     42.4MiB / 3.843GiB  1.08%     648B / 648B      0B / 0B          19

Автоматический перезапуск контейнеров



Для повышения отказоустойчивости можно настроить автоматический перезапуск контейнера в случае сбоя:

Bash
1
docker run --restart=always my-nodejs-app
Опция --restart принимает следующие значения:
  • no — не перезапускать автоматически (по умолчанию).
  • on-failure[:max-retries] — перезапуск при выходе с ненулевым кодом (с опциональным лимитом попыток).
  • always — всегда перезапускать.
  • unless-stopped — всегда перезапускать, если контейнер не был остановлен вручную.

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

Управление портами и сохранение данных с помощью volumes



При работе с Docker важно понять два ключевых аспекта: как организовать сетевое взаимодействие с контейнером и как обеспечить сохранность данных. Рассмотрим эти темы подробнее.

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



По умолчанию контейнеры Docker изолированы от хост-системы, включая сетевой стек. Это означает, что если ваше приложение внутри контейнера слушает порт 3000, этот порт не будет доступен извне без специальной настройки. Именно здесь на помощь приходит проброс портов.

Проброс портов осуществляется с помощью параметра -p (или --publish) команды docker run:

Bash
1
docker run -p <порт_хоста>:<порт_контейнера> имя_образа
Например, если ваше приложение внутри контейнера работает на порту 3000, вы можете сделать его доступным на порту 8080 хоста:

Bash
1
docker run -p 8080:3000 my-nodejs-app
Теперь вы сможете обратиться к приложению по адресу http://localhost:8080.

Различные варианты пробросов портов



Docker предоставляет гибкие возможности настройки сетевого доступа:

1. Проброс на конкретный IP-адрес:
Bash
1
   docker run -p 127.0.0.1:8080:3000 my-app
Приложение будет доступно только по адресу 127.0.0.1 (localhost).

2. Проброс на случайный порт хоста:
Bash
1
   docker run -p 127.0.0.1::3000 my-app
Docker автоматически выберет свободный порт на хосте. Чтобы узнать выбранный порт, используйте docker ps.

3. Проброс диапазона портов:
Bash
1
   docker run -p 8080-8090:8080-8090 my-app
Удобно, когда приложение использует несколько последовательных портов.

4. **Проброс всех портов, указанных в EXPOSE**:
Bash
1
   docker run -P my-app
Docker автоматически пробросит все порты, объявленные в Dockerfile через директиву EXPOSE.

Просмотр пробрасываемых портов



Увидеть настроенные пробросы портов для запущенных контейнеров можно с помощью команды:

Bash
1
docker ps
Колонка PORTS покажет настроенные привязки портов:

Bash
1
0.0.0.0:8080->3000/tcp
Более детальную информацию о сетевых настройках контейнера можно получить с помощью команды:

Bash
1
docker inspect --format='{{json .NetworkSettings.Ports}}' имя_контейнера | jq

Сохранение данных с помощью volumes



Одна из ключевых особенностей Docker-контейнеров — их эфемерность. По умолчанию все изменения в файловой системе контейнера теряются при его удалении. Это может быть проблемой для приложений, которые хранят важные данные, например, базы данных или загруженные пользователем файлы. Docker решает эту проблему с помощью механизма томов (volumes). Тома — это специальные объекты для хранения данных, которые существуют независимо от контейнеров.

Типы монтирований в Docker



В Docker существует три основных типа монтирований:
1. Volumes — предпочтительный механизм хранения данных в Docker. Тома создаются и управляются через Docker, хранятся в части файловой системы хоста (/var/lib/docker/volumes/).
2. Bind mounts — позволяют монтировать файлы или директории хоста в контейнер. Могут располагаться где угодно в файловой системе хоста.
3. tmpfs mounts — хранят данные только в памяти хоста, а не на диске. Используются для временных данных, которые не нужно сохранять.

Использование томов (volumes)



Создать том можно командой:

Bash
1
docker volume create my-data
Затем используйте его при запуске контейнера:

Bash
1
docker run -v my-data:/data my-app
Это смонтирует том my-data в директорию /data внутри контейнера.

Для просмотра списка томов используйте:

Bash
1
docker volume ls
Чтобы посмотреть детальную информацию о томе:

Bash
1
docker volume inspect my-data
Удаление тома:

Bash
1
docker volume rm my-data

Монтирование директорий хоста (bind mounts)



Bind mount позволяет смонтировать директорию или файл с хост-системы в контейнер:

Bash
1
docker run -v /path/on/host:/path/in/container my-app
Например, для монтирования текущей директории в контейнер:

Bash
1
docker run -v $(pwd):/app my-app
Это особенно полезно при разработке, когда вы хотите видеть изменения в коде без пересборки образа.

Bind mount с правами только чтения:

Bash
1
docker run -v /path/on/host:/path/in/container:ro my-app

Пример: Node.js приложение с MongoDB



Рассмотрим конфигурацию для веб-приложения с базой данных:

Bash
1
2
3
4
5
6
7
8
# Создаем том для данных MongoDB
docker volume create mongo-data
 
# Запускаем MongoDB с подключенным томом
docker run -d --name mongodb -v mongo-data:/data/db mongo:4.4
 
# Запускаем Node.js приложение с пробросом порта и связью с MongoDB
docker run -d --name app -p 3000:3000 --link mongodb:mongo my-nodejs-app
В этом примере данные MongoDB будут сохраняться даже при удалении и пересоздании контейнера, а приложение будет доступно на порту 3000 хоста.

Использование именованных томов в Dockerfile



Вы можете декларативно указать том в Dockerfile с помощью директивы VOLUME:

Bash
1
2
3
4
5
6
7
FROM node:14
WORKDIR /app
COPY . .
RUN npm install
VOLUME /app/data
EXPOSE 3000
CMD ["node", "server.js"]
Тома, объявленные таким образом, будут созданы автоматически при запуске контейнера, если не указано иное при вызове docker run.

Лучшие практики по работе с томами



1. Используйте именованные тома вместо анонимных:
Bash
1
2
3
4
5
   # Именованный том (предпочтительно)
   docker run -v my-data:/app/data my-app
   
   # Анонимный том (не рекомендуется)
   docker run -v /app/data my-app
Именованные тома проще отслеживать и управлять ими.

2. Монтируйте только необходимые директории, а не весь проект. Это улучшает производительность и безопасность.

3. Используйте метки для томов для лучшего управления:
Bash
1
   docker volume create --label project=myapp --label env=dev my-data
4. Регулярно выполняйте резервное копирование важных данных из томов:
Bash
1
2
   docker run --rm -v my-data:/source -v $(pwd):/backup alpine \
     tar -czf /backup/my-data-backup.tar.gz -C /source .
5. Планируйте управление томами при развертывании. Рассмотрите вопросы: где хранить данные в производственной среде, как обеспечить резервное копирование, как масштабировать хранилище.

Комбинирование проброса портов и томов



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

Bash
1
2
3
4
5
6
docker run -d \
  --name my-wordpress \
  -p 8080:80 \
  -v wordpress-data:/var/www/html \
  -v wordpress-config:/var/www/html/wp-content/config \
  wordpress:latest
Такая конфигурация обеспечивает:
  • Доступность веб-сайта на порту 8080.
  • Сохранение всех файлов WordPress.
  • Отдельный том для конфигурационных файлов.

Использование Docker Compose для управления сетью и томами



Для сложных приложений с несколькими контейнерами, управление пробросами портов и томами через командную строку может стать громоздким. Docker Compose значительно упрощает эту задачу:

YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
version: '3'
services:
  app:
    build: .
    ports:
      - "8080:3000"
    volumes:
      - app-data:/app/data
      - ./src:/app/src
    depends_on:
      - db
  db:
    image: postgres:13
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: example
volumes:
  app-data:
  db-data:
С этим файлом docker-compose.yml вы можете запустить всю инфраструктуру одной командой:

Bash
1
docker-compose up -d
Docker Compose автоматически создаст необходимые тома и настроит сеть между сервисами.
Правильная настройка портов и томов является фундаментальным навыком при работе с Docker. Эти механизмы позволяют создавать контейнеризованные приложения, которые эффективно взаимодействуют с внешним миром и надежно хранят данные, сохраняя при этом все преимущества изолированной среды выполнения.

Практические советы



Теперь, когда у вас есть базовое понимание Docker и вы знаете, как создавать и запускать контейнеры, пора познакомиться с некоторыми практическими советами, которые сделают вашу работу с Docker более эффективной. Эти рекомендации основаны на опыте разработчиков, которые используют Docker в реальных проектах.

Оптимизация образов



Размер Docker-образов имеет прямое влияние на скорость развертывания и эффективность использования ресурсов. Вот несколько способов сократить размер ваших образов:

1. Используйте минималистичные базовые образы. Вместо полных дистрибутивов выбирайте образы на базе Alpine Linux:
Bash
1
2
3
4
5
# Обычный образ: ~900MB
FROM node:14 
 
# Образ на базе Alpine: ~110MB
FROM node:14-alpine
2. Объединяйте команды RUN для уменьшения количества слоёв:
Bash
1
2
3
4
5
6
7
8
9
# Плохо: 3 слоя
RUN apt-get update 
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
 
# Хорошо: 1 слой
RUN apt-get update && \
    apt-get install -y curl && \
    rm -rf /var/lib/apt/lists/*
3. Удаляйте ненужные файлы в том же слое, где они были созданы:
Bash
1
2
3
4
5
6
RUN apt-get update && \
    apt-get install -y gcc g++ make && \
    npm install && \
    apt-get purge -y gcc g++ make && \
    apt-get autoremove -y && \
    rm -rf /var/lib/apt/lists/*
4. Используйте директиву .dockerignore для исключения ненужных файлов из контекста сборки:
Bash
1
2
3
4
5
node_modules
npm-debug.log
.git
.vscode
*.md
5. Не устанавливайте dev-зависимости в продакшн-образах:
Bash
1
2
3
4
5
# Для Node.js
RUN npm install --only=production
 
# Для Python
RUN pip install --no-cache-dir -r requirements.txt

Отладка контейнеров



Когда что-то идёт не так с вашим контейнером, знание методов отладки поможет быстро решить проблему:

1. Проверка логов контейнера:
Bash
1
2
3
docker logs имя_контейнера
# Для отслеживания в реальном времени
docker logs -f имя_контейнера
2. Доступ к shell внутри работающего контейнера:
Bash
1
2
3
docker exec -it имя_контейнера /bin/sh
# Или для контейнеров с bash
docker exec -it имя_контейнера /bin/bash
3. Проверка информации о контейнере:
Bash
1
docker inspect имя_контейнера
4. Отслеживание использования ресурсов:
Bash
1
docker stats имя_контейнера
5. Отладка сетевых проблем:
Bash
1
2
3
# Внутри контейнера
docker exec -it имя_контейнера ping другой_хост
docker exec -it имя_контейнера nslookup сервис_имя
6. Запуск контейнера с повышенной детализацией логов:
Bash
1
docker run -e "DEBUG=true" имя_образа
7. Запуск приложения с командой отладки вместо стандартной:
Bash
1
docker run --rm -it имя_образа python -m debugpy --listen 0.0.0.0:5678 app.py

Взаимодействие между контейнерами



Для создания сложных приложений часто требуется взаимодействие между несколькими контейнерами:

1. Используйте пользовательские сети вместо опции --link (которая считается устаревшей):
Bash
1
2
3
4
5
6
# Создание сети
docker network create my-network
 
# Запуск контейнеров в одной сети
docker run --network my-network --name database postgres
docker run --network my-network --name app my-app
В этом случае контейнер app может обращаться к контейнеру database просто по имени.

2. Использование Docker Compose для управления несколькими контейнерами:
YAML
1
2
3
4
5
6
7
8
version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"

Переход к Docker Compose



Docker Compose значительно упрощает работу с многоконтейнерными приложениями. Вот базовый пример docker-compose.yml:
YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '3'
services:
  web:
    build: ./web
    ports:
      - "8000:8000"
    depends_on:
      - db
    environment:
      - DATABASE_URL=postgres://postgres:postgres@db:5432/app
    volumes:
      - ./web:/app
      
  db:
    image: postgres:13
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=app
      
volumes:
  postgres_data:
Основные команды Docker Compose:

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Запуск всех сервисов
docker-compose up
 
# Запуск в фоновом режиме
docker-compose up -d
 
# Остановка сервисов
docker-compose down
 
# Просмотр логов
docker-compose logs
 
# Запуск команды в определённом сервисе
docker-compose exec web python manage.py migrate

Управление ресурсами контейнеров



По умолчанию Docker не ограничивает использование ресурсов контейнерами, что может привести к проблемам:

1. Ограничение памяти:
Bash
1
docker run --memory="512m" --memory-swap="1g" имя_образа
2. Ограничение CPU:
Bash
1
2
3
4
5
# Ограничение до 50% CPU одного ядра
docker run --cpus=".5" имя_образа
 
# Ограничение контейнера ядрами 0 и 1
docker run --cpuset-cpus="0,1" имя_образа
3. Ограничение операций ввода-вывода:
Bash
1
docker run --device-write-bps /dev/sda:1mb имя_образа

Автоматизация рутинных операций



Для упрощения частых операций можно создать алиасы (сокращения) команд:

Bash
1
2
3
4
5
6
7
8
9
10
11
# Добавьте в ваш ~/.bashrc или ~/.zshrc
alias dps='docker ps'
alias dimg='docker images'
alias dexec='docker exec -it'
alias dlog='docker logs -f'
 
# Удаление всех остановленных контейнеров
alias docker-clean='docker container prune -f'
 
# Удаление всех неиспользуемых образов
alias docker-clean-images='docker image prune -af'

Организация рабочего процесса



Вот несколько советов по организации рабочего процесса с Docker:

1. Используйте разные Dockerfile для разных окружений:
Bash
1
2
3
4
myapp/
├── Dockerfile          # Для продакшена
├── Dockerfile.dev      # Для разработки
└── Dockerfile.test     # Для тестирования
2. Создайте скрипты для частых операций:
Bash
1
2
3
4
5
6
7
8
9
10
#!/bin/bash
# deploy.sh
echo "Building Docker image..."
docker build -t myapp:latest .
 
echo "Pushing to registry..."
docker tag myapp:latest registry.example.com/myapp:latest
docker push registry.example.com/myapp:latest
 
echo "Done!"
3. Используйте групповые переменные окружения через файлы .env:
Bash
1
2
3
4
# .env file
DB_HOST=postgres
DB_USER=myapp
DB_PASS=secret
Bash
1
docker run --env-file .env myapp
4. Настройте автоматические тесты в контейнерах:
Bash
1
2
# Запуск тестов в одноразовом контейнере
docker run --rm myapp-tests pytest
Эти практические советы помогут вам использовать Docker более эффективно и избегать типичных проблем. По мере накопления опыта вы разработаете свои собственные практики, учитывающие специфику ваших проектов. В следующем разделе мы рассмотрим инструменты мониторинга контейнеров и основы безопасности в Docker.

Инструменты мониторинга и безопасность Docker-контейнеров



При использовании Docker в производственной среде критически важно иметь возможность отслеживать состояние контейнеров и обеспечивать их безопасность. Давайте рассмотрим наиболее эффективные инструменты мониторинга и основные принципы защиты Docker-контейнеров.

Инструменты мониторинга контейнеров



Мониторинг контейнеров помогает своевременно выявлять проблемы с производительностью, обнаруживать аномалии и обеспечивать стабильную работу приложений. Вот несколько популярных инструментов:

1. Docker Stats



Самый простой способ мониторинга - встроенная команда Docker:
Bash
1
docker stats
Она отображает использование CPU, памяти, сетевой активности и дисковых операций для каждого запущенного контейнера в реальном времени. Для получения данных конкретного контейнера:
Bash
1
docker stats имя_контейнера
Преимущество - не требует дополнительных установок, но функционал ограничен базовыми метриками.

2. cAdvisor (Container Advisor)



Разработанный Google инструмент cAdvisor собирает, агрегирует и экспортирует информацию о запущенных контейнерах. Он анализирует использование ресурсов и производительность в режиме реального времени.
Bash
1
2
3
4
5
6
7
8
9
docker run \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --publish=8080:8080 \
  --detach=true \
  --name=cadvisor \
  gcr.io/cadvisor/cadvisor:latest
После запуска веб-интерфейс доступен по адресу http://localhost:8080, где отображается детальная статистика с удобной визуализацией.

3. Prometheus + Grafana



Для более серьезного мониторинга часто используется связка Prometheus (система сбора метрик) и Grafana (система визуализации):
1. Prometheus собирает метрики с контейнеров через различные экспортеры.
2. Grafana создает интерактивные дашборды на основе этих данных.

Для интеграции с Docker необходимо настроить Docker для экспорта метрик:

Bash
1
2
3
4
5
# В файле daemon.json
{
  "metrics-addr" : "127.0.0.1:9323",
  "experimental" : true
}
Затем настроить Prometheus для сбора этих метрик:

YAML
1
2
3
4
5
# prometheus.yml
scrape_configs:
  - job_name: 'docker'
    static_configs:
      - targets: ['127.0.0.1:9323']
Преимущество этого подхода - гибкая настройка мониторинга, возможность создания алертов и визуализация исторических данных.

4. Portainer



Portainer предоставляет не только мониторинг, но и полноценное управление Docker-средой через веб-интерфейс:

Bash
1
2
3
4
5
docker run -d -p 9000:9000 --name portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  portainer/portainer-ce
После установки доступна информация о контейнерах, образах, сетях и томах с возможностью управления ими через браузер (http://localhost:9000).

5. Datadog



Для крупных проектов актуален Datadog — платформа мониторинга с поддержкой контейнеров, которая интегрируется с Docker через агент:

Bash
1
2
3
4
5
6
docker run -d --name datadog-agent \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /proc/:/host/proc/:ro \
  -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \
  -e DD_API_KEY=<YOUR_API_KEY> \
  datadog/agent:latest
Datadog предлагает расширенную аналитику, автоматическую корреляцию событий и настраиваемые оповещения.

Безопасность Docker-контейнеров: основные принципы



Обеспечение безопасности контейнеров требует комплексного подхода. Рассмотрим основные практики:

1. Сканирование образов на уязвимости



Перед использованием контейнеров в производстве проверяйте их на наличие уязвимостей с помощью специализированных инструментов:

Trivy — простой в использовании сканер образов:
Bash
1
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image имя_образа:тег
Clair — сканер с открытым исходным кодом от CoreOS, который интегрируется с CI/CD-пайплайнами.

Docker Scan — встроенный в Docker CLI инструмент для сканирования образов:
Bash
1
docker scan имя_образа:тег

2. Использование непривилегированных пользователей



Запуск приложений от имени root в контейнере может привести к серьезным проблемам безопасности. Создавайте и используйте отдельного пользователя:
Bash
1
2
3
4
# Создание пользователя
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Смена пользователя
USER appuser

3. Ограничение возможностей (capabilities)



Docker позволяет тонко настраивать привилегии контейнеров:
Bash
1
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE my-app
Этот пример удаляет все стандартные разрешения и добавляет только возможность привязки к порту ниже 1024.

4. Использование read-only файловой системы



Для дополнительной защиты можно запускать контейнеры с файловой системой только для чтения:
Bash
1
docker run --read-only my-app
Если приложению необходимо записывать данные, монтируйте только конкретные директории:
Bash
1
2
3
docker run --read-only \
  -v /tmp/app-data:/app/data \
  my-app

5. Ограничение ресурсов



Ограничение ресурсов не только оптимизирует использование системы, но и предотвращает атаки типа DoS:
Bash
1
2
3
4
5
6
docker run \
  --memory="512m" \
  --memory-swap="1g" \
  --cpu-shares=512 \
  --pids-limit=100 \
  my-app

6. Настройка сетевой изоляции



Используйте пользовательские сети Docker для изоляции групп контейнеров:
Bash
1
2
3
4
5
# Создание изолированной сети
docker network create --driver bridge isolated_network
 
# Запуск контейнера в этой сети
docker run --network isolated_network my-app

7. Аудит безопасности с Docker Bench



Docker Bench Security — инструмент, который проверяет соответствие установки Docker рекомендациям CIS (Center for Internet Security):
Bash
1
2
3
4
5
6
7
docker run --net host --pid host --userns host --cap-add audit_control \
    -v /var/lib:/var/lib \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /etc:/etc \
    -v /usr/bin/containerd:/usr/bin/containerd \
    -v /usr/bin/runc:/usr/bin/runc \
    docker/docker-bench-security

8. Регулярные обновления образов



Своевременное обновление образов помогает устранять выявленные уязвимости. Внедрите в процесс CI/CD автоматическое обновление базовых образов:
Bash
1
2
3
# Пример скрипта для обновления и пересборки
docker pull node:14-alpine
docker build -t my-app:latest .

9. Подписание образов



Для подтверждения подлинности образов используйте Docker Content Trust:
Bash
1
2
3
4
5
# Включение
export DOCKER_CONTENT_TRUST=1
 
# Подписание при отправке в репозиторий
docker push my-username/my-image:tag

10. Мониторинг аномалий поведения



Инструменты типа Falco от Sysdig позволяют обнаруживать аномальное поведение контейнеров на основе определенных правил:
Bash
1
2
3
4
docker run -d --name falco \
  --privileged \
  -v /var/run/docker.sock:/var/run/docker.sock \
  falcosecurity/falco
Комбинируя эти инструменты и практики, можно создать надежную стратегию мониторинга и защиты Docker-контейнеров. Внедрение этих инструментов и практик безопасности с самого начала работы с Docker поможет избежать многих проблем в будущем, особенно при масштабировании инфраструктуры и увеличении количества контейнеров.

Порядок разворачивания приложения при использовании Docker + Rails
Всем привет, может кто нибудь подсказать ответ на вопрос. При использовании Docker в Dockerfile часто сначала копируются файлы зависимостей...

Запуск linux контейнеров Docker в windows без Docker Desktop
Всем доброго времени суток! Пытаюсь разворачивать локальный веб-сервер на ПК С ОС windows с помощью контейнеризатора Docker, при этом в нашей фирме...

Не могу создать образ Docker, подскажите как сделать. Вылазить ошибка. docker-file. Новичок в докере
Если можно обясните как строить докер файл. столько видео посмотрел ничего не понял Step 4/5 : RUN javac ShorturlApplication.java ---&gt;...

Docker-compose push to Docker Hub
Всем привет! Я заготовил docker-compose.yml, но есть несколько зависимостей в папочках . ├── db │   ├── create.sql │   ├──...

Docker, IP Host -> Docker responce
есть некий сервис достучатся к которому возможно по IP (но только через VPN), задался вопросом, а можно как-то сделать чтобы при запуске докера...

Руководство по созданию освещения
Не могу найти КАЧЕСТВЕННОЕ руководство по созданию освещения на OpenGL+ GLSL. Может кто знает?

Flex руководство по созданию примера
Всем доброго времени суток! Дана лабораторная работа по С++. Нужно, используя библиотеку flex, из этого: Ext 999 7:10 AM , 12/11/2003 ...

Руководство по созданию клиент-сервера
Подскажите мануал, содержащий инструкцию для создания клиент-сервера, с подробными описаниями.

Исходники кода для книги Java 8 (2015) Шилдт - руководство для начинающих
Там код иногда странные ошибки возникают особенно UNicode сбивается , не могу нормально точь в точь переписать, а исходинки чет именно на яву не могу...

Java: руководство для начинающих Герберт Шилдт
Помогите скачать: Java: руководство для начинающих Герберт Шилдт. Ребят, поделитесь сканами если есть у кого или ссылкой. Очень редкая книга, весь...

Нужно руководство по созданию отчётов в VS2011 Reporting
Помогите, пожалуйста. Нужно руководство по созданию отчётов в сабже. Есть ли где-то, желательно краткое, описание, как сделать необходимое? С учётом...

Краткое руководство по работе с классом TCanvas для начинающих
Вступление Часто на форуме возникают вопросы по поводу рисования той или иной фигуры на канве, а также просят привести список всех функций...

Метки devops, docker
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Согласованность транзакций в MongoDB
Codd 30.04.2025
MongoDB, начинавшая свой путь как классическая NoSQL система с акцентом на гибкость и масштабируемость, сильно спрогрессировала, включив в свой арсенал поддержку транзакционной согласованности. Это. . .
Продвинутый ввод-вывод в Java: NIO, NIO.2 и асинхронный I/O
Javaican 30.04.2025
Когда речь заходит о вводе-выводе в Java, классический пакет java. io долгие годы был единственным вариантом для разработчиков, но его ограничения становились всё очевиднее с ростом требований к. . .
Обнаружение объектов в реальном времени на Python с YOLO и OpenCV
AI_Generated 29.04.2025
Компьютерное зрение — одна из самых динамично развивающихся областей искусственного интеллекта. В нашем мире, где визуальная информация стала доминирующим способом коммуникации, способность машин. . .
Эффективные парсеры и токенизаторы строк на C#
UnmanagedCoder 29.04.2025
Обработка текстовых данных — частая задача в программировании, с которой сталкивается почти каждый разработчик. Парсеры и токенизаторы составляют основу множества современных приложений: от. . .
C++ в XXI веке - Эволюция языка и взгляд Бьярне Страуструпа
bytestream 29.04.2025
C++ существует уже более 45 лет с момента его первоначальной концепции. Как и было задумано, он эволюционировал, отвечая на новые вызовы, но многие разработчики продолжают использовать C++ так, будто. . .
Слабые указатели в Go: управление памятью и предотвращение утечек ресурсов
golander 29.04.2025
Управление памятью — один из краеугольных камней разработки высоконагруженных приложений. Го (Go) занимает уникальную нишу в этом вопросе, предоставляя разработчикам автоматическое управление памятью. . .
Разработка кастомных расширений для компилятора C++
NullReferenced 29.04.2025
Создание кастомных расширений для компиляторов C++ — инструмент оптимизации кода, внедрения новых языковых функций и автоматизации задач. Многие разработчики недооценивают гибкость современных. . .
Гайд по обработке исключений в C#
stackOverflow 29.04.2025
Разработка надёжного программного обеспечения невозможна без грамотной обработки исключительных ситуаций. Любая программа, независимо от её размера и сложности, может столкнуться с непредвиденными. . .
Создаем RESTful API с Laravel
Jason-Webb 28.04.2025
REST (Representational State Transfer) — это архитектурный стиль, который определяет набор принципов для создания веб-сервисов. Этот подход к построению API стал стандартом де-факто в современной. . .
Дженерики в C# - продвинутые техники
stackOverflow 28.04.2025
История дженериков началась с простой идеи — создать механизм для разработки типобезопасного кода без потери производительности. До их появления программисты использовали неуклюжие преобразования. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru