Merge remote-tracking branch 'origin/dev' into remove-jcloud
This commit is contained in:
commit
4a3dae5ed6
150 changed files with 14228 additions and 1879 deletions
12
.env.example
12
.env.example
|
|
@ -46,10 +46,20 @@ LANGFLOW_OPEN_BROWSER=
|
|||
# Example: LANGFLOW_REMOVE_API_KEYS=false
|
||||
LANGFLOW_REMOVE_API_KEYS=
|
||||
|
||||
# Whether to use RedisCache or InMemoryCache
|
||||
# Values: memory, redis
|
||||
# Example: LANGFLOW_CACHE_TYPE=memory
|
||||
# If you want to use redis then the following environment variables must be set:
|
||||
# LANGFLOW_REDIS_HOST (default: localhost)
|
||||
# LANGFLOW_REDIS_PORT (default: 6379)
|
||||
# LANGFLOW_REDIS_DB (default: 0)
|
||||
# LANGFLOW_REDIS_CACHE_EXPIRE (default: 3600)
|
||||
LANGFLOW_CACHE_TYPE=
|
||||
|
||||
# Superuser username
|
||||
# Example: LANGFLOW_SUPERUSER=admin
|
||||
LANGFLOW_SUPERUSER=
|
||||
|
||||
# Superuser password
|
||||
# Example: LANGFLOW_SUPERUSER_PASSWORD=123456
|
||||
LANGFLOW_SUPERUSER_PASSWORD=
|
||||
LANGFLOW_SUPERUSER_PASSWORD=
|
||||
|
|
|
|||
44
.github/workflows/ci.yml
vendored
Normal file
44
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
name: "Async API tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-
|
||||
|
||||
- name: Set up Docker
|
||||
run: docker --version && docker-compose --version
|
||||
|
||||
- name: "Create env file"
|
||||
working-directory: ./deploy
|
||||
run: |
|
||||
echo "${{ secrets.ENV_FILE }}" > .env
|
||||
|
||||
- name: Build and start services
|
||||
|
||||
working-directory: ./deploy
|
||||
run: docker compose up --exit-code-from tests tests result_backend broker celeryworker db --build
|
||||
continue-on-error: true
|
||||
|
||||
- name: Stop services
|
||||
run: docker compose down
|
||||
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
|
|
@ -7,7 +7,7 @@ on:
|
|||
branches: [dev]
|
||||
|
||||
env:
|
||||
POETRY_VERSION: "1.4.0"
|
||||
POETRY_VERSION: "1.5.0"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -16,6 +16,8 @@ jobs:
|
|||
matrix:
|
||||
python-version:
|
||||
- "3.10"
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install poetry
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -254,3 +254,4 @@ langflow.db
|
|||
|
||||
/tmp/*
|
||||
src/backend/langflow/frontend/
|
||||
.docker
|
||||
2
Makefile
2
Makefile
|
|
@ -61,7 +61,7 @@ frontendc:
|
|||
make run_frontend
|
||||
|
||||
install_backend:
|
||||
poetry install
|
||||
poetry install --extras deploy
|
||||
|
||||
backend:
|
||||
make install_backend
|
||||
|
|
|
|||
97
base.Dockerfile
Normal file
97
base.Dockerfile
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
|
||||
|
||||
# syntax=docker/dockerfile:1
|
||||
# Keep this syntax directive! It's used to enable Docker BuildKit
|
||||
|
||||
# Based on https://github.com/python-poetry/poetry/discussions/1879?sort=top#discussioncomment-216865
|
||||
# but I try to keep it updated (see history)
|
||||
|
||||
################################
|
||||
# PYTHON-BASE
|
||||
# Sets up all our shared environment variables
|
||||
################################
|
||||
FROM python:3.10-slim as python-base
|
||||
|
||||
# python
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
# prevents python creating .pyc files
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
\
|
||||
# pip
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=on \
|
||||
PIP_DEFAULT_TIMEOUT=100 \
|
||||
\
|
||||
# poetry
|
||||
# https://python-poetry.org/docs/configuration/#using-environment-variables
|
||||
POETRY_VERSION=1.5.1 \
|
||||
# make poetry install to this location
|
||||
POETRY_HOME="/opt/poetry" \
|
||||
# make poetry create the virtual environment in the project's root
|
||||
# it gets named `.venv`
|
||||
POETRY_VIRTUALENVS_IN_PROJECT=true \
|
||||
# do not ask any interactive question
|
||||
POETRY_NO_INTERACTION=1 \
|
||||
\
|
||||
# paths
|
||||
# this is where our requirements + virtual environment will live
|
||||
PYSETUP_PATH="/opt/pysetup" \
|
||||
VENV_PATH="/opt/pysetup/.venv"
|
||||
|
||||
|
||||
# prepend poetry and venv to path
|
||||
ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH"
|
||||
|
||||
|
||||
################################
|
||||
# BUILDER-BASE
|
||||
# Used to build deps + create our virtual environment
|
||||
################################
|
||||
FROM python-base as builder-base
|
||||
RUN apt-get update \
|
||||
&& apt-get install --no-install-recommends -y \
|
||||
# deps for installing poetry
|
||||
curl \
|
||||
# deps for building python deps
|
||||
build-essential
|
||||
|
||||
|
||||
# install poetry - respects $POETRY_VERSION & $POETRY_HOME
|
||||
# The --mount will mount the buildx cache directory to where
|
||||
# Poetry and Pip store their cache so that they can re-use it
|
||||
RUN --mount=type=cache,target=/root/.cache \
|
||||
curl -sSL https://install.python-poetry.org | python3 -
|
||||
|
||||
# copy project requirement files here to ensure they will be cached.
|
||||
WORKDIR $PYSETUP_PATH
|
||||
COPY poetry.lock pyproject.toml ./
|
||||
COPY ./src/backend/langflow/main.py ./src/backend/langflow/main.py
|
||||
# Copy README.md to the build context
|
||||
COPY README.md .
|
||||
# install runtime deps - uses $POETRY_VIRTUALENVS_IN_PROJECT internally
|
||||
RUN --mount=type=cache,target=/root/.cache \
|
||||
poetry install --without dev --extras deploy
|
||||
|
||||
|
||||
################################
|
||||
# DEVELOPMENT
|
||||
# Image used during development / testing
|
||||
################################
|
||||
FROM python-base as development
|
||||
WORKDIR $PYSETUP_PATH
|
||||
|
||||
# copy in our built poetry + venv
|
||||
COPY --from=builder-base $POETRY_HOME $POETRY_HOME
|
||||
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
|
||||
|
||||
# Copy just one file to avoid rebuilding the whole image
|
||||
COPY ./src/backend/langflow/__init__.py ./src/backend/langflow/__init__.py
|
||||
# quicker install as runtime deps are already installed
|
||||
RUN --mount=type=cache,target=/root/.cache \
|
||||
poetry install --with=dev --extras deploy
|
||||
|
||||
# copy in our app code
|
||||
COPY ./src/backend ./src/backend
|
||||
RUN --mount=type=cache,target=/root/.cache \
|
||||
poetry install --with=dev --extras deploy
|
||||
COPY ./tests ./tests=
|
||||
|
||||
57
deploy/.env.example
Normal file
57
deploy/.env.example
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
DOMAIN=localhost
|
||||
STACK_NAME=langflow-stack
|
||||
ENVIRONMENT=development
|
||||
|
||||
TRAEFIK_PUBLIC_NETWORK=traefik-public
|
||||
TRAEFIK_TAG=langflow-traefik
|
||||
TRAEFIK_PUBLIC_TAG=traefik-public
|
||||
|
||||
# RabbitMQ configuration
|
||||
RABBITMQ_DEFAULT_USER=langflow
|
||||
RABBITMQ_DEFAULT_PASS=langflow
|
||||
|
||||
# Database configuration
|
||||
DB_USER=langflow
|
||||
DB_PASSWORD=langflow
|
||||
DB_HOST=db
|
||||
DB_PORT=5432
|
||||
DB_NAME=langflow
|
||||
|
||||
# Logging configuration
|
||||
LOG_LEVEL=debug
|
||||
|
||||
# DB configuration
|
||||
POSTGRES_USER=langflow
|
||||
POSTGRES_PASSWORD=langflow
|
||||
POSTGRES_DB=langflow
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
# Flower configuration
|
||||
LANGFLOW_CACHE_TYPE=redis
|
||||
LANGFLOW_REDIS_HOST=result_backend
|
||||
LANGFLOW_REDIS_PORT=6379
|
||||
LANGFLOW_REDIS_DB=0
|
||||
LANGFLOW_REDIS_EXPIRE=3600
|
||||
LANGFLOW_REDIS_PASSWORD=
|
||||
FLOWER_UNAUTHENTICATED_API=True
|
||||
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
|
||||
1
deploy/.gitignore
vendored
Normal file
1
deploy/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
pgadmin
|
||||
92
deploy/base.Dockerfile
Normal file
92
deploy/base.Dockerfile
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
|
||||
# syntax=docker/dockerfile:1
|
||||
# Keep this syntax directive! It's used to enable Docker BuildKit
|
||||
|
||||
# Based on https://github.com/python-poetry/poetry/discussions/1879?sort=top#discussioncomment-216865
|
||||
# but I try to keep it updated (see history)
|
||||
|
||||
################################
|
||||
# PYTHON-BASE
|
||||
# Sets up all our shared environment variables
|
||||
################################
|
||||
FROM python:3.10-slim as python-base
|
||||
|
||||
# python
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
# prevents python creating .pyc files
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
\
|
||||
# pip
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=on \
|
||||
PIP_DEFAULT_TIMEOUT=100 \
|
||||
\
|
||||
# poetry
|
||||
# https://python-poetry.org/docs/configuration/#using-environment-variables
|
||||
POETRY_VERSION=1.5.1 \
|
||||
# make poetry install to this location
|
||||
POETRY_HOME="/opt/poetry" \
|
||||
# make poetry create the virtual environment in the project's root
|
||||
# it gets named `.venv`
|
||||
POETRY_VIRTUALENVS_IN_PROJECT=true \
|
||||
# do not ask any interactive question
|
||||
POETRY_NO_INTERACTION=1 \
|
||||
\
|
||||
# paths
|
||||
# this is where our requirements + virtual environment will live
|
||||
PYSETUP_PATH="/opt/pysetup" \
|
||||
VENV_PATH="/opt/pysetup/.venv"
|
||||
|
||||
|
||||
# prepend poetry and venv to path
|
||||
ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH"
|
||||
|
||||
|
||||
################################
|
||||
# BUILDER-BASE
|
||||
# Used to build deps + create our virtual environment
|
||||
################################
|
||||
FROM python-base as builder-base
|
||||
RUN apt-get update \
|
||||
&& apt-get install --no-install-recommends -y \
|
||||
# deps for installing poetry
|
||||
curl \
|
||||
# deps for building python deps
|
||||
build-essential
|
||||
|
||||
# install poetry - respects $POETRY_VERSION & $POETRY_HOME
|
||||
# The --mount will mount the buildx cache directory to where
|
||||
# Poetry and Pip store their cache so that they can re-use it
|
||||
RUN --mount=type=cache,target=/root/.cache \
|
||||
curl -sSL https://install.python-poetry.org | python3 -
|
||||
|
||||
# copy project requirement files here to ensure they will be cached.
|
||||
WORKDIR $PYSETUP_PATH
|
||||
COPY ./poetry.lock ./pyproject.toml ./
|
||||
# Copy README.md to the build context
|
||||
COPY ./README.md ./
|
||||
# install runtime deps - uses $POETRY_VIRTUALENVS_IN_PROJECT internally
|
||||
RUN --mount=type=cache,target=/root/.cache \
|
||||
poetry install --without dev --extras deploy
|
||||
|
||||
|
||||
################################
|
||||
# DEVELOPMENT
|
||||
# Image used during development / testing
|
||||
################################
|
||||
FROM python-base as development
|
||||
WORKDIR $PYSETUP_PATH
|
||||
|
||||
# copy in our built poetry + venv
|
||||
COPY --from=builder-base $POETRY_HOME $POETRY_HOME
|
||||
COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
|
||||
|
||||
# Copy just one file to avoid rebuilding the whole image
|
||||
COPY ./src/backend/langflow/__init__.py ./src/backend/langflow/__init__.py
|
||||
# quicker install as runtime deps are already installed
|
||||
RUN --mount=type=cache,target=/root/.cache \
|
||||
poetry install --with=dev --extras deploy
|
||||
|
||||
# copy in our app code
|
||||
COPY ./src/backend ./src/backend
|
||||
COPY ./tests ./tests
|
||||
66
deploy/docker-compose.override.yml
Normal file
66
deploy/docker-compose.override.yml
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
version: "3.8"
|
||||
services:
|
||||
proxy:
|
||||
ports:
|
||||
- "80:80"
|
||||
- "8090:8080"
|
||||
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
|
||||
# Disable Docker Swarm mode for local development
|
||||
# - --providers.docker.swarmmode
|
||||
# Enable the access log, with HTTP requests
|
||||
- --accesslog
|
||||
# Enable the Traefik log, for configurations and errors
|
||||
- --log
|
||||
# Enable the Dashboard and API
|
||||
- --api
|
||||
# Enable the Dashboard and API in insecure mode for local development
|
||||
- --api.insecure=true
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.${STACK_NAME?Variable not set}-traefik-public-http.rule=Host(`${DOMAIN?Variable not set}`)
|
||||
- traefik.http.services.${STACK_NAME?Variable not set}-traefik-public.loadbalancer.server.port=80
|
||||
|
||||
result_backend:
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
pgadmin:
|
||||
ports:
|
||||
- "5050:5050"
|
||||
|
||||
flower:
|
||||
ports:
|
||||
- "5555:5555"
|
||||
|
||||
backend:
|
||||
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
|
||||
|
||||
frontend:
|
||||
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
|
||||
|
||||
celeryworker:
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set}
|
||||
- traefik.http.routers.${STACK_NAME?Variable not set}-celeryworker-http.rule=PathPrefix(`/api/v1`) || PathPrefix(`/docs`) || PathPrefix(`/health`)
|
||||
- traefik.http.services.${STACK_NAME?Variable not set}-celeryworker.loadbalancer.server.port=7860
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
# For local dev, don't expect an external Traefik network
|
||||
external: false
|
||||
85
deploy/docker-compose.test.yml
Normal file
85
deploy/docker-compose.test.yml
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
version: "3.8"
|
||||
services:
|
||||
proxy:
|
||||
ports:
|
||||
- "80:80"
|
||||
- "8090:8080"
|
||||
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
|
||||
# Disable Docker Swarm mode for local development
|
||||
# - --providers.docker.swarmmode
|
||||
# Enable the access log, with HTTP requests
|
||||
- --accesslog
|
||||
# Enable the Traefik log, for configurations and errors
|
||||
- --log
|
||||
# Enable the Dashboard and API
|
||||
- --api
|
||||
# Enable the Dashboard and API in insecure mode for local development
|
||||
- --api.insecure=true
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.${STACK_NAME?Variable not set}-traefik-public-http.rule=Host(`${DOMAIN?Variable not set}`)
|
||||
- traefik.http.services.${STACK_NAME?Variable not set}-traefik-public.loadbalancer.server.port=80
|
||||
|
||||
result_backend:
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
pgadmin:
|
||||
ports:
|
||||
- "5050:5050"
|
||||
|
||||
flower:
|
||||
ports:
|
||||
- "5555:5555"
|
||||
|
||||
backend:
|
||||
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
|
||||
|
||||
frontend:
|
||||
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
|
||||
|
||||
celeryworker:
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set}
|
||||
- traefik.http.routers.${STACK_NAME?Variable not set}-celeryworker-http.rule=PathPrefix(`/api/v1`) || PathPrefix(`/docs`) || PathPrefix(`/health`)
|
||||
- traefik.http.services.${STACK_NAME?Variable not set}-celeryworker.loadbalancer.server.port=7860
|
||||
|
||||
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
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
# For local dev, don't expect an external Traefik network
|
||||
external: false
|
||||
258
deploy/docker-compose.yml
Normal file
258
deploy/docker-compose.yml
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
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=INFO --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
|
||||
|
||||
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}
|
||||
11
deploy/prometheus.yml
Normal file
11
deploy/prometheus.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: prometheus
|
||||
static_configs:
|
||||
- targets: ["prometheus:9090"]
|
||||
- job_name: flower
|
||||
static_configs:
|
||||
- targets: ["flower:5555"]
|
||||
5
deploy/scripts/.gitignore
vendored
Normal file
5
deploy/scripts/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# terraform
|
||||
*.tfstate
|
||||
*.tfstate.backup
|
||||
*.tfvars
|
||||
.terraform/
|
||||
11
deploy/scripts/build-push.sh
Executable file
11
deploy/scripts/build-push.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
#! /usr/bin/env sh
|
||||
|
||||
# Exit in case of error
|
||||
set -e
|
||||
|
||||
TAG=${TAG?Variable not set} \
|
||||
FRONTEND_ENV=${FRONTEND_ENV-production} \
|
||||
sh ./scripts/build.sh
|
||||
|
||||
docker-compose -f docker-compose.yml push
|
||||
10
deploy/scripts/build.sh
Executable file
10
deploy/scripts/build.sh
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#! /usr/bin/env sh
|
||||
|
||||
# Exit in case of error
|
||||
set -e
|
||||
|
||||
TAG=${TAG?Variable not set} \
|
||||
FRONTEND_ENV=${FRONTEND_ENV-production} \
|
||||
docker-compose \
|
||||
-f docker-compose.yml \
|
||||
build
|
||||
24
deploy/scripts/terraform/.terraform.lock.hcl
generated
Normal file
24
deploy/scripts/terraform/.terraform.lock.hcl
generated
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/aws" {
|
||||
version = "5.13.1"
|
||||
hashes = [
|
||||
"h1:T/p3Gp8uAvRk3BmBZI/B7JIUpxF+2DygvBsv2UvJK4w=",
|
||||
"zh:0d107e410ecfbd5d2fb5ff9793f88e2ce03ae5b3bda4e3b772b5d146cdd859d8",
|
||||
"zh:1080cf6a402939ec4ad393380f2ab2dfdc0e175903e08ed796aa22eb95868847",
|
||||
"zh:300420d642c3ada48cfe633444eafa7bcd410cd6a8503de2384f14ac54dc3ce3",
|
||||
"zh:4e0121014a8d6ef0b1ab4634877545737bb54e951340f1b67ffea8cd22b2d252",
|
||||
"zh:59b401bbf95dc8c6bea58085ff286543380f176271251193eac09cb7fcf619b7",
|
||||
"zh:5dfaf51e979131710ce8e1572e6012564e68c7c842e3d9caaaeb0fe6af15c351",
|
||||
"zh:84bb75dafca056d7c3783be5185187fdd3294f902e9d72f7655f2efb5e066650",
|
||||
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
|
||||
"zh:aa4e2b9f699d497041679bc05ca34ac21a5184298eb1813f35455b1883977910",
|
||||
"zh:b51a4f08d84b071128df68a95cfa5114301a50bf8ab8e655dcf7e384e5bc6458",
|
||||
"zh:bce284ac6ebb65053d9b703048e3157bf4175782ea9dbaec9f64dc2b6fcefb0c",
|
||||
"zh:c748f78b79b354794098b06b18a02aefdb49be144dff8876c9204083980f7de0",
|
||||
"zh:ee69d9aef5ca532392cdc26499096f3fa6e55f8622387f78194ebfaadb796aef",
|
||||
"zh:ef561bee58e4976474bc056649095737fa3b2bcb74602032415d770bfc620c1f",
|
||||
"zh:f696d8416c57c31f144d432779ba34764560a95937db3bb3dd2892a791a6d5a7",
|
||||
]
|
||||
}
|
||||
114
deploy/scripts/terraform/main.tf
Normal file
114
deploy/scripts/terraform/main.tf
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
terraform {
|
||||
backend "s3" {
|
||||
bucket = "terraform-5fso81t4tn8z"
|
||||
key = "backend/terraform.tfstate"
|
||||
region = "us-east-1"
|
||||
}
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
region = var.region # Choose the region as needed
|
||||
}
|
||||
|
||||
module "docker-swarm" {
|
||||
source = "./modules/docker-swarm"
|
||||
key_name = aws_key_pair.swarm-key.key_name
|
||||
vpc_id = aws_vpc.swarm-vpc.id
|
||||
subnet_id = aws_subnet.swarm-public-subnet.id
|
||||
security_group = aws_security_group.swarm-sg.id
|
||||
instance_type = var.instance_type # Choose the instance type as needed
|
||||
manager_count = var.manager_count
|
||||
worker_count = var.worker_count # This is the number of services in the docker-compose.yml file
|
||||
}
|
||||
|
||||
resource "aws_key_pair" "swarm-key" {
|
||||
key_name = "swarm-key"
|
||||
public_key = file("~/.ssh/id_rsa.pub")
|
||||
}
|
||||
|
||||
resource "aws_vpc" "swarm-vpc" {
|
||||
cidr_block = "10.0.0.0/16"
|
||||
enable_dns_support = true
|
||||
enable_dns_hostnames = true
|
||||
}
|
||||
|
||||
resource "aws_subnet" "swarm-private-subnet" {
|
||||
vpc_id = aws_vpc.swarm-vpc.id
|
||||
cidr_block = "10.0.1.0/24"
|
||||
}
|
||||
|
||||
resource "aws_subnet" "swarm-public-subnet" {
|
||||
vpc_id = aws_vpc.swarm-vpc.id
|
||||
cidr_block = "10.0.2.0/24"
|
||||
}
|
||||
|
||||
resource "aws_internet_gateway" "igw" {
|
||||
vpc_id = aws_vpc.swarm-vpc.id
|
||||
}
|
||||
|
||||
resource "aws_route_table" "public_rt" {
|
||||
vpc_id = aws_vpc.swarm-vpc.id
|
||||
|
||||
route {
|
||||
cidr_block = "0.0.0.0/0"
|
||||
gateway_id = aws_internet_gateway.igw.id
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_route_table_association" "public_subnet_asso" {
|
||||
subnet_id = aws_subnet.swarm-public-subnet.id
|
||||
route_table_id = aws_route_table.public_rt.id
|
||||
}
|
||||
|
||||
resource "aws_security_group" "swarm-sg" {
|
||||
vpc_id = aws_vpc.swarm-vpc.id
|
||||
|
||||
ingress {
|
||||
from_port = 22
|
||||
to_port = 22
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
ingress {
|
||||
from_port = 2376
|
||||
to_port = 2377
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
ingress {
|
||||
from_port = 7946
|
||||
to_port = 7946
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
ingress {
|
||||
from_port = 4789
|
||||
to_port = 4789
|
||||
protocol = "udp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
egress {
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
ingress {
|
||||
from_port = 8080
|
||||
to_port = 8080
|
||||
protocol = "tcp"
|
||||
cidr_blocks = [aws_subnet.swarm-public-subnet.cidr_block]
|
||||
}
|
||||
|
||||
egress {
|
||||
from_port = 8080
|
||||
to_port = 8080
|
||||
protocol = "tcp"
|
||||
cidr_blocks = [aws_subnet.swarm-public-subnet.cidr_block]
|
||||
}
|
||||
}
|
||||
94
deploy/scripts/terraform/modules/docker-swarm/main.tf
Normal file
94
deploy/scripts/terraform/modules/docker-swarm/main.tf
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
variable "key_name" {}
|
||||
variable "vpc_id" {}
|
||||
variable "subnet_id" {}
|
||||
variable "security_group" {}
|
||||
variable "instance_type" {}
|
||||
variable "manager_count" {}
|
||||
variable "worker_count" {}
|
||||
|
||||
|
||||
resource "aws_instance" "manager" {
|
||||
count = var.manager_count
|
||||
ami = "ami-08a52ddb321b32a8c" # Amazon Linux 2 LTS
|
||||
instance_type = var.instance_type
|
||||
key_name = var.key_name
|
||||
vpc_security_group_ids = [var.security_group]
|
||||
subnet_id = var.subnet_id
|
||||
associate_public_ip_address = true
|
||||
|
||||
user_data = <<-EOT
|
||||
#!/bin/bash
|
||||
sudo yum update -y
|
||||
sudo yum install -y docker
|
||||
sudo yum install -y git
|
||||
sudo yum install -y nc
|
||||
sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
|
||||
sudo chmod +x /usr/local/bin/docker-compose
|
||||
sudo service docker start
|
||||
sudo usermod -a -G docker ec2-user
|
||||
sudo chkconfig docker on
|
||||
|
||||
# Fetch instance metadata with token
|
||||
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
|
||||
IP_ADDR=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/local-ipv4)
|
||||
|
||||
docker swarm init --advertise-addr $IP_ADDR
|
||||
|
||||
# Create a script to get the join token
|
||||
echo 'docker swarm join-token worker -q' > get_token.sh
|
||||
chmod +x get_token.sh
|
||||
timeout 5m bash -c "while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; ./get_token.sh; } | nc -l 8080; done" &
|
||||
sleep 10
|
||||
|
||||
# Clone the repo and start the stack
|
||||
git clone https://github.com/logspace-ai/langflow.git
|
||||
cd /langflow
|
||||
git checkout celery
|
||||
cd /langflow/deploy
|
||||
|
||||
sudo cp .env.example .env
|
||||
|
||||
# Add the label to random worker node to ensure that the data volume is created on the same node
|
||||
docker node update --label-add app-db-data=true $(docker node ls --format '{{.Hostname}}' --filter role=worker | head -n 1)
|
||||
|
||||
env $(cat .env | grep ^[A-Z] | xargs) docker stack deploy --compose-file docker-compose.yml langflow_stack
|
||||
|
||||
EOT
|
||||
|
||||
tags = {
|
||||
Name = "manager-${count.index}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "worker" {
|
||||
count = var.worker_count
|
||||
ami = "ami-08a52ddb321b32a8c" # Amazon Linux 2 LTS
|
||||
instance_type = var.instance_type
|
||||
key_name = var.key_name
|
||||
vpc_security_group_ids = [var.security_group]
|
||||
subnet_id = var.subnet_id
|
||||
associate_public_ip_address = true
|
||||
|
||||
user_data = <<-EOT
|
||||
#!/bin/bash
|
||||
MANAGER_IP="${aws_instance.manager.0.private_ip}"
|
||||
sudo yum update -y
|
||||
sudo yum install -y docker
|
||||
sudo service docker start
|
||||
sudo usermod -a -G docker ec2-user
|
||||
sudo chkconfig docker on
|
||||
docker swarm join --token $(curl -s http://$MANAGER_IP:8080/token) $MANAGER_IP:2377
|
||||
EOT
|
||||
|
||||
tags = {
|
||||
Name = "worker-${count.index}"
|
||||
}
|
||||
}
|
||||
|
||||
output "manager_public_ips" {
|
||||
value = aws_instance.manager[*].public_ip
|
||||
}
|
||||
|
||||
output "worker_public_ips" {
|
||||
value = aws_instance.worker[*].public_ip
|
||||
}
|
||||
8
deploy/scripts/terraform/outputs.tf
Normal file
8
deploy/scripts/terraform/outputs.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
output "manager_public_ips" {
|
||||
value = module.docker-swarm.manager_public_ips
|
||||
}
|
||||
|
||||
output "worker_public_ips" {
|
||||
value = module.docker-swarm.worker_public_ips
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue