# Лабораторная работа 3. Вариант 5. ### Как запустить В директории с файлом `docker-compose.yaml` выполнить команду: ``` docker-compose up -d ``` Это запустит `docker-compose`, который создаст контейнер и развернет в нем 3 контейнера. ### Файловая иерархия ``` basharin_sevastyan_lab_3/ |-- user_service/ | |-- Dockerfile | |-- requirements.txt | |-- user_service.py |-- order_service/ | |-- Dockerfile | |-- requirements.txt | |-- order_service.py |-- nginx/ | |-- Dockerfile | |-- nginx.conf |-- docker-compose.yml ``` ### Описание работы #### Описание предметной области Объекты микросервисов буду связаны следующим образом: ``` user (single) <- order (many) ``` #### Синхронный обмен сообщениями `order_service` будет отправлять http-запрос на `user_service` при определенных crud операциях. Например, при создании экземпляра `order`, будет отправлен запрос на добавление `order` к определенному `user`: ```python # CREATE @app.route('/add_order/_', methods=['POST']) def create_order(user_id, product): order = {'id': len(orders) + 1, 'user_id': user_id, 'product': product, 'action': 'create'} orders.append(order) # Отправка сообщения о создании заказа requests.post("http://user-service:5001/event", json=order) return jsonify(order) ``` В `user_service` этот запрос обрабатывается следующим образом: ```python @app.route('/event', methods=['POST']) def event(): print('получено сообщение') data = request.get_json() print(data) user_id = data.get('user_id') if data['action'] == 'create': # Создание заказа у пользователя user = next((user for user in users if user['id'] == user_id), None) if user: order_id = len(user.get('orders', [])) + 1 order = {'id': order_id, 'product': data['product']} user.setdefault('orders', []).append(order) print(f"Order created for user {user_id}: {order}") else: print(f"User not found for order creation: {user_id}") elif data['action'] == 'update': # Обновление заказа у пользователя user = next((user for user in users if user['id'] == user_id), None) if user: order_id = data.get('id') order = next((order for order in user['orders'] if order['id'] == order_id), None) if order: order['product'] = data['product'] print(f"Order updated for user {user_id}: {order}") else: print(f"Order not found for update: {order_id}") else: print(f"User not found for order update: {user_id}") elif data['action'] == 'delete': # Удаление заказа у пользователя user = next((user for user in users if user['id'] == user_id), None) if user: order_id = user.get('id') user['orders'] = [order for order in user.get('orders', []) if order['id'] != order_id] print(f"Order deleted for user {user_id}: {order_id}") else: print(f"User not found for order deletion: {user_id}") return jsonify({'result': True}) ``` ### Описание docker-compose ```yaml version: '3.8' services: user-service: build: context: ./user_service ports: - "5001:5001" networks: - my_network restart: always order-service: build: context: ./order_service ports: - "5002:5002" networks: - my_network restart: always nginx: image: nginx:latest ports: - "80:80" depends_on: - user-service - order-service networks: - my_network volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf restart: always networks: my_network: driver: bridge ``` ### Dockerfile микросервисов ```dockerfile # user_service/Dockerfile FROM python:3.11 WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . /app CMD ["gunicorn", "--bind", "0.0.0.0:5001", "user_service:app"] ``` ```dockerfile # order_service/Dockerfile FROM python:3.11 WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . /app CMD ["gunicorn", "--bind", "0.0.0.0:5002", "order_service:app"] ``` ### Dockerfile nginx ```dockerfile # nginx/Dockerfile FROM nginx COPY nginx.conf /etc/nginx/nginx.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` ### Видео https://youtu.be/3-iF9xBHvCU