Цель лабораторной: собрать из исходного кода и запустить в докере рабочее приложение с базой данных (любое опенсорс - Java, python/django/flask, golang).
- Образ должен быть легковесным
- Использовать базовые легковесные образы - alpine
- Вся конфигурация приложения должна быть через переменные окружения
- Статика (зависимости) должна быть внешним томом
volume
- Создать файл
docker-compose
для старта и сборки - В
docker-compose
нужно использовать базу данных (postgresql,mysql,mongodb etc.) - При старте приложения должно быть учтено выполнение автоматических миграций
- Контейнер должен запускаться от непривилегированного пользователя
- После установки всех нужных утилит, должен очищаться кеш.
Исаев Эльшад 2383, Соц Екатерина 2384
Для выполнения лабораторной работы было выбрано простое веб-приложения, работающего на фреймворке Flask с использованием ORM Peewee. Данное приложение работает в связке с базой данных PostgreSQL. Такой выбор обоснован написанием данного приложения в рамках другой учебной дисциплины.
app/
├── src/
│ ├── core/
│ │ ├── __init__.py
│ │ ├── db.py
│ │ ├── faker_seed.py
│ │ ├── models.py
│ │ ├── utils.py
│ ├── web.py
├── .env
├── docker-compose.yml
├── Dockerfile
└── requirements.txt
Docker-образы — это шаблоны для создания контейнеров. Легковесные образы уменьшают объем загружаемых данных и сокращают время сборки.
Alpine Linux — это минималистичная дистрибуция Linux, которая занимает мало места и предназначена для выполнения контейнеризированных приложений. Ее основное преимущество — уменьшение размеров Docker-образов и повышение безопасности, так как меньше компонентов означает меньше возможных уязвимостей. Были выбраны python:3.11-alpine для приложения и postgres:15-alpine для базы данных. Оба образа являются легковесными и обеспечивают оптимальную работу.
Все переменные окружения базы данных (DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD, DATABASE_HOST, DATABASE_PORT) передаются через .env файл и используются в docker-compose.yml. В приложении же эти переменные подхватываются через os.getenv().
Контейнеры в Docker являются эфемерными, то есть при их остановке или удалении все данные, которые были созданы внутри контейнера, теряются.
Docker Volumes используются для хранения данных вне контейнера. Это полезно для сохранения данных между перезапусками контейнера, а также обеспечения совместного использования данных между контейнерами.
В docker-compose.yml определен том для базы данных pg_data:/var/lib/postgresql/data.
docker-compose.yml — это конфигурационный файл, позволяющий описывать и управлять многоконтейнерными приложениями. С его помощью можно автоматически запускать несколько сервисов (в данной работе: приложение + база данных), а также указывать зависимости между сервисами и задавать переменные окружения, монтирование томов и проброс портов.
Контейнеризация баз данных позволяет легко настраивать окружение без необходимости ручной установки СУБД. В данной работы была выбрана PostgreSQL.
Миграции — это процесс обновления структуры базы данных в соответствии с изменениями в моделях приложения. Автоматическое выполнение миграций при запуске контейнера гарантирует, что база данных всегда будет синхронизирована с текущей версией приложения. В Dockerfile миграции запускаются через скрипт, гарантирующий, что структура базы данных будет обновляться автоматически.
Запуск контейнеров от имени непривилегированного пользователя улучшает безопасность. Так, при получении доступа к контейнеру, будет невозможно выйти за его пределы для атаки на хост-систему.
В Dockerfile создается пользователь appuser, и контейнер запускается от его имени. Это соответствует требованиям безопасности.
Во время установки пакетов или сборки приложений в контейнере создаются временные файлы, которые увеличивают размер образа. Очистка кеша после установки минимизирует размер итогового образа.
В работе используется опция --no-cache-dir для очистки кеша pip, а также удаляется директория кеша вручную.
Dockerfile
# легковесный образ Python
FROM python:3.11-alpine
# рабочая директорию
WORKDIR /.
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt && \
rm -rf /root/.cache/pip
COPY . .
# пользователь без привилегий
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
# переменные окружения
ENV FLASK_APP=src.web
ENV FLASK_RUN_HOST=0.0.0.0
# миграции, заполнение и запуск приложения
CMD ["sh", "-c", "python -m src.core.utils migrate && python -m src.core.faker_seed && flask run"]
docker-compose.yml
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "5000:5000"
volumes:
- .:/app
environment:
- DATABASE_NAME=${DATABASE_NAME}
- DATABASE_USER=${DATABASE_USER}
- DATABASE_PASSWORD=${DATABASE_PASSWORD}
- DATABASE_HOST=db
- DATABASE_PORT=${DATABASE_PORT}
depends_on:
- db
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: ${DATABASE_NAME}
POSTGRES_USER: ${DATABASE_USER}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
volumes:
- pg_data:/var/lib/postgresql/data
volumes:
pg_data:
.env
DATABASE_NAME=lab4
DATABASE_USER=lab4
DATABASE_PASSWORD=1221
DATABASE_PORT=5432
- Сборка и запуск контейнеров:
docker-compose up --build
- Сервер создается на localhost:5000:
http://localhost:5000/