Новогодняя задача: помогите Тирексу поздравить коллег - Академия Selectel

Новогодняя задача: помогите Тирексу поздравить коллег

Владислав Рябчевский
Владислав Рябчевский DevOps-инженер
22 декабря 2025

Самая новогодняя задача, которая позволит проверить свои скиллы в контейнеризации и сетях, а заодно — креативно поздравить коллег с Новым годом.

Изображение записи

Условие

Программист Тирекс написал праздничное веб-приложение с обратным отсчетом до Нового года и хочет поздравить им всех коллег. Приложение уже собрано: в директории web находятся готовые статические артефакты (HTML, JavaScript и изображения). У Тирекса есть TLS-сертификат и приватный ключ, и он хочет, чтобы приложение работало по HTTPS.

Задача

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

Создайте конфигурацию nginx, которая:

  • слушает порт 80 и выполняет 301-редирект на HTTPS (https://$host$request_uri);
  • слушает порт 443 с включенным SSL;
  • использует сертификат /etc/nginx/ssl/cert.pem и ключ /etc/nginx/ssl/key.pem;
  • отдает статические файлы из /usr/share/nginx/html по пути /.

Напишите Dockerfile, который:

  • копирует в  контейнер конфигурацию nginx и артефакты приложения
  • создает пустую директорию /etc/nginx/ssl (для монтирования сертификатов при запуске);
  • использует легкий образ (например, nginx:alpine).

При запуске контейнера должны быть опубликованы порты 80 и 443.

Бонусная задача

Добавьте docker-compose.yml файл, чтобы запускать приложение одной короткой командой из папки с сертификатами.

Решение

Перед решением задачи рекомендуем ознакомиться со следующими статьями:

Что такое Docker,

Как настроить nginx.

Решением подобных кейсов обычно занимается DevOps-инженер. Это специалист, который автоматизирует и синхронизирует весь цикл разработки ПО от кода до релиза. Он отвечает за непрерывную интеграцию и доставку (CI/CD), управление инфраструктурой (IaC), мониторинг, масштабирование и обеспечение надежной работы продукта.

Предложенные примеры команд выполняются в Linux и MacOS. Для создания контейнера в Windows процесс похож, но отличаются команды генерации сертификата и редактирования файлов.

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


      mkdir -p happy/app 
tar -xzvf newyear_countdown_web.tar.gz -C happy/app

Далее перейдем в папку с проектом. В данном примере — happy. Создадим в ней необходимые дополнительные директории: для файла конфигурации nginx и для сертификатов.


      mkdir ssl
mkdir nginx

Создадим сертификат для локальной отладки приложения:


      openssl req -x509 -nodes -days 30 -newkey rsa:2048 \
  -keyout ssl/key.pem \
  -out ssl/cert.pem \
  -subj "/C=RU/ST=SPb/L=city/O=MyTask/CN=$(hostname)"

Далее создадим файл nginx/default.conf. Это можно сделать как в редакторе кода, так и открыв текстовый редактор nano, например, командой nano ./nginx/default.conf.  

В файле конфигурации требуется добавить два блока server. Первый обрабатывает запросы по незащищенному соединению и возвращает код HTTP 301 — постоянный редирект.


      server {
    listen 80;
    return 301 https://$host$request_uri;
}

Следующий блок server уже обеспечивает безопасное соединение. Он использует ранее созданные сертификат и ключ, а также указывает браузеру использовать безопасные протоколы TLS версии 1.2 и выше. Внутри этого блока прописан раздел location — он определяет, как веб-сервер будет отвечать на запросы к сайту (какую страницу отдавать при обращении по доменному имени). Здесь указывается путь к статическим файлам, задается главная страница index.html, а также правило для случая, когда запрашиваемый файл не найден — возвращается ошибка 404.


      server {
    listen 443 ssl;

    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ =404;
    }
}

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


      FROM nginx:alpine

# Копируем статику
COPY app/ /usr/share/nginx/html/

# Копируем конфигурацию
COPY nginx/default.conf /etc/nginx/conf.d/default.conf

# Создаём папку для SSL
RUN mkdir -p /etc/nginx/ssl

# Открываем порты
EXPOSE 80 443

Теперь создадим сам контейнер и запустим его. Для этого убедимся в правильном составе файлов и папок:


      tree -L 2
.
├── Dockerfile
├── app
│   ├── assets
│   ├── ...
│   └── version.json
├── nginx
│   └── default.conf
└── ssl
    ├── cert.pem
    └── key.pem

И выполним сборку и просмотр существующих образов:


      docker build -t countdown-app . 
docker images

Будет примерно следующий вывод (IMAGE ID уникальный для каждой сборки):

Вывод.

Далее можно выполнить запуск. С помощью флага -d мы позволяем контейнеру работать «в фоне», флаг --name задает имя приложению для удобного отслеживания. При помощи -p указывается, какими портами будет «светить» этот контейнер приложения (в данном примере — 80 и 443). Флаг -v отвечает за монтирование директории ssl в режиме ro = read only.


      docker run -d \
    --name countdown \
    -p 80:80 \
    -p 443:443 \
    -v "$(pwd)/ssl:/etc/nginx/ssl:ro" \
    countdown-app

С помощью команды docker ps можете убедиться в корректной работе.

А как убедиться в корректной работе контейнера? Достаточно в той же консоли ввести curl localhost:80 -v - обращение к localhost по порту 80. Вывод будет примерно следующим:


      ...
< HTTP/1.1 301 Moved Permanently
...
< Location: https://localhost/
< 
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.29.4</center>
</body>
</html>

Наше приложение полностью корректно говорит браузеру, что оно перемещено на https://localhost/ (т. е. добавлен префикс https). Однако при попытке обратиться по curl https://localhost мы получим сообщение: «curl: (60) SSL certificate problem: self signed certificate». Для проверки работоспособности страницы откройте в браузере https://localhost и согласитесь с небезопасным подключением. После этого веб-страница откроется.

Картинка с Тирексом и елочкой, которую вы увидите, если правильно выполните задание.

Дополнительно можно прописать docker-compose файл. Он позволяет запускать одно или несколько приложений и их экземпляров всего общей короткой командой. Для этого создайте файл docker-compose.yaml следующего содержания:


      version: '3.8'

services:
  countdown-app:
    build: .
    ports:
      - "80:80"
      - "443:443"
    volumes:
      # Монтируем локальную папку с сертификатами в контейнер
      - ./ssl:/etc/nginx/ssl:ro

Здесь указано создание сервиса countdown-app. При запуске дана инструкция «собрать все в текущей директории» (т. е. Dockerfile), выведены порты 80 и 443 и подключены директории с сертификатами.