Как сделать приложение в docker?

У меня есть маленькое приложение написанное на питоне и html. Мне нужно засунуть Бэк и фронт в разные контейнеры и чтобы они между собой общались. Фронт отсылает данные на бэк, бэк дает ответ. Не могу понять как составить докер файлы и докер компоуз. Вот код приложения:

from flask import Flask, render_template, request
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
import torch
import torch.nn as nn
import torch.optim as optim

app = Flask(__name__)

# Упрощенные данные
data = {
    'Площадь': [60, 75, 80, 65, 90],
    'Количество комнат': [2, 3, 2, 2, 4],
    'Этаж': [3, 5, 1, 8, 6],
    'Расстояние до центра': [10, 5, 15, 8, 20],
    'Близость к транспорту': [1, 1, 0, 1, 0],
    'Год постройки': [2010, 2005, 2015, 2012, 2018],
    'Стоимость': [3000000, 4000000, 3500000, 3200000, 4500000]
}

df = pd.DataFrame(data)

# Разделение данных на признаки (X) и целевую переменную (y) стоимость
X = df.drop('Стоимость', axis=1)
y = df['Стоимость']

# Нормализация данных с помощью sklearn
min_max_scaler = MinMaxScaler()
X_normalized = min_max_scaler.fit_transform(X)

# Преобразование данных в тензоры PyTorch
X_tensor = torch.tensor(X_normalized, dtype=torch.float32)
y_tensor = torch.tensor(y.values, dtype=torch.float32).view(-1, 1)

# Инициализация более сложной модели
input_size = X_tensor.shape[1]
hidden_size1 = 64
hidden_size2 = 32
output_size = 1

model = nn.Sequential(
    nn.Linear(input_size, hidden_size1),
    nn.ReLU(),
    nn.Linear(hidden_size1, hidden_size2),
    nn.ReLU(),
    nn.Linear(hidden_size2, output_size)
)

criterion = nn.L1Loss()  # Используем среднюю абсолютную ошибку (MAE)
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Обучение модели
num_epochs = 5000

for epoch in range(num_epochs):
    # Forward pass
    outputs = model(X_tensor)
    loss = criterion(outputs, y_tensor)

    # Backward pass и оптимизация
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if (epoch + 1) % 100 == 0:
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

# Графический интерфейс
class ApartmentPricePredictorApp:
    def __init__(self):
        self.app = Flask(__name__)

        @self.app.route('/', methods=['GET', 'POST'])
        def index():
            if request.method == 'POST':
                return self.get_prediction(request.form)

            return render_template('index.html')

        self.app.run(host='0.0.0.0', port=80)

    def get_prediction(self, form_data):
        try:
            # Получение введенных пользователем данных
            area = float(form_data['area'])
            rooms = int(form_data['rooms'])
            floor = int(form_data['floor'])
            distance_to_center = float(form_data['distance_to_center'])
            transport_proximity = int(form_data['transport_proximity'])
            year_built = int(form_data['year_built'])

            # Нормализация входных данных
            input_data = min_max_scaler.transform(
                [[area, rooms, floor, distance_to_center, transport_proximity, year_built]]
            )

            # Преобразование данных в тензор PyTorch
            input_tensor = torch.tensor(input_data, dtype=torch.float32)

            # Получение прогноза от модели
            model.eval()
            with torch.no_grad():
                output_tensor = model(input_tensor)

            # Обратное преобразование тензора в значение
            predicted_price = output_tensor.item()

            return render_template('result.html', predicted_price=predicted_price)

        except ValueError:
            return render_template('error.html')

if __name__ == '__main__':
    if __name__ == '__main__': app_instance = ApartmentPricePredictorApp()
<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Apartment Price Predictor</title>
    </head>
    <body>
        <h1>Введите данные для прогноза стоимости квартиры</h1>
        <form method="post" action="/">
            <label for="area">Площадь (кв. м):</label>
            <input type="text" name="area" required><br>
    
            <label for="rooms">Количество комнат:</label>
            <input type="text" name="rooms" required><br>
    
            <label for="floor">Этаж:</label>
            <input type="text" name="floor" required><br>
    
            <label for="distance_to_center">Расстояние до центра (км):</label>
            <input type="text" name="distance_to_center" required><br>
    
            <label for="transport_proximity">Близость к транспорту (1 - близко, 0 - нет):</label>
            <input type="text" name="transport_proximity" required><br>
    
            <label for="year_built">Год постройки:</label>
            <input type="text" name="year_built" required><br>
    
            <input type="submit" value="Получить прогноз">
        </form>
    </body>
    </html>
    <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Результат прогноза</title>
</head>
<body>
    <h1>Прогноз стоимости квартиры</h1>
    <p>{{ predicted_price }} руб.</p>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ошибка</title>
</head>
<body>
    <h1>Ошибка! Проверьте правильность введенных данных.</h1>
</body>
</html>

Ответы (0 шт):