From 98a1b79293d0156ef04a5b6617bcc906359f5f48 Mon Sep 17 00:00:00 2001 From: Igor Ilic <30923996+dexters1@users.noreply.github.com> Date: Wed, 23 Apr 2025 21:11:16 +0200 Subject: [PATCH] fix: run cognee in Docker [COG-1961] (#775) ## Description Resolve issue with .venv being broken when using docker compose with Cognee ## DCO Affirmation I affirm that all code in every commit of this pull request conforms to the terms of the Topoteretes Developer Certificate of Origin. --------- Co-authored-by: Boris Arzentar --- .github/workflows/dockerhub-mcp.yml | 3 +- Dockerfile | 2 +- .../versions/482cd6517ce4_add_default_user.py | 28 +++++++++++++ .../8057ae7329c2_initial_migration.py | 27 ++++++++++++ cognee-mcp/Dockerfile | 14 +++++-- cognee-mcp/README.md | 19 +++++++++ cognee-mcp/entrypoint.sh | 41 +++++++++++++++++++ cognee-mcp/src/server.py | 4 +- docker-compose.yml | 10 ++--- 9 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 alembic/versions/482cd6517ce4_add_default_user.py create mode 100644 alembic/versions/8057ae7329c2_initial_migration.py create mode 100644 cognee-mcp/entrypoint.sh diff --git a/.github/workflows/dockerhub-mcp.yml b/.github/workflows/dockerhub-mcp.yml index 7223db0b3..3d4ef4fe1 100644 --- a/.github/workflows/dockerhub-mcp.yml +++ b/.github/workflows/dockerhub-mcp.yml @@ -36,9 +36,10 @@ jobs: id: build uses: docker/build-push-action@v5 with: - context: cognee-mcp + context: . platforms: linux/amd64,linux/arm64 push: true + file: cognee-mcp/Dockerfile tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=cognee/cognee-mcp:buildcache diff --git a/Dockerfile b/Dockerfile index cc9a5cbcd..54f110f1e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ ENV DEBUG=${DEBUG} ENV PIP_NO_CACHE_DIR=true ENV PATH="${PATH}:/root/.poetry/bin" -RUN apt-get update && apt-get install +RUN apt-get update RUN apt-get install -y \ gcc \ diff --git a/alembic/versions/482cd6517ce4_add_default_user.py b/alembic/versions/482cd6517ce4_add_default_user.py new file mode 100644 index 000000000..92429e1e4 --- /dev/null +++ b/alembic/versions/482cd6517ce4_add_default_user.py @@ -0,0 +1,28 @@ +"""Add default user + +Revision ID: 482cd6517ce4 +Revises: 8057ae7329c2 +Create Date: 2024-10-16 22:17:18.634638 + +""" + +from typing import Sequence, Union + +from sqlalchemy.util import await_only + +from cognee.modules.users.methods import create_default_user, delete_user + + +# revision identifiers, used by Alembic. +revision: str = "482cd6517ce4" +down_revision: Union[str, None] = "8057ae7329c2" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = "8057ae7329c2" + + +def upgrade() -> None: + await_only(create_default_user()) + + +def downgrade() -> None: + await_only(delete_user("default_user@example.com")) diff --git a/alembic/versions/8057ae7329c2_initial_migration.py b/alembic/versions/8057ae7329c2_initial_migration.py new file mode 100644 index 000000000..48e795327 --- /dev/null +++ b/alembic/versions/8057ae7329c2_initial_migration.py @@ -0,0 +1,27 @@ +"""Initial migration + +Revision ID: 8057ae7329c2 +Revises: +Create Date: 2024-10-02 12:55:20.989372 + +""" + +from typing import Sequence, Union +from sqlalchemy.util import await_only +from cognee.infrastructure.databases.relational import get_relational_engine + +# revision identifiers, used by Alembic. +revision: str = "8057ae7329c2" +down_revision: Union[str, None] = None +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + db_engine = get_relational_engine() + await_only(db_engine.create_database()) + + +def downgrade() -> None: + db_engine = get_relational_engine() + await_only(db_engine.delete_database()) diff --git a/cognee-mcp/Dockerfile b/cognee-mcp/Dockerfile index f7a56b8a5..06ce4ec06 100644 --- a/cognee-mcp/Dockerfile +++ b/cognee-mcp/Dockerfile @@ -22,7 +22,7 @@ RUN apt-get update && apt-get install -y \ libpq-dev # Copy pyproject.toml and lockfile first for better caching -COPY pyproject.toml uv.lock ./ +COPY ./cognee-mcp/pyproject.toml ./cognee-mcp/uv.lock ./cognee-mcp/entrypoint.sh ./ # Install the project's dependencies using the lockfile and settings RUN --mount=type=cache,target=/root/.cache/uv \ @@ -31,19 +31,25 @@ RUN --mount=type=cache,target=/root/.cache/uv \ # Copy .env file first if it exists (for environment variables) COPY .env* /app/ +# Copy Alembic configuration +COPY alembic.ini /app/alembic.ini +COPY alembic/ /app/alembic + # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching -COPY . /app +COPY ./cognee-mcp /app RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-dev --no-editable FROM python:3.12-slim-bookworm WORKDIR /app - + COPY --from=uv /root/.local /root/.local COPY --from=uv /app /app +RUN chmod +x /app/entrypoint.sh + # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" @@ -54,4 +60,4 @@ ENV PYTHONPATH=/app # Use the application name from pyproject.toml for normal operation # For testing, we'll override this with a direct command -ENTRYPOINT ["cognee"] +ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/cognee-mcp/README.md b/cognee-mcp/README.md index fa8888f29..16cde91c0 100644 --- a/cognee-mcp/README.md +++ b/cognee-mcp/README.md @@ -84,3 +84,22 @@ To apply new changes while developing cognee you need to do: 1. `poetry lock` in cognee folder 2. `uv sync --dev --all-extras --reinstall` 3. `mcp dev src/server.py` + +### Development +In order to use local cognee build, run in root of the cognee repo: +```bash +poetry build -o ./cognee-mcp/sources +``` +After the build process is done, change the cognee library dependency inside the `cognee-mcp/pyproject.toml` from +```toml +cognee[postgres,codegraph,gemini,huggingface]==0.1.38 +``` +to +```toml +cognee[postgres,codegraph,gemini,huggingface] +``` +After that add the following snippet to the same file (`cognee-mcp/pyproject.toml`). +```toml +[tool.uv.sources] +cognee = { path = "sources/cognee-0.1.38-py3-none-any.whl" } +``` diff --git a/cognee-mcp/entrypoint.sh b/cognee-mcp/entrypoint.sh new file mode 100644 index 000000000..2c14518fc --- /dev/null +++ b/cognee-mcp/entrypoint.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +set -e # Exit on error +echo "Debug mode: $DEBUG" +echo "Environment: $ENVIRONMENT" + +# Run Alembic migrations with proper error handling. +# Note on UserAlreadyExists error handling: +# During database migrations, we attempt to create a default user. If this user +# already exists (e.g., from a previous deployment or migration), it's not a +# critical error and shouldn't prevent the application from starting. This is +# different from other migration errors which could indicate database schema +# inconsistencies and should cause the startup to fail. This check allows for +# smooth redeployments and container restarts while maintaining data integrity. +echo "Running database migrations..." +MIGRATION_OUTPUT=$(uv run alembic upgrade head 2>&1) || { + if [[ $MIGRATION_OUTPUT == *"UserAlreadyExists"* ]] || [[ $MIGRATION_OUTPUT == *"User default_user@example.com already exists"* ]]; then + echo "Warning: Default user already exists, continuing startup..." + else + echo "Migration failed with unexpected error:" + echo "$MIGRATION_OUTPUT" + exit 1 + fi +} + +echo "Starting Cognee MCP Server" + +# Add startup delay to ensure DB is ready +sleep 2 + +# Modified Gunicorn startup with error handling +if [ "$ENVIRONMENT" = "dev" ] || [ "$ENVIRONMENT" = "local" ]; then + if [ "$DEBUG" = "true" ]; then + echo "Waiting for the debugger to attach..." + exec python -m debugpy --wait-for-client --listen 0.0.0.0:5678 -m cognee + else + exec cognee + fi +else + exec cognee +fi diff --git a/cognee-mcp/src/server.py b/cognee-mcp/src/server.py index f4c9cc142..6340906d6 100755 --- a/cognee-mcp/src/server.py +++ b/cognee-mcp/src/server.py @@ -36,11 +36,11 @@ async def list_tools() -> list[types.Tool]: }, "graph_model_file": { "type": "string", - "description": "The path to the graph model file", + "description": "The path to the graph model file (Optional)", }, "graph_model_name": { "type": "string", - "description": "The name of the graph model", + "description": "The name of the graph model (Optional)", }, }, "required": ["text"], diff --git a/docker-compose.yml b/docker-compose.yml index 0e5195900..91e3291b7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,8 +7,8 @@ services: context: . dockerfile: Dockerfile volumes: - - .:/app - - /app/cognee-frontend/ # Ignore frontend code + - ./cognee:/app/cognee + - .env:/app/.env environment: - DEBUG=false # Change to true if debugging - HOST=0.0.0.0 @@ -26,10 +26,8 @@ services: cpus: "4.0" memory: 8GB -# NOTE: Frontend is a work in progress and is not intended to be used by users yet. -# If you want to use Cognee with a UI environment you can run the cognee-gui.py script or -# integrate the Cognee MCP Server to Cursor / Claude Desktop / Visual Studio Code ( through Cline/Roo ) - + # NOTE: Frontend is a work in progress and supports minimum amount of features required to be functional. + # If you want to use Cognee with a UI environment you can integrate the Cognee MCP Server into Cursor / Claude Desktop / Visual Studio Code (through Cline/Roo) frontend: container_name: frontend profiles: