Docker з Flask та Postgres

Сьогодні ми навчимося використовувати Postgres разом із Flask як сервіси за допомогою Docker Compose. Ми використовуватимемо це для контейнеризації додатка Flask і бази даних Postgres як єдиного сервісного блоку та відкриття порту додатка Flask для взаємодії з запитами користувача.

Давайте розглянемо кроки:

Спочатку потрібно переконатися, що Docker встановлений на вашій системі.

Створимо віртуальне середовище:

python3 -m venv env  
source env/bin/activate

Тепер створимо файл requirements.txt:

psycopg2-binary  
Flask

Встановимо всі залежності за допомогою:

pip install -r requirements.txt

Спочатку ми створимо простий додаток Flask для простого маршруту:

app = Flask(__name__)  
@app.route("/")  
def home():  
 return "Hello world"  
if __name__ == "__main__":  
 app.run()

Це найпростіша форма додатка Flask.

Далі ми створимо файл script.py, який буде завантажувати та вставляти дані до бази даних, а також інший для відображення всіх даних, що зберігаються в базі. Нижче наведено простий приклад файлу script.py:

def insert_val(cursor, datafile):  
 CREATE_TABLE_QUERY = """  
 CREATE TABLE IF NOT EXISTS sample_table (  
 id SERIAL PRIMARY KEY,  
 NAME VARCHAR(50),  
 DEPARTMENT VARCHAR(50)  
 )"""  
 cursor.execute(CREATE_TABLE_QUERY)  
 name = datafile.get("name")  
 department = datafile.get("department")  
 INSERT_QUERY = """  
 INSERT INTO sample_table (NAME, DEPARTMENT) VALUES (%s, %s)  
 """  
 cursor.execute(INSERT_QUERY, (name, department))  


def show_all_data(cursor):  
 SHOW_QUERY = """SELECT * FROM sample_table"""  
 cursor.execute(SHOW_QUERY)  
 rows = cursor.fetchall()  
 column_names = [desc[0] for desc in cursor.description]  
 # Форматуємо результат як список словників  
 result = [dict(zip(column_names, row)) for row in rows]  
 return result

Тепер ми створимо кінцеві точки для вставки даних і отримання всіх даних з бази.

@app.route("/")  
def home():  
 return "All good!!!"  

@app.route("/insert-data", methods=["POST"])  
def add_data():  
 try:  
 conn = psycopg2.connect(**config)  
 cursor = conn.cursor()  
 data = request.get_json()  
 if data is None:  
 return jsonify({"error": "Missing JSON in request"})  
 insert_val(cursor, data)  
 conn.commit()  
 return jsonify({"message": "All good"}), 200  
 except Exception as e:  
 raise jsonify({"error": str(e)})  
 finally:  
 conn.close()  

@app.route("/show-all")  
def show_data():  
 try:  
 conn = psycopg2.connect(**config)  
 cursor = conn.cursor()  
 result = show_all_data(cursor)  
 return jsonify(result), 200  
 except Exception as e:  
 raise jsonify({"error": str(e)})  
 finally:  
 conn.close()

Є змінна config (насправді це словник), яка буде пояснена на наступному етапі.

У методі add_data встановлюється з’єднання з сервером Postgres за допомогою параметрів із файлу config. Дані потім парсяться в об'єкт JSON і вставляються до бази даних за допомогою методу insert_val, зміни фіксуються, і в кінці з’єднання закривається. Метод show_data використовується для підключення до бази даних за допомогою параметрів config, а результат отримується за допомогою методу show_all_data і в кінці з’єднання закривається.

На наступному етапі ми контейнеризуємо додаток Flask, створивши Dockerfile. Нижче наведено визначення Dockerfile з поясненням:

# Використовуємо базовий образ Python і на ньому будемо будувати docker-образ  
FROM python:3.10  
# Це буде робоча директорія  
WORKDIR /app  
## Ось файли, необхідні для створення docker-образа

## Flask app містить необхідні кінцеві точки API  
## Файл script містить SQL-запити для вставки та відображення даних  
## Requirements.txt міститиме необхідні бібліотеки  
COPY flaskapp.py /app/  
COPY script.py /app/  
COPY requirements.txt /app/  
## Це встановить необхідні бібліотеки  
RUN pip install -r /app/requirements.txt  
## Це відкриє порт 5000  
EXPOSE 5000  
## Це запустить додаток flask  
CMD ["python3", "/app/flaskapp.py"]

На наступному кроці ми визначимо файл docker-compose.yml, який побудує Docker-образ та створить Flask-додаток і базу даних Postgres як сервіси.

services: <←- Це визначає сервіси ("web" для Flask-додатка і "db" для бази даних Postgres).  
 web:  
 build: <←- Це дозволяє отримати доступ до побудови образа і використовуватиме Dockerfile, який знаходиться в поточній директорії  
 context: .  
 dockerfile: Dockerfile  
 ports: <←- Визначаємо відображення портів (формат: машина_порт : порт_контейнера)  
 - "5000:5000"  
 depends_on: <←- Це забезпечує, що сервіс "db" буде побудований перед сервісом "web"  
 - db  
 db:  
 image: postgres:16 <←- Це визначає образ бази даних і її версію  
 container_name: postgres-container  
 environment: <←- Це містить змінні середовища для контейнера Postgres  
 POSTGRES_PASSWORD: postgres  
 POSTGRES_USER: postgres  
 POSTGRES_DB: postgres

Постійний контейнер бази даних Postgres не створюється тут, але його можна створити, звернувшись до документації:

https://medium.com/codex/how-to-persist-and-backup-data-of-a-postgresql-docker-container-9fe269ff4334

Давайте подивимося на конфігураційний файл для підключення бази даних до Flask-додатка;

config = {  
"dbname": "postgres",  
"user": "postgres",  
"password": "postgres",  
"host": "postgres-container",  
"port": 5432  
}

Спробуйте провести паралель із файлом docker-compose, під сервісом "db", де зазначені ім’я користувача, пароль та інші облікові дані, і ці ж дані мають бути вказані тут. Інші деталі конфігурації можна додавати за потреби.

Тепер давайте побудуємо контейнер Flask і контейнер Postgres як сервіси, використовуючи Docker Compose:

  1. sudo docker compose up -d

Це створить журнали побудови обох контейнерів у фоновому режимі.

pic

Створення сервісів за допомогою docker-compose

2. Sudo docker compose logs db

Це створить журнали для побудови бази даних.

pic

Перевірка журналів docker compose для сервісу db

3. sudo docker compose logs web

Це створить журнали для побудови Flask-додатка.

pic

Перевірка журналів docker compose для сервісу web

Тепер ми вставимо дані в таблицю і відобразимо всі дані, що містяться в базі.

curl -X POST http://localhost:5000/insert-data -H "Content-Type: application/json" -d '{"name": "John Doe", "department": "IT"}'

Цей запит буде використовуватися для вставки даних.

curl http://localhost:5000/show-all

Цей запит буде використовуватися для відображення всіх даних, що є в базі даних.

pic

Вставка та відображення даних з бази

Після всіх операцій видаліть Docker-сервіси за допомогою:

sudo docker compose down

Також ви можете перевірити всі контейнера, що працюють після використання docker compose up, за допомогою:

sudo docker ps -a

Посилання на вихідний код можна знайти тут: https://github.com/MrPotato-00/docker-flask

Більш стійкий підхід може бути застосований для обробки винятків бази даних, які можуть виникнути.

Якщо у вас є пропозиції або відгуки, пишіть у коментарях.

Дякую.

Перекладено з: Docker with Flask and Postgres

Leave a Reply

Your email address will not be published. Required fields are marked *