Skip to the content.

Вернуться к главной странице, списку всех тем

4. Упаковка приложений со всем необходимым для их работы, передача и запуск таких «контейнеров» другим, запуск нескольких контейнеров вместе

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

Контейнеризация

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

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

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

  1. Docker — это приложение которое работает как сервис systemd (то есть запущенно постоянно), предназначенное для создания, запуска и управления контейнерами.
  2. Контейнер (Container) — это изолированная среда, которая содержит все необходимое для запуска приложения: код, зависимости, библиотеки, конфигурационные файлы и так далее. Контейнеры используют общие ресурсы хоста, но при этом остаются независимыми друг от друга.
  3. Образ (Image) — это шаблон из слоев, на основе которого создаются контейнеры. Можно представить, что образ как рецепт слоёного пирога, а контейнер — это уже готовый слоёный пирог. Образ включает в себя все необходимые компоненты для запуска приложения, такие как операционная система, библиотеки и настройки.
  4. Репозиторий (Repository) — это хранилище образов Docker. Репозитории могут быть как общедоступными, например, Docker Hub, так и частными — созданными на вашем компьютере и доступными только для ограниченного круга лиц, например, для ваших друзей. Они предоставляют возможность хранить и обмениваться образами между разработчиками и командами.
  5. Тег (Tag) — это метка, которая присваивается образу для идентификации конкретной версии или состояния. Например, тег “latest” обычно указывает на последнюю версию образа. Примеры образов:
    1. nginx:1.27.3 - базовый образ Nginx с тегом 1.27.3, на основании которого вы можете
    2. ubuntu:24.04 - Базовый образ Ubuntu с тегом 24.04, который вы можете использовать для запуска своего приложения в изолированной среде Ubuntu, добавляя собственные слои cсодержащие ваше приложение, команду для его запуска, библиотеки и т.д.
  6. Dockerfile — это файл, содержащий инструкции для сборки образа Docker. Он описывает шаги, которые необходимо выполнить для создания образа, начиная с базового (например как выше Ubuntu) и заканчивая установкой всех необходимых компонентов.
  7. Командная строка Docker (CLI) — это интерфейс для взаимодействия с сервисом Docker через команды. С помощью CLI можно выполнять различные операции, такие как создание, запуск, остановка и удаление контейнеров, сборка образов и многое другое.
  8. Volume (Том) — это механизм для сохранения данных вне контейнера. Том позволяет сохранять данные даже после удаления контейнера, что особенно полезно для хранения важных файлов или базы данных.
  9. Network (Сеть) — это способ подключения контейнеров друг к другу и внешнему миру. Docker поддерживает различные типы сетей, что позволяет настраивать взаимодействие между контейнерами.

Преимущества контейнеризации

  1. Простота и скорость развертывания - Контейнеры создаются и удаляются очень быстро, поскольку для их создания не требуется установка полной операционной системы.
  2. Переносимость - Контейнеры могут работать практически на любой платформе, где установлен соответствующий движок контейнеризации, например, Docker.
  3. Экономия ресурсов - Поскольку контейнеры используют одно и то же ядро операционной системы, они занимают меньше места и потребляют меньше ресурсов по сравнению с виртуальными машинами.
  4. Упрощение разработки и тестирования - Разработчики могут создавать контейнеры, содержащие все необходимые зависимости, что значительно облегчает процесс тестирования и развертывания кода.

Недостатки контейнеризации

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

Виртуализация

Виртуализация — это процесс создания виртуальных машин (VM), то есть на одном физическом компьютере можно запустить несколько виртуальных, каждая из которых имеет свою собственную копию операционной системы. Эти виртуальные машины функционируют на основе гипервизора — программы, отвечающей за создание и управление виртуальными машинами. Гипервизор распределяет ресурсы физической машины между различными виртуальными машинами.

Вот несколько примеров технологий виртуализации:

Преимущества виртуализации

  1. Полная изоляция - Каждая виртуальная машина функционирует под управлением собственной копии операционной системы, что обеспечивает надежную защиту приложений и данных.
  2. Безопасность - Благодаря полной изоляции, сбой или атака на одну виртуальную машину не затронет остальные.
  3. Поддержка различных операционных систем - Виртуальные машины дают возможность одновременно запускать различные операционные системы на одном физическом оборудовании, что открывает новые горизонты для использования и управления.
  4. Управление ресурсами - Гипервизоры обеспечивают гибкое управление ресурсами, позволяя динамически распределять процессорное время, память и дисковое пространство между виртуальными машинами, что дает возможность максимально эффективно использовать ресурсы.

Недостатки виртуализации

  1. Высокая нагрузка на ресурсы - Каждая виртуальная машина требует значительного объёма памяти и процессорных мощностей, поскольку содержит полную копию операционной системы.
  2. Медленное развёртывание - Процесс создания новой виртуальной машины занимает больше времени по сравнению с контейнерами.
  3. Сложное масштабирование - Масштабирование виртуальных машин связано с дополнительными затратами ресурсов и времени, особенно когда требуется создать несколько копий одной и той же виртуальной машины.

Запуск нескольких контейнеров вместе

Compose — это инструмент, который позволяет легко создавать и запускать многоконтейнерные приложения. Он работает на основе файла compose.yml, в котором описывается, какие контейнеры будут запущены, а также их переменные среды, сети и тома.

Compose упрощает запуск и тестирование нескольких контейнеров одновременно. Например, если мы создаем проект интернет-магазина, нам понадобятся два контейнера, которые будут взаимодействовать друг с другом. Удобнее всего управлять ими и запускать их вместе с помощью Compose.

  1. Первый контейнер — это веб-сайт (приложение которое принимает и отвечает на HTTP запросы), который должен иметь возможность обращаться к базе данных для отображения информации из нее в виде HTML-страниц.
  2. Второй контейнер — это база данных (приложение которое записывает данные на диск особенным образом) товаров и учетных записей пользователей.

Теоретические вопросы

  1. В чем ключевые различия между виртуализацией и контейнеризацией?
  2. Как Docker обеспечивает изоляцию контейнеров?
  3. Сохраняются ли данные, которые хранились в контейнере, после его остановки?
  4. Зачем нужны тома (volumes) в docker?
  5. Где располагаются тома (volumes), создаваемые Docker?
  6. Что такое логи и где хранятся логи для dokcer приложений?
  7. Каким образом формируется образ для контейнера?
  8. Как происходит создание контейнера?
  9. В чем заключается разница между образом и контейнером?
  10. Приведите пример простого Dockerfile.
  11. Объясните, как создаются слои в Dockerfile?
  12. Какие основные инструкции есть для создания слоев в Dockerfile?
  13. При создании нового слоя, что происходит?
  14. В чем разница между ENTRYPOINT и CMD?
  15. Возможно ли использовать ENTRYPOINT и CMD одновременно?
  16. Почему не рекомендуется всегда использовать только latest версию образа?
  17. Как остановить запущенный контейнер, но не уничтожить его?
  18. Допустимо ли запускать несколько контейнеров на одной виртуальной машине?
  19. Какой командой можно просмотреть все образы Docker, скачанные на вашу машину?
  20. Какой командой выгрузить ваш образ в registry?
  21. Какие основные типы сетей поддерживает docker?
  22. Чем лучше сборка через kaniko чем через docker?
  23. Чем отличается базовый образ alpine от ubuntu?
  24. В чем отличия между COPY и ADD?
  25. Можно ли в docker compose ограничить использование RAM и CPU для отдельных контейнеров?
  26. Как настроить контейнер так чтобы он перезапускался сам если приложение внутри сломается?
    1. Как сделать также в docker compose?

Практическое руководство по Docker для начинающих

Подготовка к работе

Что вам понадобится

Задание 0: Установка и проверка Docker

Цель

Убедиться, что Docker установлен и работает на вашем компьютере.

Шаги

Шаг 1: Проверка установки Docker

docker --version

Зачем это нужно: Эта команда покажет версию Docker, если он установлен. Если команда не найдена, Docker нужно установить.

Ожидаемый результат: Вы увидите что-то вроде:

Docker version 24.0.6, build ed223bc

Шаг 2: Проверка работы Docker

docker ps

Зачем это нужно: Команда показывает список запущенных контейнеров. Если она работает без ошибок, Docker установлен правильно.

Ожидаемый результат: Пустая таблица (так как контейнеры ещё не запущены):

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Если появилась ошибка: Возможно, Docker не запущен. На Windows/Mac запустите Docker Desktop. На Linux запустите сервис:

sudo systemctl start docker

Задание 1: Первое знакомство с Docker-образами

Цель

Научиться скачивать готовые образы из Docker Hub и работать с ними.

Шаги

Шаг 1: Скачивание образа nginx

docker pull nginx

Зачем это нужно: docker pull скачивает образ из Docker Hub (это как магазин приложений, но для Docker). Nginx — это популярный веб-сервер, который мы будем использовать для практики.

Ожидаемый результат: Вы увидите процесс загрузки слоёв образа:

Using default tag: latest
latest: Pulling from library/nginx
...
Status: Downloaded newer image for nginx:latest

Шаг 2: Просмотр скачанных образов

docker images

Зачем это нужно: Команда показывает все образы, которые есть на вашем компьютере.

Ожидаемый результат:

REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    a6bd71f48f68   2 weeks ago   187MB

Обратите внимание на:

Шаг 3: Скачивание конкретной версии nginx

docker pull nginx:1.27.3

Зачем это нужно: В продакшене (реальных проектах) не рекомендуется использовать тег latest, так как он может измениться. Лучше указывать конкретную версию.

Ожидаемый результат: Скачается образ с конкретной версией.

Шаг 4: Проверка, что скачались оба образа

docker images nginx

Зачем это нужно: Мы фильтруем вывод, чтобы видеть только образы nginx.

Ожидаемый результат:

REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    a6bd71f48f68   2 weeks ago   187MB
nginx        1.27.3    a6bd71f48f68   2 weeks ago   187MB

Важно: Возможно, IMAGE ID будет одинаковым — это нормально, если latest указывает на ту же версию.

Задание 2: Запуск первого контейнера

Цель

Запустить контейнер с nginx и получить доступ к нему через браузер.

Шаги

Шаг 1: Простой запуск контейнера

docker run nginx:1.27.3

Зачем это нужно: docker run создаёт и запускает контейнер из образа.

Ожидаемый результат: Терминал “повиснет” и будет показывать логи nginx. Это нормально — контейнер работает.

Чтобы остановить: Нажмите Ctrl+C

Что произошло: Мы запустили nginx, но не можем к нему подключиться, так как порты не пробросили.

Шаг 2: Запуск контейнера в фоновом режиме

docker run -d nginx:1.27.3

Зачем это нужно: Флаг -d (detached) запускает контейнер в фоновом режиме, освобождая терминал.

Ожидаемый результат: Длинная строка (ID контейнера):

f5a8c2b1e9d4a3c7b6e5f4d3c2b1a0e9d8c7b6a5f4e3d2c1b0a9e8d7c6b5a4f3

Шаг 3: Проверка запущенных контейнеров

docker ps

Зачем это нужно: Посмотреть, какие контейнеры сейчас работают.

Ожидаемый результат:

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS      NAMES
f5a8c2b1e9d4   nginx:1.27.3   "/docker-entrypoint.…"   5 seconds ago   Up 4 seconds   80/tcp     inspiring_euler

Обратите внимание:

Шаг 4: Остановка контейнера

docker stop f5a8c2b1e9d4

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

Замените f5a8c2b1e9d4 на первые символы ID вашего контейнера из предыдущего шага.

Ожидаемый результат: Команда вернёт ID контейнера, подтверждая остановку.

Шаг 5: Запуск контейнера с пробросом порта

docker run -d -p 8080:80 --name my-nginx nginx:1.27.3

Зачем это нужно:

Ожидаемый результат: Новый ID контейнера.

Шаг 6: Проверка доступа через браузер

Откройте браузер и перейдите по адресу:

http://localhost:8080

Зачем это нужно: Проверить, что nginx работает и доступен.

Ожидаемый результат: Вы увидите страницу приветствия nginx:

Welcome to nginx!
If you see this page, the nginx web server is successfully installed and working.

Что произошло: Ваш браузер отправил запрос на порт 8080 вашего компьютера, Docker перенаправил его на порт 80 внутри контейнера, nginx обработал запрос и вернул HTML-страницу.

Шаг 7: Просмотр логов контейнера

docker logs my-nginx

Зачем это нужно: Увидеть, что происходит внутри контейнера (запросы, ошибки).

Ожидаемый результат: Логи nginx, включая ваш запрос из браузера:

/docker-entrypoint.sh: Configuration complete; ready for start up
172.17.0.1 - - [24/Nov/2025:10:30:45 +0000] "GET / HTTP/1.1" 200 615

Шаг 8: Остановка и удаление контейнера

# Остановить контейнер
docker stop my-nginx

# Удалить контейнер
docker rm my-nginx

Зачем это нужно: Освободить ресурсы и имя контейнера для следующих экспериментов.

Ожидаемый результат: Обе команды вернут имя контейнера.

Проверка:

docker ps -a

Контейнер my-nginx не должен отображаться в списке.

Задание 3: Создание своего Docker-образа

Цель

Создать собственную HTML-страницу и упаковать её в Docker-образ с nginx.

Шаги

Шаг 1: Создание рабочей директории

# Создаём папку для проекта
mkdir my-first-docker-project

# Переходим в неё
cd my-first-docker-project

Зачем это нужно: Организовать файлы проекта в отдельной папке.

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

Проверка:

pwd

Должен показать путь к my-first-docker-project.

Шаг 2: Узнаём, где nginx хранит HTML-файлы

# Запустим временный контейнер
docker run --rm nginx:1.27.3 cat /etc/nginx/conf.d/default.conf | grep root

Зачем это нужно: Узнать путь к директории с HTML-файлами внутри контейнера nginx.

Ожидаемый результат:

    root   /usr/share/nginx/html;

Что это значит: Файлы сайта находятся в /usr/share/nginx/html/ внутри контейнера.

Шаг 3: Создание своей HTML-страницы

Создайте файл index.html в текущей директории:

# Для Linux/Mac:
cat > index.html << 'EOF'
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Моя первая страница в Docker</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }
        .container {
            text-align: center;
            padding: 40px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 20px;
            backdrop-filter: blur(10px);
        }
        h1 {
            font-size: 3em;
            margin-bottom: 20px;
        }
        p {
            font-size: 1.5em;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🎉 Поздравляю!</h1>
        <p>Вы создали свой первый Docker-образ!</p>
        <p>Имя студента: <strong>Ваше Имя</strong></p>
        <p>Версия: 1.0</p>
    </div>
</body>
</html>
EOF

Для Windows (PowerShell): Создайте файл через блокнот или используйте команду:

@"
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Моя первая страница в Docker</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }
        .container {
            text-align: center;
            padding: 40px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 20px;
        }
        h1 { font-size: 3em; margin-bottom: 20px; }
        p { font-size: 1.5em; }
    </style>
</head>
<body>
    <div class="container">
        <h1>🎉 Поздравляю!</h1>
        <p>Вы создали свой первый Docker-образ!</p>
        <p>Имя студента: <strong>Ваше Имя</strong></p>
        <p>Версия: 1.0</p>
    </div>
</body>
</html>
"@ | Out-File -FilePath index.html -Encoding UTF8

Зачем это нужно: Создать свою уникальную веб-страницу, которую мы упакуем в Docker-образ.

Проверка:

ls

Вы должны увидеть файл index.html.

Шаг 4: Создание Dockerfile

Создайте файл с именем Dockerfile (без расширения):

# Для Linux/Mac:
cat > Dockerfile << 'EOF'
# Указываем базовый образ - nginx версии 1.27.3
# Это основа, на которой мы строим свой образ
FROM nginx:1.27.3

# Копируем наш index.html в директорию, где nginx ищет файлы сайта
# Путь /usr/share/nginx/html/ - стандартное место для HTML-файлов в nginx
COPY index.html /usr/share/nginx/html/

# Документируем, что контейнер будет слушать порт 80
# Это информация для пользователей образа
EXPOSE 80

# Не нужно указывать CMD, так как базовый образ nginx уже знает, как запускаться
EOF

Для Windows (PowerShell):

@"
FROM nginx:1.27.3
COPY index.html /usr/share/nginx/html/
EXPOSE 80
"@ | Out-File -FilePath Dockerfile -Encoding UTF8 -NoNewline

Зачем это нужно: Dockerfile — это инструкция для Docker, как собрать образ. Мы говорим: “Возьми nginx, добавь туда мой HTML-файл”.

Проверка:

ls

Должны быть два файла: Dockerfile и index.html.

Шаг 5: Сборка Docker-образа

docker build -t devops:1.0 .

Расшифровка команды:

Ожидаемый результат:

[+] Building 2.5s (7/7) FINISHED
 => [internal] load build definition from Dockerfile
 => [internal] load .dockerignore
 => [internal] load metadata for docker.io/library/nginx:1.27.3
 => [1/2] FROM docker.io/library/nginx:1.27.3
 => [internal] load build context
 => [2/2] COPY index.html /usr/share/nginx/html/
 => exporting to image
 => => naming to docker.io/library/devops:1.0

Что произошло: Docker создал новый образ на основе nginx, добавил в него ваш HTML-файл.

Шаг 6: Проверка созданного образа

docker images devops

Ожидаемый результат:

REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
devops       1.0       b9c8f7e6d5a4   10 seconds ago   187MB

Шаг 7: Запуск контейнера с вашим образом

docker run -d -p 8080:80 --name my-first-app devops:1.0

Зачем это нужно: Запустить контейнер из нашего нового образа.

Ожидаемый результат: ID нового контейнера.

Шаг 8: Проверка в браузере

Откройте браузер и перейдите:

http://localhost:8080

Ожидаемый результат: Вы должны увидеть вашу красивую страницу с градиентным фоном и поздравлением!

🎉 Поздравляю! Вы создали и запустили свой первый Docker-образ!

Шаг 9: Эксперименты (опционально)

Попробуйте изменить index.html, пересобрать образ с другим тегом и запустить:

# 1. Отредактируйте index.html (измените текст)
# 2. Пересоберите образ с новым тегом
docker build -t devops:2.0 .

# 3. Остановите старый контейнер
docker stop my-first-app

# 4. Запустите новый
docker run -d -p 8080:80 --name my-second-app devops:2.0

# 5. Обновите страницу в браузере

Задание 4: Docker Compose для нескольких контейнеров

Цель

Научиться запускать несколько связанных контейнеров одновременно.

Шаги

Шаг 1: Создание файла compose.yml

В той же папке создайте файл compose.yml:

# Для Linux/Mac:
cat > compose.yml << 'EOF'
# Версия формата Docker Compose (можно не указывать в новых версиях)
version: '3.8'

# Описываем сервисы (контейнеры), которые будут запущены
services:
  
  # Первый сервис - наш веб-сервер nginx
  web:
    # Используем образ, который мы создали
    image: devops:1.0
    
    # Имя контейнера
    container_name: my-web-app
    
    # Проброс портов: порт_на_компьютере:порт_в_контейнере
    ports:
      - "8080:80"
    
    # Автоматический перезапуск при сбое
    restart: unless-stopped
  
  # Второй сервис - контейнер, который будет отправлять запросы к nginx
  tester:
    # Используем легковесный образ alpine с curl
    image: alpine:latest
    
    # Имя контейнера
    container_name: web-tester
    
    # Команда, которая будет выполняться в контейнере
    # Каждые 10 секунд отправляем HTTP-запрос к нашему nginx
    command: >
      sh -c "
      apk add --no-cache curl &&
      while true; do
        echo '========== Отправляю запрос к web серверу ==========' &&
        curl -s http://web:80 | head -n 5 &&
        echo '' &&
        echo 'Жду 10 секунд...' &&
        sleep 10;
      done
      "
    
    # Указываем, что tester зависит от web
    # Docker запустит web раньше, чем tester
    depends_on:
      - web
EOF

Для Windows (PowerShell): Создайте файл через блокнот и скопируйте содержимое выше.

Зачем это нужно:

Шаг 2: Запуск Docker Compose

docker compose up

Зачем это нужно: Запустить все сервисы, описанные в compose.yml.

Ожидаемый результат: Вы увидите логи обоих контейнеров в реальном времени:

my-web-app   | /docker-entrypoint.sh: Configuration complete; ready for start up
web-tester   | ========== Отправляю запрос к web серверу ==========
web-tester   | <!DOCTYPE html>
web-tester   | <html lang="ru">
web-tester   | <head>
web-tester   |     <meta charset="UTF-8">
my-web-app   | 172.20.0.3 - - [24/Nov/2025:11:15:30 +0000] "GET / HTTP/1.1" 200 615
web-tester   | Жду 10 секунд...

Что происходит:

Чтобы остановить: Нажмите Ctrl+C

Шаг 3: Запуск в фоновом режиме

docker compose up -d

Зачем это нужно: Запустить контейнеры в фоне, освободив терминал.

Ожидаемый результат:

[+] Running 2/2
 ✔ Container my-web-app  Started
 ✔ Container web-tester  Started

Шаг 4: Просмотр логов

# Логи всех сервисов
docker compose logs

# Логи в реальном времени
docker compose logs -f

# Логи только web сервиса
docker compose logs web

# Последние 20 строк логов
docker compose logs --tail=20

Зачем это нужно: Посмотреть, что происходит в контейнерах.

Чтобы выйти из режима реального времени: Нажмите Ctrl+C

Шаг 5: Проверка статуса сервисов

docker compose ps

Ожидаемый результат:

NAME          IMAGE        COMMAND                  STATUS         PORTS
my-web-app    devops:1.0   "/docker-entrypoint.…"   Up 2 minutes   0.0.0.0:8080->80/tcp
web-tester    alpine       "sh -c 'apk add --no…"   Up 2 minutes

Шаг 6: Остановка всех сервисов

docker compose down

Зачем это нужно: Остановить и удалить все контейнеры, созданные Docker Compose.

Ожидаемый результат:

[+] Running 2/2
 ✔ Container web-tester  Removed
 ✔ Container my-web-app  Removed
 ✔ Network my-first-docker-project_default  Removed

Что произошло: Docker Compose остановил контейнеры, удалил их и удалил сеть, которую создал для их связи.

Задание 5: Работа с томами (volumes)

Цель

Понять, как сохранять данные вне контейнера.

Шаги

Шаг 1: Создание директории для данных

# Создаём папку для HTML-файлов
mkdir html-files

# Копируем наш index.html туда
cp index.html html-files/

Зачем это нужно: Подготовить данные, которые мы будем монтировать в контейнер.

Шаг 2: Запуск контейнера с примонтированной директорией

# Для Linux/Mac:
docker run -d -p 8080:80 \
  -v $(pwd)/html-files:/usr/share/nginx/html \
  --name nginx-with-volume \
  nginx:1.27.3

# Для Windows PowerShell:
docker run -d -p 8080:80 -v ${PWD}/html-files:/usr/share/nginx/html --name nginx-with-volume nginx:1.27.3

Расшифровка:

Ожидаемый результат: Контейнер запущен, и nginx читает файлы из нашей папки.

Шаг 3: Изменение файла без пересборки образа

# Отредактируйте файл html-files/index.html
# Например, измените текст "Версия: 1.0" на "Версия: 2.0 (без пересборки!)"

# Для Linux/Mac можно использовать sed:
sed -i 's/Версия: 1.0/Версия: 2.0 (без пересборки!)/' html-files/index.html

Для Windows: Откройте файл html-files/index.html в блокноте и измените текст вручную.

Зачем это нужно: Продемонстрировать, что изменения файлов сразу видны в контейнере.

Шаг 4: Проверка изменений

Обновите страницу в браузере: http://localhost:8080

Ожидаемый результат: Вы сразу увидите изменённый текст БЕЗ перезапуска контейнера!

Что произошло: Контейнер читает файлы напрямую с вашего компьютера. Это удобно для разработки — не нужно каждый раз пересобирать образ.

Шаг 5: Очистка

docker stop nginx-with-volume
docker rm nginx-with-volume

Полезные команды для повседневной работы

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

# Просмотр запущенных контейнеров
docker ps

# Просмотр ВСЕХ контейнеров (включая остановленные)
docker ps -a

# Остановка контейнера
docker stop <имя_или_id>

# Запуск остановленного контейнера
docker start <имя_или_id>

# Удаление контейнера
docker rm <имя_или_id>

# Удаление всех остановленных контейнеров
docker container prune

Управление образами

# Список образов
docker images

# Удаление образа
docker rmi <имя_образа:тег>

# Удаление неиспользуемых образов
docker image prune

# Просмотр истории слоёв образа
docker history <имя_образа>

Логи и отладка

# Просмотр логов
docker logs <имя_контейнера>

# Логи в реальном времени
docker logs -f <имя_контейнера>

# Последние 50 строк логов
docker logs --tail=50 <имя_контейнера>

# Выполнение команды внутри контейнера
docker exec -it <имя_контейнера> bash

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

# Информация о контейнере
docker inspect <имя_контейнера>

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

# Удалить всё неиспользуемое (контейнеры, образы, сети, кэш)
docker system prune -a

# Просмотр занимаемого места
docker system df