mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-17 21:25:46 +02:00
163 lines
4.1 KiB
Python
163 lines
4.1 KiB
Python
import json
|
|
import pathlib
|
|
import shutil
|
|
from typing import Literal, NamedTuple, Optional
|
|
|
|
import click.exceptions
|
|
|
|
from langgraph_cli.exec import subp_exec
|
|
|
|
ROOT = pathlib.Path(__file__).parent.resolve()
|
|
DEFAULT_POSTGRES_URI = (
|
|
"postgres://postgres:postgres@langgraph-postgres:5432/postgres?sslmode=disable"
|
|
)
|
|
|
|
|
|
DB = """
|
|
langgraph-postgres:
|
|
image: postgres:16
|
|
restart: on-failure
|
|
ports:
|
|
- "5433:5432"
|
|
environment:
|
|
POSTGRES_DB: postgres
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
volumes:
|
|
- langgraph-data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: pg_isready -U postgres
|
|
start_period: 10s
|
|
timeout: 1s
|
|
retries: 5
|
|
"""
|
|
|
|
|
|
DEBUGGER = """
|
|
langgraph-debugger:
|
|
image: langchain/langgraph-debugger
|
|
restart: on-failure
|
|
ports:
|
|
- "{debugger_port}:80"
|
|
depends_on:
|
|
langgraph-postgres:
|
|
condition: service_healthy
|
|
"""
|
|
|
|
|
|
class Version(NamedTuple):
|
|
major: int
|
|
minor: int
|
|
patch: int
|
|
|
|
|
|
DockerComposeType = Literal["plugin", "standalone"]
|
|
|
|
|
|
class DockerCapabilities(NamedTuple):
|
|
version_docker: Version
|
|
version_compose: Version
|
|
healthcheck_start_interval: bool
|
|
compose_type: DockerComposeType = "plugin"
|
|
|
|
|
|
def _parse_version(version: str) -> Version:
|
|
parts = version.split(".", 2)
|
|
if len(parts) == 1:
|
|
major = parts[0]
|
|
minor = "0"
|
|
patch = "0"
|
|
elif len(parts) == 2:
|
|
major, minor = parts
|
|
patch = "0"
|
|
else:
|
|
major, minor, patch = parts
|
|
return Version(int(major.lstrip("v")), int(minor), int(patch.split("-")[0]))
|
|
|
|
|
|
def check_capabilities(runner) -> DockerCapabilities:
|
|
# check docker available
|
|
try:
|
|
stdout, _ = runner.run(subp_exec("docker", "info", "-f", "json", collect=True))
|
|
info = json.loads(stdout)
|
|
except (click.exceptions.Exit, json.JSONDecodeError):
|
|
raise click.UsageError("Docker not installed or not running") from None
|
|
|
|
compose_type: DockerComposeType
|
|
try:
|
|
compose = next(
|
|
p for p in info["ClientInfo"]["Plugins"] if p["Name"] == "compose"
|
|
)
|
|
compose_type = "plugin"
|
|
except (KeyError, StopIteration):
|
|
if shutil.which("docker-compose") is None:
|
|
raise click.UsageError("Docker Compose not installed") from None
|
|
|
|
compose_type = "standalone"
|
|
|
|
# parse versions
|
|
docker_version = _parse_version(info["ServerVersion"])
|
|
compose_version = _parse_version(compose["Version"])
|
|
|
|
# check capabilities
|
|
return DockerCapabilities(
|
|
version_docker=docker_version,
|
|
version_compose=compose_version,
|
|
healthcheck_start_interval=docker_version >= Version(25, 0, 0),
|
|
compose_type=compose_type,
|
|
)
|
|
|
|
|
|
def compose(
|
|
capabilities: DockerCapabilities,
|
|
*,
|
|
port: int,
|
|
debugger_port: Optional[int] = None,
|
|
# postgres://user:password@host:port/database?option=value
|
|
postgres_uri: Optional[str] = None,
|
|
) -> str:
|
|
if postgres_uri is None:
|
|
include_db = True
|
|
postgres_uri = DEFAULT_POSTGRES_URI
|
|
else:
|
|
include_db = False
|
|
|
|
db = DB.format() if include_db else ""
|
|
volumes = (
|
|
"""volumes:
|
|
langgraph-data:
|
|
driver: local
|
|
"""
|
|
if include_db
|
|
else ""
|
|
)
|
|
if db:
|
|
if capabilities.healthcheck_start_interval:
|
|
db += """
|
|
interval: 60s
|
|
start_interval: 1s"""
|
|
else:
|
|
db += """
|
|
interval: 5s"""
|
|
|
|
compose_str = f"""{volumes}services:
|
|
{db}
|
|
{DEBUGGER.format(debugger_port=debugger_port) if debugger_port else ""}
|
|
langgraph-api:
|
|
restart: on-failure
|
|
ports:
|
|
- "{port}:8000"
|
|
depends_on:
|
|
langgraph-postgres:
|
|
condition: service_healthy
|
|
environment:
|
|
POSTGRES_URI: {postgres_uri}
|
|
"""
|
|
if capabilities.healthcheck_start_interval:
|
|
compose_str += """ healthcheck:
|
|
interval: 60s
|
|
start_interval: 1s
|
|
start_period: 10s"""
|
|
|
|
return compose_str
|