diff --git a/deploy/.env.example b/deploy/.env.example index e673074061c3..a0b80bd561f4 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -1,11 +1,21 @@ DOMAIN=localhost STACK_NAME=langflow-stack -ENVIRONMENT=development TRAEFIK_PUBLIC_NETWORK=traefik-public TRAEFIK_TAG=langflow-traefik TRAEFIK_PUBLIC_TAG=traefik-public + +# Langflow backend configuration +LANGFLOW_LOG_LEVEL=debug +LANGFLOW_SUPERUSER=superuser +LANGFLOW_SUPERUSER_PASSWORD=superuser +LANGFLOW_NEW_USER_IS_ACTIVE=False + + +# Langflow frontend configuration +BACKEND_URL=http://backend:7860 + # RabbitMQ configuration RABBITMQ_DEFAULT_USER=langflow RABBITMQ_DEFAULT_PASS=langflow @@ -17,9 +27,6 @@ DB_HOST=db DB_PORT=5432 DB_NAME=langflow -# Logging configuration -LOG_LEVEL=debug - # DB configuration POSTGRES_USER=langflow POSTGRES_PASSWORD=langflow @@ -27,7 +34,8 @@ POSTGRES_DB=langflow POSTGRES_PORT=5432 # Flower configuration -LANGFLOW_CACHE_TYPE=redis +# Disable until https://github.com/langflow-ai/langflow/pull/2655 gets released +#LANGFLOW_CACHE_TYPE=redis LANGFLOW_REDIS_HOST=result_backend LANGFLOW_REDIS_PORT=6379 LANGFLOW_REDIS_DB=0 @@ -38,20 +46,7 @@ BROKER_URL=amqp://langflow:langflow@broker:5672 RESULT_BACKEND=redis://result_backend:6379/0 C_FORCE_ROOT="true" -# Frontend configuration -VITE_PROXY_TARGET=http://backend:7860/api/ -BACKEND_URL=http://backend:7860 # PGAdmin configuration PGADMIN_DEFAULT_EMAIL=admin@admin.com PGADMIN_DEFAULT_PASSWORD=admin - -# OpenAI configuration (for testing purposes) -OPENAI_API_KEY=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 - -# Superuser configuration -LANGFLOW_SUPERUSER=superuser -LANGFLOW_SUPERUSER_PASSWORD=superuser - -# New user configuration -LANGFLOW_NEW_USER_IS_ACTIVE=False \ No newline at end of file diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 000000000000..5456713c673c --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,21 @@ +# Run Langflow + + +## Docker compose +To run Langflow with Docker compose, you need to have Docker and Docker compose installed on your machine. You can install Docker and Docker compose by following the instructions on the [official Docker documentation](https://docs.docker.com/get-docker/). + +The docker-compose file uses `latest` tag; it's recommended to pull the latest version of the images before running the docker-compose file. + +```bash +docker compose pull +``` + +To start the Langflow services, run the following command: + +```bash +docker compose up +``` + +After running the command, you can access the Langflow services at the following url: http://localhost:80. + +Edit the `.env` file to change the port or other configurations. \ No newline at end of file diff --git a/deploy/docker-compose.override.yml b/deploy/docker-compose.override.yml index 1992916fbf76..0bff922993fc 100644 --- a/deploy/docker-compose.override.yml +++ b/deploy/docker-compose.override.yml @@ -1,5 +1,3 @@ -version: "3.8" - services: proxy: ports: diff --git a/deploy/docker-compose.with_tests.yml b/deploy/docker-compose.with_tests.yml deleted file mode 100644 index 82da7eb49c08..000000000000 --- a/deploy/docker-compose.with_tests.yml +++ /dev/null @@ -1,277 +0,0 @@ -version: "3.8" - -services: - proxy: - image: traefik:v3.0 - env_file: - - .env - networks: - - ${TRAEFIK_PUBLIC_NETWORK?Variable not set} - - default - volumes: - - /var/run/docker.sock:/var/run/docker.sock - command: - # Enable Docker in Traefik, so that it reads labels from Docker services - - --providers.docker - # Add a constraint to only use services with the label for this stack - # from the env var TRAEFIK_TAG - - --providers.docker.constraints=Label(`traefik.constraint-label-stack`, `${TRAEFIK_TAG?Variable not set}`) - # Do not expose all Docker services, only the ones explicitly exposed - - --providers.docker.exposedbydefault=false - # Enable the access log, with HTTP requests - - --accesslog - # Enable the Traefik log, for configurations and errors - - --log - # Enable the Dashboard and API - - --api - deploy: - placement: - constraints: - - node.role == manager - labels: - # Enable Traefik for this service, to make it available in the public network - - traefik.enable=true - # Use the traefik-public network (declared below) - - traefik.docker.network=${TRAEFIK_PUBLIC_NETWORK?Variable not set} - # Use the custom label "traefik.constraint-label=traefik-public" - # This public Traefik will only use services with this label - - traefik.constraint-label=${TRAEFIK_PUBLIC_TAG?Variable not set} - # traefik-http set up only to use the middleware to redirect to https - - traefik.http.middlewares.${STACK_NAME?Variable not set}-https-redirect.redirectscheme.scheme=https - - traefik.http.middlewares.${STACK_NAME?Variable not set}-https-redirect.redirectscheme.permanent=true - # Handle host with and without "www" to redirect to only one of them - # Uses environment variable DOMAIN - # To disable www redirection remove the Host() you want to discard, here and - # below for HTTPS - - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-http.rule=Host(`${DOMAIN?Variable not set}`) || Host(`www.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-http.entrypoints=http - # traefik-https the actual router using HTTPS - - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.rule=Host(`${DOMAIN?Variable not set}`) || Host(`www.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.entrypoints=https - - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.tls=true - # Use the "le" (Let's Encrypt) resolver created below - - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.tls.certresolver=le - # Define the port inside of the Docker service to use - - traefik.http.services.${STACK_NAME?Variable not set}-proxy.loadbalancer.server.port=80 - # Handle domain with and without "www" to redirect to only one - # To disable www redirection remove the next line - - traefik.http.middlewares.${STACK_NAME?Variable not set}-www-redirect.redirectregex.regex=^https?://(www.)?(${DOMAIN?Variable not set})/(.*) - # Redirect a domain with www to non-www - # To disable it remove the next line - - traefik.http.middlewares.${STACK_NAME?Variable not set}-www-redirect.redirectregex.replacement=https://${DOMAIN?Variable not set}/$${3} - # Redirect a domain without www to www - # To enable it remove the previous line and uncomment the next - # - traefik.http.middlewares.${STACK_NAME}-www-redirect.redirectregex.replacement=https://www.${DOMAIN}/$${3} - # Middleware to redirect www, to disable it remove the next line - - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.middlewares=${STACK_NAME?Variable not set}-www-redirect - # Middleware to redirect www, and redirect HTTP to HTTPS - # to disable www redirection remove the section: ${STACK_NAME?Variable not set}-www-redirect, - - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-http.middlewares=${STACK_NAME?Variable not set}-www-redirect,${STACK_NAME?Variable not set}-https-redirect - - backend: &backend - image: "ogabrielluiz/langflow:latest" - build: - context: ../ - dockerfile: base.Dockerfile - depends_on: - - db - - broker - - result_backend - env_file: - - .env - volumes: - - ../:/app - - ./startup-backend.sh:/startup-backend.sh # Ensure the paths match - command: /startup-backend.sh # Fixed the path - healthcheck: - test: "exit 0" - deploy: - labels: - - traefik.enable=true - - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.rule=PathPrefix(`/api/v1`) || PathPrefix(`/docs`) || PathPrefix(`/health`) - - traefik.http.services.${STACK_NAME?Variable not set}-backend.loadbalancer.server.port=7860 - - db: - image: postgres:15.4 - volumes: - - app-db-data:/var/lib/postgresql/data/pgdata - environment: - - PGDATA=/var/lib/postgresql/data/pgdata - deploy: - placement: - constraints: - - node.labels.app-db-data == true - healthcheck: - test: "exit 0" - env_file: - - .env - - pgadmin: - image: dpage/pgadmin4 - networks: - - ${TRAEFIK_PUBLIC_NETWORK?Variable not set} - - default - volumes: - - pgadmin-data:/var/lib/pgadmin - env_file: - - .env - deploy: - labels: - - traefik.enable=true - - traefik.docker.network=${TRAEFIK_PUBLIC_NETWORK?Variable not set} - - traefik.constraint-label=${TRAEFIK_PUBLIC_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-http.rule=Host(`pgadmin.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-http.entrypoints=http - - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-http.middlewares=${STACK_NAME?Variable not set}-https-redirect - - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-https.rule=Host(`pgadmin.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-https.entrypoints=https - - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-https.tls=true - - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-https.tls.certresolver=le - - traefik.http.services.${STACK_NAME?Variable not set}-pgadmin.loadbalancer.server.port=5050 - - result_backend: - image: redis:6.2.5 - env_file: - - .env - # ports: - # - 6379:6379 - healthcheck: - test: "exit 0" - - celeryworker: - <<: *backend - env_file: - - .env - build: - context: ../ - dockerfile: base.Dockerfile - command: celery -A langflow.worker.celery_app worker --loglevel=DEBUG --concurrency=1 -n lf-worker@%h - healthcheck: - test: "exit 0" - deploy: - replicas: 1 - - flower: - <<: *backend - env_file: - - .env - networks: - - default - build: - context: ../ - dockerfile: base.Dockerfile - environment: - - FLOWER_PORT=5555 - - command: /bin/sh -c "celery -A langflow.worker.celery_app --broker=${BROKER_URL?Variable not set} flower --port=5555" - deploy: - labels: - - traefik.enable=true - - traefik.docker.network=${TRAEFIK_PUBLIC_NETWORK?Variable not set} - - traefik.constraint-label=${TRAEFIK_PUBLIC_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-flower-http.rule=Host(`flower.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-flower-http.entrypoints=http - - traefik.http.routers.${STACK_NAME?Variable not set}-flower-http.middlewares=${STACK_NAME?Variable not set}-https-redirect - - traefik.http.routers.${STACK_NAME?Variable not set}-flower-https.rule=Host(`flower.${DOMAIN?Variable not set}`) - - traefik.http.routers.${STACK_NAME?Variable not set}-flower-https.entrypoints=https - - traefik.http.routers.${STACK_NAME?Variable not set}-flower-https.tls=true - - traefik.http.routers.${STACK_NAME?Variable not set}-flower-https.tls.certresolver=le - - traefik.http.services.${STACK_NAME?Variable not set}-flower.loadbalancer.server.port=5555 - - frontend: - image: "ogabrielluiz/langflow_frontend:latest" - env_file: - - .env - # user: your-non-root-user - build: - context: ../src/frontend - dockerfile: Dockerfile - args: - - BACKEND_URL=http://backend:7860 - restart: on-failure - deploy: - labels: - - traefik.enable=true - - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=PathPrefix(`/`) - - traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=80 - - broker: - # RabbitMQ management console - image: rabbitmq:3-management - environment: - - RABBITMQ_DEFAULT_USER=${RABBITMQ_DEFAULT_USER:-admin} - - RABBITMQ_DEFAULT_PASS=${RABBITMQ_DEFAULT_PASS:-admin} - volumes: - - rabbitmq_data:/etc/rabbitmq/ - - rabbitmq_data:/var/lib/rabbitmq/ - - rabbitmq_log:/var/log/rabbitmq/ - ports: - - 5672:5672 - - 15672:15672 - - prometheus: - image: prom/prometheus:v2.37.9 - env_file: - - .env - volumes: - - ./prometheus.yml:/etc/prometheus/prometheus.yml - command: - - "--config.file=/etc/prometheus/prometheus.yml" - # ports: - # - 9090:9090 - healthcheck: - test: "exit 0" - deploy: - labels: - - traefik.enable=true - - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-prometheus-http.rule=PathPrefix(`/metrics`) - - traefik.http.services.${STACK_NAME?Variable not set}-prometheus.loadbalancer.server.port=9090 - - grafana: - image: grafana/grafana:8.2.6 - env_file: - - .env - # ports: - # - 3000:3000 - volumes: - - grafana_data:/var/lib/grafana - deploy: - labels: - - traefik.enable=true - - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-grafana-http.rule=PathPrefix(`/grafana`) - - traefik.http.services.${STACK_NAME?Variable not set}-grafana.loadbalancer.server.port=3000 - - tests: - extends: - file: docker-compose.yml - service: backend - env_file: - - .env - build: - context: ../ - dockerfile: base.Dockerfile - command: pytest -vv - healthcheck: - test: "exit 0" - # override deploy labels to avoid conflicts with the backend service - labels: - - traefik.enable=true - - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-tests-http.rule=PathPrefix(`/api/v1`) || PathPrefix(`/docs`) || PathPrefix(`/health`) - - traefik.http.services.${STACK_NAME?Variable not set}-tests.loadbalancer.server.port=7861 - -volumes: - grafana_data: - app-db-data: - rabbitmq_data: - rabbitmq_log: - pgadmin-data: - -networks: - traefik-public: - # Allow setting it to false for testing - external: false # ${TRAEFIK_PUBLIC_NETWORK_IS_EXTERNAL-true} diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index b1a5f4f06858..d4c00fd9587e 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.8" - services: proxy: image: traefik:v3.0 @@ -69,17 +67,13 @@ services: - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-http.middlewares=${STACK_NAME?Variable not set}-www-redirect,${STACK_NAME?Variable not set}-https-redirect backend: &backend - image: "langflowai/langflow:latest" + image: "langflowai/langflow-backend:latest" depends_on: - db - broker - result_backend env_file: - .env - volumes: - - ../:/app - - ./startup-backend.sh:/startup-backend.sh # Ensure the paths match - command: /startup-backend.sh # Fixed the path healthcheck: test: "exit 0" deploy: @@ -140,7 +134,7 @@ services: <<: *backend env_file: - .env - command: celery -A langflow.worker.celery_app worker --loglevel=INFO --concurrency=1 -n lf-worker@%h -P eventlet + command: /bin/sh -c "python -m celery -A langflow.worker.celery_app worker --loglevel=INFO --concurrency=1 -n lf-worker@%h -P eventlet" healthcheck: test: "exit 0" deploy: @@ -155,7 +149,7 @@ services: environment: - FLOWER_PORT=5555 - command: /bin/sh -c "celery -A langflow.worker.celery_app --broker=${BROKER_URL?Variable not set} flower --port=5555" + command: /bin/sh -c "python -m celery -A langflow.worker.celery_app --broker=${BROKER_URL?Variable not set} flower --port=5555" deploy: labels: - traefik.enable=true @@ -171,15 +165,9 @@ services: - traefik.http.services.${STACK_NAME?Variable not set}-flower.loadbalancer.server.port=5555 frontend: - image: "ogabrielluiz/langflow_frontend:latest" + image: "langflowai/langflow-frontend:latest" env_file: - .env - # user: your-non-root-user - build: - context: ../src/frontend - dockerfile: Dockerfile - args: - - BACKEND_URL=http://backend:7860 restart: on-failure deploy: labels: diff --git a/deploy/startup-backend.sh b/deploy/startup-backend.sh deleted file mode 100755 index 75c8002a5de0..000000000000 --- a/deploy/startup-backend.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -export LANGFLOW_DATABASE_URL="postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}" - - -# Your command to start the backend - -# If the ENVIRONMENT variable is set to "development", then start the backend in development mode -# else start the backend in production mode with guvicorn -if [ "$ENVIRONMENT" = "development" ]; then - echo "Starting backend in development mode" - exec python -m uvicorn --factory langflow.main:create_app --host 0.0.0.0 --port 7860 --log-level ${LOG_LEVEL:-info} --workers 2 --reload -else - echo "Starting backend in production mode" - exec langflow run --host 0.0.0.0 --port 7860 --log-level ${LOG_LEVEL:-info} --workers -1 --backend-only -fi -