Введение
У LITTLE HOUR есть готовое меню кафе, и для временной точки на выходных нужен такой же сайт. Одной главной страницы мало: посетителям нужны описания напитков, цены, локальные иллюстрации и часы работы. Ваша задача — доставить весь этот сайт внутри образа Docker.
Вы упакуете готовые файлы, запустите образ, затем создадите из него новый контейнер и проверите настоящий сайт. Писать код приложения и устанавливать Docker не потребуется. Достаточно базового знакомства с терминалом: Docker, пути, порты и команды объясняются по мере использования. Кафе, товары, цены и адреса вымышлены.
Выполняйте команды в Workstation, смотрите образец в Reference Menu, свой контейнер — в Your Menu, а схему окружения — в Topology. Your Menu станет доступен после запуска контейнера на шаге 2; до этого он может не отвечать. Каждое упражнение начинается независимо.
Соберите образ полного меню
На этом шаге вы разберётесь в потребностях кафе и соберёте образ со всем клиентским сайтом. Начните с Reference Menu.
Изучите путь посетителя
Главная страница представляет LITTLE HOUR. В разделе A few good favourites откройте Flat white. В описании указаны $4.00, порция и аллергены. Перейдите по Find us, прочитайте часы работы и выберите LITTLE HOUR, чтобы вернуться на главную. Эти ссылки и иллюстрации входят в поставку, а не служат необязательным украшением.

Образец уже работает на порту 8082. Он доступен даже при остановленном вашем контейнере, поэтому не доказывает, что вы доставили сайт.
Найдите файлы для поставки
Переключитесь в Workstation. Терминал начинается в /home/labex/project/cafe-menu. pwd выводит текущий каталог, ls — его содержимое:
pwd
/home/labex/project/cafe-menu
ls
Вы увидите menu, brand и notes. В menu/ находятся клиентские страницы, в brand/ — таблица стилей и иллюстрации. notes/ содержит материалы автора, которым не место в публичном меню. Не изменяйте предоставленные файлы.
Адрес сайта — это путь URL. Сервер сопоставляет /menu/flat-white.html с файлом внутри публичного каталога. Внешний исходный каталог menu/ содержит внутренний menu/ со страницами описаний. Изучите обе группы исходных файлов:
ls menu
ls brand
Среди страниц есть index.html, visit.html, 404.html и каталог описаний. Файлы оформления включают site.css и три иллюстрации .svg. SVG — формат изображений. Страницы ожидают все файлы оформления по путям /assets/ на работающем сайте.
Напишите рецепт упаковки
Docker запускает программы в контейнерах. Образ — сохранённый пакет для создания контейнера; контейнер — работающий или остановленный экземпляр образа. Docker уже установлен. Подготовленный образ menu-base:1 содержит веб-сервер Nginx и настройки отсутствующих страниц. Его публичный каталог — /usr/share/nginx/html/. Меню кафе в нём пока нет.
Dockerfile описывает сборку образа. FROM выбирает базовый образ. COPY копирует файлы в образ: первый путь — источник относительно каталога сборки, второй — назначение внутри образа. Копирование содержимого каталога в правильное место сохраняет существующие ссылки страниц. Оно не подключает работающий контейнер к исходному каталогу.
Сделайте две явные копии: страницы в публичный каталог, файлы оформления — в его подкаталог assets/. Так заметки автора останутся снаружи. База Nginx уже определяет команду запуска сервера; добавлять её не нужно.
cat > Dockerfile заменяет указанный файл следующим текстом. DOCKERFILE в кавычках начинает here-document: вставьте весь блок, включая заключительный DOCKERFILE на отдельной строке. Кавычки сохраняют буквальное содержимое. Выполните в Workstation:
cat > Dockerfile <<'DOCKERFILE'
FROM menu-base:1
COPY menu/ /usr/share/nginx/html/
COPY brand/ /usr/share/nginx/html/assets/
DOCKERFILE
cat также выводит файл. Перед сборкой прочитайте сохранённый рецепт и проверьте оба назначения:
cat Dockerfile
Соберите сохраняемый образ
docker build читает рецепт и создаёт образ. -t задаёт имя и тег: little-hour-menu — имя, 1 — выбранная метка версии. Точка в конце означает, что текущий каталог служит контекстом сборки, то есть набором доступных Docker файлов. Тег — удобная метка, а не доказательство полноты содержимого.
docker build -t little-hour-menu:1 .
Вывод зависит от версии Docker. Команда должна успешно завершиться и указать little-hour-menu:1. Если COPY не сработал, проверьте pwd, имена источников и сохранённый Dockerfile, исправьте рецепт и повторите сборку. Не подменяйте страницы и не копируйте весь проект, чтобы скрыть ошибку пути.
Теперь у вас есть сохранённый образ поставки. Контейнер меню ещё не запущен.
Опубликуйте образ как работающее меню
На этом шаге вы создадите собственный работающий контейнер и откроете его сайт. Начните в Workstation.
Подключите контейнер к порту сайта
Nginx слушает порт 80 внутри контейнера. Порт обозначает сетевую службу. Мы опубликуем его на порту 8081 экземпляра лаборатории, чтобы к нему обращался Your Menu. Образец на порту 8082 не изменится.
docker run создаёт и запускает контейнер. -d оставляет его работать в фоне, освобождая терминал. --name cafe-menu назначает имя для дальнейших команд. -p 8081:80 связывает порт 8081 лаборатории с портом 80 контейнера. Последний аргумент выбирает собранный образ. Исходный каталог и тома не монтируются:
docker run -d --name cafe-menu -p 8081:80 little-hour-menu:1
Длинная строка — ID нового контейнера; при каждом запуске он другой. Один ID не доказывает, что приложение продолжает работать. docker ps показывает запущенные контейнеры:
docker ps
Найдите cafe-menu, образ little-hour-menu:1 и сопоставление с 8081->80/tcp. Могут отображаться другие учебные контейнеры; не трогайте их.
Если имя занято, не запускайте множество копий с другими именами. Найдите свой контейнер через docker ps и продолжайте, если он правильный. Если он завершился или порты неверны, docker logs cafe-menu покажет сообщения сервера. Чтобы заменить только свой контейнер статического меню, выполните docker rm -f cafe-menu: команда остановит и удалит именно его, сохранив образ и источники.
Исправив рецепт или порт, при необходимости пересоберите образ и повторите исходный docker run. Удаляйте контейнер только для необходимой замены, а не после каждого успешного запуска.
Откройте собственную поставку
Переключитесь в Your Menu. Если открыли его до запуска контейнера, обновите страницу. Должен появиться LITTLE HOUR с полным оформлением и иллюстрациями. Эта страница приходит с порта 8081, а не из готового Reference Menu.

Откройте Flat white в A few good favourites. На странице должны быть иллюстрация, цена, порция и аллергены. Перейдите по Find us, проверьте часы и вернитесь через LITTLE HOUR в той же вкладке. Текстовая главная без оформления или сломанная иллюстрация — неполная поставка.
Откройте Topology. Теперь может появиться Menu homepage reachable. Это лишь узкое наблюдение, а не приёмка всех страниц. Далее вы проверите независимость поставки и остальные клиентские пути.
Проверьте новый контейнер и весь сайт
Вы запустите новый экземпляр образа и проверите весь клиентский опыт без зависимости от авторского каталога. Начните в Workstation.
Разделите образ и контейнер
После удаления контейнера образ остаётся сохранённым. На этом сайте нет пользовательских отправок и базы данных, поэтому замена данного контейнера не уничтожит бизнес-данные. Для приложения с состоянием это различие было бы существенно.
Удалите только cafe-menu командой замены из шага 2:
docker rm -f cafe-menu
Запустите новый экземпляр с тем же опубликованным портом:
docker run -d --name cafe-menu -p 8081:80 little-hour-menu:1
Он выведет другой ID. Вы не повторяли сборку и не монтировали авторский каталог: новый экземпляр использует файлы, уже включённые в образ.
docker inspect показывает настоящую конфигурацию контейнера. --format выбирает одно поле вместо целого объекта. Шаблон в кавычках превращает список монтирований в JSON:
docker inspect cafe-menu --format '{{json .Mounts}}'
[]
Пустой список означает отсутствие подключённых каталогов хоста и томов. Именно это нужно доказать: источники незаметно не восполняют пробелы поставки. Монтирования полезны в других ситуациях; здесь требуется автономное статическое меню.
Проверьте настоящие клиентские пути
Переключитесь в Your Menu и обновите страницу. По очереди откройте три популярных товара. Flat white стоит $4.00, Espresso — $3.00, Iced oat latte — $4.75. Каждое описание должно содержать правильную картинку и информацию. После каждого возвращайтесь через LITTLE HOUR. Откройте Find us и подтвердите будние часы 08:00–17:00. Оставайтесь в Your Menu: Reference Menu проверяет другой сервер.

Переключитесь в Workstation. HTTP — протокол запросов и ответов браузера. Успешный ответ имеет статус 200; 404 означает, что ресурс не найден. Ошибка соединения отличается: рабочий ответ сервера вообще не получен.
curl отправляет запрос. -sS скрывает прогресс, но показывает ошибки соединения. -o /dev/null отбрасывает тело ответа. -w выводит формат в кавычках: %{http_code} — статус, \n завершает строку. В Workstation адрес 127.0.0.1 обозначает этот экземпляр лаборатории; не выполняйте запросы из терминала собственного компьютера.
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8081/menu/flat-white.html
Ожидается 200. Проверка в браузере также подтвердила содержание и иллюстрацию; одного 200 с неправильной страницей недостаточно.
Заметки автора не должны быть публичными. Запросите возможный URL:
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8081/notes/launch-notes.txt
Ожидается 404. Для границы пакета это нужный результат. Curl завершается нормально, потому что мы не потребовали ошибки завершения при ошибочном HTTP-ответе. Остановка всего сайта не пройдёт проверки работающего меню.
Вернитесь в Your Menu и выберите LITTLE HOUR для перехода на главную. Обычное меню должно работать после отклонённого запроса заметок. Вы проверили и полноту клиентского содержания, и правильную реакцию на ресурс, не входящий в поставку.
Резюме
Вы собрали полный образ статического меню, опубликовали порт сервера и запустили новый контейнер без монтирования источников. Проверили реальные страницы, картинки и информацию для посещения, оставив заметки автора вне публичного сайта. Следующее самостоятельное задание переносит эти решения на пекарню с другой структурой исходников.



