diff --git a/mochalov_danila_lab_3/.gitignore b/mochalov_danila_lab_3/.gitignore
new file mode 100644
index 0000000..b694934
--- /dev/null
+++ b/mochalov_danila_lab_3/.gitignore
@@ -0,0 +1 @@
+.venv
\ No newline at end of file
diff --git a/mochalov_danila_lab_3/README.md b/mochalov_danila_lab_3/README.md
new file mode 100644
index 0000000..a156c8d
--- /dev/null
+++ b/mochalov_danila_lab_3/README.md
@@ -0,0 +1,35 @@
+# Лабораторная работа №3
+#### ПИбд-42. Мочалов Данила.
+
+#### При выполнении использовал:
+- Python 3.12
+- Flask
+- requests
+- Docker
+- Docker Compose
+
+#### Задание:
+Для выполнения лабораторной работы были созданы следующие сущности: 
+##### 1. Категория. Имеет поля: 
+    - id
+    - name
+    - description
+#####  2. Услуга. Имеет поля: 
+    - id
+    - name
+    - category_id
+
+##### Каждой категории может принадлежать множество услуг.
+##### Были развернуты два сервиса - category_service и service_service, синхронно обменивающиеся сообщениями. 
+##### Сущности хранятся в оперативной памяти (без БД)
+
+#### Инструкция
+Для запуска лабораторной работы, перейдите в папку *mochalov_danila_lab_3* и выполните команду:
+```
+docker-compose up --build -d --remove-orphans
+```
+
+#### Демонстрация работы
+Доступна по [ссылке](https://drive.google.com/file/d/1-DoS7b4ArfetVDsqjGHrfVxWhvIBt_fH/view?usp=sharing)
+
+
diff --git a/mochalov_danila_lab_3/category_service/Dockerfile b/mochalov_danila_lab_3/category_service/Dockerfile
new file mode 100644
index 0000000..692acd7
--- /dev/null
+++ b/mochalov_danila_lab_3/category_service/Dockerfile
@@ -0,0 +1,11 @@
+FROM python:latest
+
+WORKDIR /app
+
+COPY requirements.txt .
+
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY category_service/category_service.py .
+
+CMD ["python", "category_service.py"]
\ No newline at end of file
diff --git a/mochalov_danila_lab_3/category_service/category_service.py b/mochalov_danila_lab_3/category_service/category_service.py
new file mode 100644
index 0000000..64cf28c
--- /dev/null
+++ b/mochalov_danila_lab_3/category_service/category_service.py
@@ -0,0 +1,102 @@
+from flask import Flask, jsonify, request
+import requests
+
+app = Flask(__name__)
+
+services_url = 'http://serviceService:20002/'
+
+class Category:
+    def __init__(self, id: int, name: str, description: str):
+        self.id = id
+        self.name = name
+        self.description = description
+
+    def to_dict(self):
+        return {
+            "id": self.id,  
+            "name": self.name,
+            "description": self.description
+        }
+
+    def to_dict_with_services(self, services: list):
+        return {
+            "id": self.id,  
+            "name": self.name,
+            "description": self.description,
+            "services": services
+        }
+
+
+categories = [
+    Category(1, 'Shooters', 'Shooter games'),
+    Category(2, 'Strategy', 'Strategy games'),
+]
+
+
+@app.route('/', methods=['GET'])
+def get_all_categories():
+    return jsonify([category.to_dict() for category in categories]), 200
+
+
+@app.route('/<int:category_id>', methods=['GET']) 
+def get_category(category_id):
+    for category in categories:
+        if category.id == category_id:  
+            return category.to_dict(), 200
+    return f'Category with id {category_id} not found', 404 
+
+
+@app.route('/info/<int:category_id>', methods=['GET']) 
+def get_category_extended(category_id):
+    for category in categories:
+        if category.id == category_id: 
+            response = requests.get(services_url + f'by-category/{category_id}') 
+            return category.to_dict_with_services(response.json()), 200
+    return f'Category with id {category_id} not found', 404  
+
+
+@app.route('/check/<int:category_id>', methods=['GET']) 
+def check_category_exists(category_id):
+    for category in categories:
+        if category.id == category_id:  
+            return '', 200
+    return '', 404
+
+
+@app.route('/', methods=['POST'])
+def create_category():
+    data = request.json
+    name = data.get('name')
+    description = data.get('description')
+    if name is None or description is None:
+        return 'Insufficient data to create a category', 400
+
+    next_id = max([c.id for c in categories]) + 1 if categories else 1 
+    new_category = Category(next_id, name, description) 
+    categories.append(new_category)
+    return jsonify(new_category.to_dict()), 201
+
+
+
+@app.route('/<int:category_id>', methods=['PUT'])  
+def update_category(category_id):
+    data = request.json
+    for category in categories:
+        if category.id == category_id: 
+            category.name = data.get('name', category.name)
+            category.description = data.get('description', category.description)
+            return jsonify(category.to_dict()), 200
+    return f'Category with id {category_id} not found', 404 
+
+
+@app.route('/<int:category_id>', methods=['DELETE'])  
+def delete_category(category_id):
+    for category in categories:
+        if category.id == category_id:  
+            categories.remove(category)
+            return 'Category deleted', 200
+    return f'Category with id {category_id} not found', 404 
+
+
+if __name__ == '__main__':
+    app.run(host='0.0.0.0', port=20001, debug=True)
\ No newline at end of file
diff --git a/mochalov_danila_lab_3/docker-compose.yaml b/mochalov_danila_lab_3/docker-compose.yaml
new file mode 100644
index 0000000..aeab821
--- /dev/null
+++ b/mochalov_danila_lab_3/docker-compose.yaml
@@ -0,0 +1,26 @@
+services:
+  category_service:
+    container_name: categoryService
+    build:
+      context: .
+      dockerfile: ./category_service/Dockerfile
+    expose:
+      - 20001
+
+  service_service:
+    container_name: serviceService
+    build:
+      context: .
+      dockerfile: ./service_service/Dockerfile
+    expose:
+      - 20002
+
+  nginx:
+    image: nginx:latest
+    ports:
+      - "80:80"
+    volumes:
+      - ./nginx.conf:/etc/nginx/nginx.conf
+    depends_on:
+      - category_service
+      - service_service
\ No newline at end of file
diff --git a/mochalov_danila_lab_3/nginx.conf b/mochalov_danila_lab_3/nginx.conf
new file mode 100644
index 0000000..20e00f6
--- /dev/null
+++ b/mochalov_danila_lab_3/nginx.conf
@@ -0,0 +1,25 @@
+events { worker_connections 1024; }
+
+http {
+    server {
+        listen      80;
+        listen      [::]:80;
+        server_name localhost;
+
+        location /categoryService/ {
+            proxy_pass http://categoryService:20001/;
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+            proxy_set_header X-Forwarded-Proto $scheme;
+        }
+
+        location /serviceService/ {
+            proxy_pass http://serviceService:20002/;
+            proxy_set_header Host $host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+            proxy_set_header X-Forwarded-Proto $scheme;
+        }
+    }
+}
\ No newline at end of file
diff --git a/mochalov_danila_lab_3/requirements.txt b/mochalov_danila_lab_3/requirements.txt
new file mode 100644
index 0000000..494909e
--- /dev/null
+++ b/mochalov_danila_lab_3/requirements.txt
@@ -0,0 +1,2 @@
+Flask==3.0.3
+requests==2.32.3
\ No newline at end of file
diff --git a/mochalov_danila_lab_3/service_service/Dockerfile b/mochalov_danila_lab_3/service_service/Dockerfile
new file mode 100644
index 0000000..119d191
--- /dev/null
+++ b/mochalov_danila_lab_3/service_service/Dockerfile
@@ -0,0 +1,11 @@
+FROM python:latest
+
+WORKDIR /app
+
+COPY requirements.txt .
+
+RUN pip install --no-cache-dir -r requirements.txt
+
+COPY service_service/service_service.py .
+
+CMD ["python", "service_service.py"]
\ No newline at end of file
diff --git a/mochalov_danila_lab_3/service_service/service_service.py b/mochalov_danila_lab_3/service_service/service_service.py
new file mode 100644
index 0000000..ced90bf
--- /dev/null
+++ b/mochalov_danila_lab_3/service_service/service_service.py
@@ -0,0 +1,111 @@
+from flask import Flask, jsonify, request
+import requests
+
+app = Flask(__name__)
+
+categories_url = 'http://categoryService:20001/'
+
+class Service:
+    def __init__(self, id: int, name: str, category_id: int):
+        self.id = id
+        self.name = name
+        self.category_id = category_id
+
+    def to_dict(self):
+        return {
+            "id": self.id,  
+            "name": self.name,
+            "category_id": self.category_id
+        }
+
+    def to_dict_with_category(self, category):
+        return {
+            "id": self.id,  
+            "name": self.name,
+            "category": category
+        }
+
+
+services = [
+    Service(1, 'CS 2', 1),
+    Service(2, 'StarCraft', 2)
+] 
+
+
+@app.route('/', methods=['GET'])
+def get_all_services():
+    return jsonify([service.to_dict() for service in services]), 200
+
+
+@app.route('/by-category/<int:category_id>', methods=['GET']) 
+def get_services_by_category(category_id):
+    services_for_category = [service.to_dict() for service in services if service.category_id == category_id]
+    return jsonify(services_for_category), 200
+
+
+@app.route('/<int:service_id>', methods=['GET'])  
+def get_service(service_id):
+    for service in services:
+        if service.id == service_id:  
+            return jsonify(service.to_dict()), 200
+    return f'Service with id {service_id} not found', 404 
+
+
+@app.route('/info/<int:service_id>', methods=['GET'])  
+def get_service_with_category(service_id):
+    for service in services:
+        if service.id == service_id: 
+            try:
+                response = requests.get(categories_url + str(service.category_id))
+                response.raise_for_status()
+                category = response.json()
+                return jsonify(service.to_dict_with_category(category)), 200
+            except requests.exceptions.RequestException as e:
+                return f"Error fetching category: {e}", 500
+
+    return f'Service with id {service_id} not found', 404  
+
+
+@app.route('/', methods=['POST'])
+def create_service():
+    data = request.json
+    name = data.get('name')
+    category_id = data.get('category_id')
+
+    try:
+        response = requests.get(categories_url + f'check/{category_id}')
+        response.raise_for_status()
+        if response.status_code == 200:
+            next_id = max([s.id for s in services]) + 1 if services else 1 
+            new_service = Service(next_id, name, category_id)  
+            services.append(new_service)
+            return jsonify(new_service.to_dict()), 201
+        else:
+            return f"Category with ID {category_id} not found", 404
+    except requests.exceptions.RequestException as e:
+        return f"Error checking category: {e}", 500
+
+
+@app.route('/<int:service_id>', methods=['PUT'])  
+def update_service(service_id):
+    data = request.json
+    for service in services:
+        if service.id == service_id:  
+            service.name = data.get('name', service.name)
+            service.category_id = data.get('category_id', service.category_id)
+            return jsonify(service.to_dict()), 200
+    return f'Service with id {service_id} not found', 404  
+
+
+
+@app.route('/<int:service_id>', methods=['DELETE'])  
+def delete_service(service_id):
+    for service in services:
+        if service.id == service_id:  
+            services.remove(service)
+            return 'Service deleted', 200
+    return f'Service with id {service_id} not found', 404  
+
+
+if __name__ == '__main__':
+    app.run(host='0.0.0.0', port=20002, debug=True)
\ No newline at end of file