mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-11 03:12:55 +00:00
feat: serve the UI from the backend image, one-port standalone stack
The backend image builds the web UI with scripts/build_frontend.sh and serves it through docsgpt/ui.py, so the standalone Compose file drops the frontend container. UI and API share port 7091, published on 127.0.0.1 unless DOCSGPT_BIND says otherwise. POSTGRES_PASSWORD is configurable, and an optional https profile puts Caddy in front of a public domain. docker-image-verify.yml starts the standalone stack on the image it built and checks the API, the UI, /config.js and a client-side route on one port.
This commit is contained in:
1 parent
0fcec68b67
commit
95fd4bdefe
9 files changed
+236
-51
No files matched your search
+17
-2
@@ -1,11 +1,14 @@
|
|||||||
# Build context for docsgpt/Dockerfile is the repository root, so the image can
|
# Build context for docsgpt/Dockerfile is the repository root, so the image can
|
||||||
# carry the `application` import alias next to the `docsgpt` package. Allow only
|
# carry the `application` import alias next to the `docsgpt` package. Allow only
|
||||||
# what the image needs; everything else (frontend, docs, tests, venvs) stays out.
|
# what the image needs; everything else (docs, tests, venvs) stays out.
|
||||||
*
|
*
|
||||||
!docsgpt/
|
!docsgpt/
|
||||||
# Only the alias file: an upgraded checkout may still hold gitignored
|
# Only the alias file: an upgraded checkout may still hold gitignored
|
||||||
# application/{inputs,indexes,vectors,.env} from the old layout.
|
# application/{inputs,indexes,vectors,.env} from the old layout.
|
||||||
!application/__init__.py
|
!application/__init__.py
|
||||||
|
# The web UI's source and the script that builds it (the `ui` stage).
|
||||||
|
!frontend/
|
||||||
|
!scripts/build_frontend.sh
|
||||||
|
|
||||||
# Inside the package: caches, local runtime data and secrets never ship.
|
# Inside the package: caches, local runtime data and secrets never ship.
|
||||||
**/__pycache__/
|
**/__pycache__/
|
||||||
@@ -23,5 +26,17 @@ docsgpt/*.pkl
|
|||||||
docsgpt/.env
|
docsgpt/.env
|
||||||
docsgpt/.env.*
|
docsgpt/.env.*
|
||||||
docsgpt/Dockerfile
|
docsgpt/Dockerfile
|
||||||
# The backend image serves no UI (the frontend image does); a local UI build stays out.
|
# A local UI build stays out: the `ui` stage builds the one the image serves.
|
||||||
docsgpt/static/
|
docsgpt/static/
|
||||||
|
|
||||||
|
# Inside the frontend: installed packages and local builds are redone in the
|
||||||
|
# `ui` stage, and local VITE_* overrides must not be baked into a published image.
|
||||||
|
frontend/node_modules/
|
||||||
|
frontend/dist/
|
||||||
|
frontend/.env.local
|
||||||
|
frontend/.env.*.local
|
||||||
|
frontend/*.log
|
||||||
|
# The frontend image's own build files; changing them must not rebuild this UI.
|
||||||
|
frontend/Dockerfile
|
||||||
|
frontend/.dockerignore
|
||||||
|
frontend/docker/
|
||||||
@@ -3,6 +3,8 @@ name: Verify the Docker image works offline
|
|||||||
# Builds the backend image and runs its offline check with networking off, so
|
# Builds the backend image and runs its offline check with networking off, so
|
||||||
# a change that reintroduces a first-request download (a tokenizer, tiktoken's
|
# a change that reintroduces a first-request download (a tokenizer, tiktoken's
|
||||||
# encoding, an embedding model) fails here instead of in an air-gapped install.
|
# encoding, an embedding model) fails here instead of in an air-gapped install.
|
||||||
|
# Then starts the standalone Compose stack on the image and checks that the one
|
||||||
|
# published port serves both the API and the web UI.
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -17,6 +19,10 @@ on:
|
|||||||
- 'docsgpt/vectorstore/model_registry.py'
|
- 'docsgpt/vectorstore/model_registry.py'
|
||||||
- 'docsgpt/parser/tokenization.py'
|
- 'docsgpt/parser/tokenization.py'
|
||||||
- 'docsgpt/vectorstore/embeddings_local.py'
|
- 'docsgpt/vectorstore/embeddings_local.py'
|
||||||
|
- 'docsgpt/ui.py'
|
||||||
|
- 'frontend/**'
|
||||||
|
- 'scripts/build_frontend.sh'
|
||||||
|
- 'deployment/docker-compose-standalone.yaml'
|
||||||
- '.github/workflows/docker-image-verify.yml'
|
- '.github/workflows/docker-image-verify.yml'
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -45,7 +51,8 @@ jobs:
|
|||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
load: true
|
load: true
|
||||||
tags: docsgpt:verify${{ matrix.variant }}
|
# The name the standalone Compose file runs, under a tag no registry has.
|
||||||
|
tags: arc53/docsgpt:verify${{ matrix.variant }}
|
||||||
build-args: |
|
build-args: |
|
||||||
EXTRAS=${{ matrix.variant == '-docling' && 'docling' || '' }}
|
EXTRAS=${{ matrix.variant == '-docling' && 'docling' || '' }}
|
||||||
INSTALL_TESSERACT=${{ matrix.variant == '-docling' && 'true' || 'false' }}
|
INSTALL_TESSERACT=${{ matrix.variant == '-docling' && 'true' || 'false' }}
|
||||||
@@ -54,14 +61,49 @@ jobs:
|
|||||||
|
|
||||||
- name: Image size
|
- name: Image size
|
||||||
env:
|
env:
|
||||||
IMAGE: docsgpt:verify${{ matrix.variant }}
|
IMAGE: arc53/docsgpt:verify${{ matrix.variant }}
|
||||||
run: |
|
run: |
|
||||||
docker image inspect "$IMAGE" --format '{{.Size}}' | awk '{printf "uncompressed: %.2f GB\n", $1/1e9}'
|
docker image inspect "$IMAGE" --format '{{.Size}}' | awk '{printf "uncompressed: %.2f GB\n", $1/1e9}'
|
||||||
docker history "$IMAGE" --format '{{.Size}}\t{{.CreatedBy}}' | head -20
|
docker history "$IMAGE" --format '{{.Size}}\t{{.CreatedBy}}' | head -20
|
||||||
|
|
||||||
- name: Offline verification (no network)
|
- name: Offline verification (no network)
|
||||||
env:
|
env:
|
||||||
IMAGE: docsgpt:verify${{ matrix.variant }}
|
IMAGE: arc53/docsgpt:verify${{ matrix.variant }}
|
||||||
run: |
|
run: |
|
||||||
docker run --rm --network none "$IMAGE" \
|
docker run --rm --network none "$IMAGE" \
|
||||||
python -m docsgpt.scripts.verify_offline
|
python -m docsgpt.scripts.verify_offline
|
||||||
|
|
||||||
|
- name: The standalone stack serves the API and the UI on one port
|
||||||
|
env:
|
||||||
|
DOCSGPT_IMAGE_TAG: verify
|
||||||
|
DOCSGPT_IMAGE_VARIANT: ${{ matrix.variant }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
# --pull missing keeps the image built above; postgres and redis are pulled.
|
||||||
|
docker compose -f deployment/docker-compose-standalone.yaml up -d --pull missing backend
|
||||||
|
base=http://127.0.0.1:7091
|
||||||
|
for _ in $(seq 1 90); do
|
||||||
|
if curl -fsS "$base/api/health" >/dev/null 2>&1; then break; fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
curl -fsS "$base/api/health"
|
||||||
|
echo
|
||||||
|
curl -fsS "$base/" | grep -q 'src="/config.js"'
|
||||||
|
curl -fsS "$base/config.js" | grep -q 'window.__DOCSGPT_ENV__'
|
||||||
|
# A client-side route falls back to the UI's index.html.
|
||||||
|
curl -fsS "$base/settings" | grep -q 'src="/config.js"'
|
||||||
|
echo "API and UI served on $base"
|
||||||
|
|
||||||
|
- name: Stack logs
|
||||||
|
if: failure()
|
||||||
|
env:
|
||||||
|
DOCSGPT_IMAGE_TAG: verify
|
||||||
|
DOCSGPT_IMAGE_VARIANT: ${{ matrix.variant }}
|
||||||
|
run: docker compose -f deployment/docker-compose-standalone.yaml logs --no-color
|
||||||
|
|
||||||
|
- name: Stop the stack
|
||||||
|
if: always()
|
||||||
|
env:
|
||||||
|
DOCSGPT_IMAGE_TAG: verify
|
||||||
|
DOCSGPT_IMAGE_VARIANT: ${{ matrix.variant }}
|
||||||
|
run: docker compose -f deployment/docker-compose-standalone.yaml down -v
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
# DOCSGPT_IMAGE_TAG develop (default, follows main) or a release, e.g. 0.20.0
|
# DOCSGPT_IMAGE_TAG develop (default, follows main) or a release, e.g. 0.20.0
|
||||||
# DOCSGPT_IMAGE_VARIANT empty (default, slim) or -docling: docling parser engine,
|
# DOCSGPT_IMAGE_VARIANT empty (default, slim) or -docling: docling parser engine,
|
||||||
# its models, and tesseract baked in (OCR-ready)
|
# its models, and tesseract baked in (OCR-ready)
|
||||||
# Set them in ../.env or the shell. deployment/docker-compose-standalone.yaml is
|
# Set them in ../.env or the shell. deployment/docker-compose-standalone.yaml runs
|
||||||
# the same stack without a git checkout.
|
# the same images without a git checkout, with the backend serving the UI on one port.
|
||||||
name: docsgpt-oss
|
name: docsgpt-oss
|
||||||
services:
|
services:
|
||||||
|
|
||||||
|
|||||||
@@ -3,52 +3,43 @@
|
|||||||
# curl -fsSLO https://raw.githubusercontent.com/arc53/DocsGPT/main/deployment/docker-compose-standalone.yaml
|
# curl -fsSLO https://raw.githubusercontent.com/arc53/DocsGPT/main/deployment/docker-compose-standalone.yaml
|
||||||
# printf 'LLM_PROVIDER=docsgpt\nVITE_API_STREAMING=true\nINTERNAL_KEY=%s\n' "$(openssl rand -hex 16)" > .env
|
# printf 'LLM_PROVIDER=docsgpt\nVITE_API_STREAMING=true\nINTERNAL_KEY=%s\n' "$(openssl rand -hex 16)" > .env
|
||||||
# docker compose -f docker-compose-standalone.yaml up -d
|
# docker compose -f docker-compose-standalone.yaml up -d
|
||||||
|
# open http://localhost:7091
|
||||||
#
|
#
|
||||||
# INTERNAL_KEY is the shared secret the worker uses to hand finished indexes to
|
# INTERNAL_KEY is the shared secret the worker uses to hand finished indexes to
|
||||||
# the API; without it every ingest fails with a 401 (setup.sh generates one).
|
# the API; without it every ingest fails with a 401 (setup.sh generates one).
|
||||||
# open http://localhost:5173
|
|
||||||
#
|
#
|
||||||
# Every release also attaches this file as an asset. Settings come from .env
|
# The backend image serves the web UI and the API on one port. Every release
|
||||||
# next to this file (any DocsGPT setting; the compose-internal service URLs
|
# also attaches this file as an asset. Settings come from .env next to this
|
||||||
# below take precedence). Data lives in named volumes, so `docker compose
|
# file (any DocsGPT setting, VITE_* included; the compose-internal service URLs
|
||||||
# down` keeps it and `docker compose down -v` removes it.
|
# below take precedence). Data lives in named volumes, so `docker compose down`
|
||||||
|
# keeps it and `docker compose down -v` removes it.
|
||||||
#
|
#
|
||||||
# DOCSGPT_IMAGE_TAG release to run, e.g. 0.20.0 (default: latest release);
|
# DOCSGPT_IMAGE_TAG release to run, e.g. 0.20.0 (default: latest release);
|
||||||
# develop follows the main branch
|
# develop follows the main branch
|
||||||
# DOCSGPT_IMAGE_VARIANT empty (slim, default) or -docling: docling parser
|
# DOCSGPT_IMAGE_VARIANT empty (slim, default) or -docling: docling parser
|
||||||
# engine, its models, and tesseract baked in (OCR-ready)
|
# engine, its models, and tesseract baked in (OCR-ready)
|
||||||
|
# DOCSGPT_BIND interface the port is published on: 127.0.0.1 (default,
|
||||||
|
# this machine only) or 0.0.0.0 (every interface; set
|
||||||
|
# AUTH_TYPE, see the DocsGPT settings guide)
|
||||||
|
# DOCSGPT_PORT host port for the UI and API (default: 7091)
|
||||||
|
# POSTGRES_PASSWORD database password (default: docsgpt). Read when the
|
||||||
|
# postgres volume is first created; changing it later
|
||||||
|
# does not change the existing database's password.
|
||||||
|
# Use URL-safe characters (e.g. openssl rand -hex 24).
|
||||||
|
# DOCSGPT_DOMAIN public domain for the `https` profile (below)
|
||||||
# EMBEDDINGS_NAME defaults to granite here (this stack always starts on
|
# EMBEDDINGS_NAME defaults to granite here (this stack always starts on
|
||||||
# fresh volumes, so there is no older index to keep
|
# fresh volumes, so there is no older index to keep
|
||||||
# compatible); the code default stays mpnet for upgrades.
|
# compatible); the code default stays mpnet for upgrades.
|
||||||
|
#
|
||||||
|
# HTTPS for a public domain: point the domain's DNS at this machine, open ports
|
||||||
|
# 80 and 443, then
|
||||||
|
# DOCSGPT_DOMAIN=docs.example.com docker compose -f docker-compose-standalone.yaml --profile https up -d
|
||||||
|
# Caddy obtains and renews the certificate and proxies to the backend. Putting
|
||||||
|
# DOCSGPT_DOMAIN and COMPOSE_PROFILES=https in .env instead makes every later
|
||||||
|
# `up`, `down` and `logs` include Caddy without the flag.
|
||||||
name: docsgpt
|
name: docsgpt
|
||||||
|
|
||||||
services:
|
services:
|
||||||
frontend:
|
|
||||||
image: arc53/docsgpt-fe:${DOCSGPT_IMAGE_TAG:-latest}
|
|
||||||
env_file:
|
|
||||||
- path: .env
|
|
||||||
required: false
|
|
||||||
environment:
|
|
||||||
# Every VITE_* the app reads. A bare name is passed through only when it is
|
|
||||||
# set in the shell or the --env-file, so an unset one does not reach the
|
|
||||||
# container as an empty string and override the image's own default.
|
|
||||||
- VITE_API_HOST=${VITE_API_HOST:-http://localhost:7091}
|
|
||||||
- VITE_API_STREAMING=${VITE_API_STREAMING:-true}
|
|
||||||
- VITE_BASE_URL
|
|
||||||
- VITE_GOOGLE_CLIENT_ID
|
|
||||||
- VITE_GOOGLE_PICKER_API_KEY
|
|
||||||
- VITE_SHARE_POINT_CLIENT_ID
|
|
||||||
- VITE_CONFLUENCE_CLIENT_ID
|
|
||||||
- VITE_NOTIFICATION_TEXT
|
|
||||||
- VITE_NOTIFICATION_LINK
|
|
||||||
- VITE_ENABLE_VOICE_INPUT
|
|
||||||
- VITE_DISABLE_SOURCE_FE
|
|
||||||
- VITE_USE_V
|
|
||||||
ports:
|
|
||||||
- "5173:5173"
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
image: arc53/docsgpt:${DOCSGPT_IMAGE_TAG:-latest}${DOCSGPT_IMAGE_VARIANT:-}
|
image: arc53/docsgpt:${DOCSGPT_IMAGE_TAG:-latest}${DOCSGPT_IMAGE_VARIANT:-}
|
||||||
# Same as docker-compose-hub.yaml: the data volumes are written by root so
|
# Same as docker-compose-hub.yaml: the data volumes are written by root so
|
||||||
@@ -62,10 +53,10 @@ services:
|
|||||||
- CELERY_BROKER_URL=redis://redis:6379/0
|
- CELERY_BROKER_URL=redis://redis:6379/0
|
||||||
- CELERY_RESULT_BACKEND=redis://redis:6379/1
|
- CELERY_RESULT_BACKEND=redis://redis:6379/1
|
||||||
- CACHE_REDIS_URL=redis://redis:6379/2
|
- CACHE_REDIS_URL=redis://redis:6379/2
|
||||||
- POSTGRES_URI=postgresql://docsgpt:docsgpt@postgres:5432/docsgpt
|
- POSTGRES_URI=postgresql://docsgpt:${POSTGRES_PASSWORD:-docsgpt}@postgres:5432/docsgpt
|
||||||
- EMBEDDINGS_NAME=${EMBEDDINGS_NAME:-ibm-granite/granite-embedding-311m-multilingual-r2}
|
- EMBEDDINGS_NAME=${EMBEDDINGS_NAME:-ibm-granite/granite-embedding-311m-multilingual-r2}
|
||||||
ports:
|
ports:
|
||||||
- "7091:7091"
|
- "${DOCSGPT_BIND:-127.0.0.1}:${DOCSGPT_PORT:-7091}:7091"
|
||||||
volumes:
|
volumes:
|
||||||
- indexes:/app/indexes
|
- indexes:/app/indexes
|
||||||
- inputs:/app/inputs
|
- inputs:/app/inputs
|
||||||
@@ -90,7 +81,7 @@ services:
|
|||||||
- CELERY_BROKER_URL=redis://redis:6379/0
|
- CELERY_BROKER_URL=redis://redis:6379/0
|
||||||
- CELERY_RESULT_BACKEND=redis://redis:6379/1
|
- CELERY_RESULT_BACKEND=redis://redis:6379/1
|
||||||
- CACHE_REDIS_URL=redis://redis:6379/2
|
- CACHE_REDIS_URL=redis://redis:6379/2
|
||||||
- POSTGRES_URI=postgresql://docsgpt:docsgpt@postgres:5432/docsgpt
|
- POSTGRES_URI=postgresql://docsgpt:${POSTGRES_PASSWORD:-docsgpt}@postgres:5432/docsgpt
|
||||||
- API_URL=http://backend:7091
|
- API_URL=http://backend:7091
|
||||||
- EMBEDDINGS_NAME=${EMBEDDINGS_NAME:-ibm-granite/granite-embedding-311m-multilingual-r2}
|
- EMBEDDINGS_NAME=${EMBEDDINGS_NAME:-ibm-granite/granite-embedding-311m-multilingual-r2}
|
||||||
volumes:
|
volumes:
|
||||||
@@ -112,7 +103,7 @@ services:
|
|||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_USER=docsgpt
|
- POSTGRES_USER=docsgpt
|
||||||
- POSTGRES_PASSWORD=docsgpt
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-docsgpt}
|
||||||
- POSTGRES_DB=docsgpt
|
- POSTGRES_DB=docsgpt
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
@@ -123,8 +114,36 @@ services:
|
|||||||
retries: 10
|
retries: 10
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
image: caddy:2-alpine
|
||||||
|
profiles: [https]
|
||||||
|
environment:
|
||||||
|
- DOCSGPT_DOMAIN=${DOCSGPT_DOMAIN:-}
|
||||||
|
# The domain is checked here rather than with ${DOCSGPT_DOMAIN:?}: compose
|
||||||
|
# interpolates every service, so a required variable would break the stack
|
||||||
|
# for everyone who does not use this profile.
|
||||||
|
entrypoint: ["/bin/sh", "-c"]
|
||||||
|
command:
|
||||||
|
- >-
|
||||||
|
if [ -z "$$DOCSGPT_DOMAIN" ]; then
|
||||||
|
echo "caddy: set DOCSGPT_DOMAIN to the public domain" >&2; exit 1;
|
||||||
|
fi;
|
||||||
|
exec caddy reverse-proxy --from "$$DOCSGPT_DOMAIN" --to backend:7091
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
- "443:443/udp"
|
||||||
|
volumes:
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
indexes:
|
indexes:
|
||||||
inputs:
|
inputs:
|
||||||
vectors:
|
vectors:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
@@ -39,13 +39,14 @@ On a machine with internet access, pull the images and save them to one file:
|
|||||||
```bash
|
```bash
|
||||||
TAG=latest # or a release, e.g. 0.19.0
|
TAG=latest # or a release, e.g. 0.19.0
|
||||||
docker pull arc53/docsgpt:$TAG
|
docker pull arc53/docsgpt:$TAG
|
||||||
docker pull arc53/docsgpt-fe:$TAG
|
|
||||||
docker pull redis:6-alpine
|
docker pull redis:6-alpine
|
||||||
docker pull postgres:16-alpine
|
docker pull postgres:16-alpine
|
||||||
docker save -o docsgpt-images.tar \
|
docker save -o docsgpt-images.tar \
|
||||||
arc53/docsgpt:$TAG arc53/docsgpt-fe:$TAG redis:6-alpine postgres:16-alpine
|
arc53/docsgpt:$TAG redis:6-alpine postgres:16-alpine
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The backend image serves the web UI too, so the standalone stack needs no frontend image. Add `arc53/docsgpt-fe:$TAG` only if you run the checkout Compose files or Kubernetes, which use it.
|
||||||
|
|
||||||
Copy `docsgpt-images.tar` and the [standalone Compose file](/Deploying/Docker-Deploying#quickest-setup-pre-built-images-no-checkout) into the air-gapped network, then load the images (or push them to your internal registry):
|
Copy `docsgpt-images.tar` and the [standalone Compose file](/Deploying/Docker-Deploying#quickest-setup-pre-built-images-no-checkout) into the air-gapped network, then load the images (or push them to your internal registry):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -21,10 +21,13 @@ Docker is the recommended method for deploying DocsGPT, providing a consistent a
|
|||||||
|
|
||||||
Every release publishes ready-to-run images to Docker Hub (`arc53/docsgpt`,
|
Every release publishes ready-to-run images to Docker Hub (`arc53/docsgpt`,
|
||||||
`arc53/docsgpt-fe`) and GitHub Container Registry (`ghcr.io/arc53/docsgpt`,
|
`arc53/docsgpt-fe`) and GitHub Container Registry (`ghcr.io/arc53/docsgpt`,
|
||||||
`ghcr.io/arc53/docsgpt-fe`) for `linux/amd64` and `linux/arm64`. The images
|
`ghcr.io/arc53/docsgpt-fe`) for `linux/amd64` and `linux/arm64`.
|
||||||
contain everything the default configuration needs (embedding models,
|
`arc53/docsgpt` runs the API, serves the web UI and runs the worker;
|
||||||
tokenizers, tiktoken's encoding), so a fresh container makes no downloads on
|
`arc53/docsgpt-fe` is the separate frontend image the checkout Compose files
|
||||||
first use. You do not need the source tree to run them:
|
and Kubernetes use. The images contain everything the default configuration
|
||||||
|
needs (embedding models, tokenizers, tiktoken's encoding), so a fresh
|
||||||
|
container makes no downloads on first use. You do not need the source tree to
|
||||||
|
run them:
|
||||||
|
|
||||||
1. **Download the standalone Compose file** (also attached to every
|
1. **Download the standalone Compose file** (also attached to every
|
||||||
[release](https://github.com/arc53/DocsGPT/releases)):
|
[release](https://github.com/arc53/DocsGPT/releases)):
|
||||||
@@ -52,7 +55,9 @@ first use. You do not need the source tree to run them:
|
|||||||
docker compose -f docker-compose-standalone.yaml up -d
|
docker compose -f docker-compose-standalone.yaml up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
Then open [http://localhost:5173/](http://localhost:5173/). Data lives in
|
Then open [http://localhost:7091/](http://localhost:7091/). The web UI and
|
||||||
|
the API share that port, which is published on `127.0.0.1`: only this
|
||||||
|
machine can reach it until you change `DOCSGPT_BIND` (below). Data lives in
|
||||||
named Docker volumes; `docker compose -f docker-compose-standalone.yaml down`
|
named Docker volumes; `docker compose -f docker-compose-standalone.yaml down`
|
||||||
keeps it and `down -v` removes it.
|
keeps it and `down -v` removes it.
|
||||||
|
|
||||||
@@ -66,6 +71,77 @@ the shell, e.g. `DOCSGPT_IMAGE_TAG=0.20.0 DOCSGPT_IMAGE_VARIANT=-docling`.
|
|||||||
The same two variables drive `deployment/docker-compose-hub.yaml` in a
|
The same two variables drive `deployment/docker-compose-hub.yaml` in a
|
||||||
checkout.
|
checkout.
|
||||||
|
|
||||||
|
### Opening it from other machines
|
||||||
|
|
||||||
|
Publish the port on every interface and turn on authentication in `.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DOCSGPT_BIND=0.0.0.0
|
||||||
|
AUTH_TYPE=simple_jwt
|
||||||
|
JWT_SECRET_KEY=<a long random value, e.g. openssl rand -hex 32>
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run `docker compose -f docker-compose-standalone.yaml up -d` again. The UI
|
||||||
|
takes its API address from the page it was loaded from, so
|
||||||
|
`http://<server-address>:7091/` works without further settings. Without
|
||||||
|
`AUTH_TYPE`, anyone who can reach the port can use DocsGPT.
|
||||||
|
|
||||||
|
With `simple_jwt` the UI asks for a token, which the backend prints when it
|
||||||
|
starts: `docker compose -f docker-compose-standalone.yaml logs backend | grep "Simple JWT"`.
|
||||||
|
The token is signed with `JWT_SECRET_KEY`. Without that setting each container
|
||||||
|
generates its own secret, and a re-created container (after `pull` or a
|
||||||
|
settings change) gets a new one and so a new token. Over plain HTTP the token
|
||||||
|
travels as readable text; outside a trusted network, use HTTPS as below.
|
||||||
|
`DOCSGPT_PORT` changes the host port (default `7091`). See
|
||||||
|
[Authentication Settings](/Deploying/DocsGPT-Settings#authentication-settings) for the other modes.
|
||||||
|
|
||||||
|
### HTTPS with your own domain
|
||||||
|
|
||||||
|
The Compose file has an optional Caddy service that obtains and renews a
|
||||||
|
Let's Encrypt certificate and proxies to the backend.
|
||||||
|
|
||||||
|
1. Point the domain's DNS records at the machine and open ports 80 and 443.
|
||||||
|
2. Add to `.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
COMPOSE_PROFILES=https
|
||||||
|
DOCSGPT_DOMAIN=docs.example.com
|
||||||
|
AUTH_TYPE=simple_jwt
|
||||||
|
JWT_SECRET_KEY=<a long random value, e.g. openssl rand -hex 32>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run `docker compose -f docker-compose-standalone.yaml up -d` and open
|
||||||
|
`https://docs.example.com/`.
|
||||||
|
|
||||||
|
`COMPOSE_PROFILES=https` in `.env` makes every later `up`, `down` and `logs`
|
||||||
|
include Caddy. Leave `DOCSGPT_BIND` at its default: Caddy reaches the backend
|
||||||
|
over the Compose network.
|
||||||
|
|
||||||
|
### Database password
|
||||||
|
|
||||||
|
The Postgres password defaults to `docsgpt`; the database is only reachable
|
||||||
|
inside the Compose network. To use your own, set `POSTGRES_PASSWORD` in `.env`
|
||||||
|
before the first start, with URL-safe characters (e.g. `openssl rand -hex 24`).
|
||||||
|
Postgres reads it only when its volume is created, so changing it later does
|
||||||
|
not change the existing database's password.
|
||||||
|
|
||||||
|
### Upgrading from an earlier standalone file
|
||||||
|
|
||||||
|
Before this change the standalone file ran a separate frontend container on
|
||||||
|
port 5173 and published both ports on every interface. After downloading the
|
||||||
|
new file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose-standalone.yaml pull
|
||||||
|
docker compose -f docker-compose-standalone.yaml up -d --remove-orphans
|
||||||
|
```
|
||||||
|
|
||||||
|
`--remove-orphans` removes the old frontend container. Open port 7091 instead
|
||||||
|
of 5173. Your data volumes are unchanged. If you opened DocsGPT from other
|
||||||
|
machines, follow [Opening it from other machines](#opening-it-from-other-machines),
|
||||||
|
and remove `VITE_API_HOST` from `.env` if it points at `localhost`: the UI
|
||||||
|
would otherwise keep calling the visitor's own machine.
|
||||||
|
|
||||||
## Using the Source Checkout
|
## Using the Source Checkout
|
||||||
|
|
||||||
With a clone of the repository, `deployment/docker-compose-hub.yaml` runs the
|
With a clone of the repository, `deployment/docker-compose-hub.yaml` runs the
|
||||||
|
|||||||
@@ -11,6 +11,20 @@ The notable changes in each release. Every release on GitHub also carries
|
|||||||
[auto-generated notes](https://github.com/arc53/DocsGPT/releases) listing every merged pull
|
[auto-generated notes](https://github.com/arc53/DocsGPT/releases) listing every merged pull
|
||||||
request, and [Upgrading](/upgrading) covers the steps an existing deployment has to take.
|
request, and [Upgrading](/upgrading) covers the steps an existing deployment has to take.
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### The standalone Docker stack runs on one port
|
||||||
|
|
||||||
|
The `arc53/docsgpt` image now serves the web UI next to the API, the way `docsgpt api` does from
|
||||||
|
the Python package. `docker-compose-standalone.yaml` no longer runs a frontend container: the UI
|
||||||
|
and the API share port 7091, published on `127.0.0.1` by default. The UI takes its API address
|
||||||
|
from the page it was loaded from, so opening the stack from another machine works without
|
||||||
|
setting `VITE_API_HOST`. New Compose settings: `DOCSGPT_BIND` and `DOCSGPT_PORT` for where the
|
||||||
|
port is published, `POSTGRES_PASSWORD`, and an `https` profile that puts Caddy with an automatic
|
||||||
|
certificate in front of a public domain. The `arc53/docsgpt-fe` image is still published for the
|
||||||
|
checkout Compose files and Kubernetes. See
|
||||||
|
[Upgrading from an earlier standalone file](/Deploying/Docker-Deploying#upgrading-from-an-earlier-standalone-file).
|
||||||
|
|
||||||
## 0.20.0
|
## 0.20.0
|
||||||
|
|
||||||
### DocsGPT installs from PyPI
|
### DocsGPT installs from PyPI
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ import { Callout } from 'nextra/components'
|
|||||||
**Upgrading from 0.16.x?** User data moved from MongoDB to Postgres in 0.17.0. Follow the [Postgres Migration guide](/Deploying/Postgres-Migration) before running `docker compose pull` or `git pull` — existing deployments will not start cleanly without it.
|
**Upgrading from 0.16.x?** User data moved from MongoDB to Postgres in 0.17.0. Follow the [Postgres Migration guide](/Deploying/Postgres-Migration) before running `docker compose pull` or `git pull` — existing deployments will not start cleanly without it.
|
||||||
</Callout>
|
</Callout>
|
||||||
|
|
||||||
|
## Standalone Compose file: one port
|
||||||
|
|
||||||
|
The standalone Compose file (`docker-compose-standalone.yaml`) no longer runs a frontend container. The backend image serves the web UI on port 7091, and the port is published on `127.0.0.1` unless you set `DOCSGPT_BIND`. After downloading the new file, start it with `--remove-orphans` to remove the old frontend container, then open port 7091 instead of 5173. If you opened DocsGPT from other machines, see [Upgrading from an earlier standalone file](/Deploying/Docker-Deploying#upgrading-from-an-earlier-standalone-file). The checkout Compose files and the Kubernetes manifests are unchanged.
|
||||||
|
|
||||||
## Embedding models
|
## Embedding models
|
||||||
|
|
||||||
DocsGPT now runs embeddings through [FastEmbed](https://github.com/qdrant/fastembed) (ONNX Runtime) instead of SentenceTransformer. The models are the same and the vectors are identical, so **your existing index needs no action** — `all-mpnet-base-v2` keeps working exactly as before.
|
DocsGPT now runs embeddings through [FastEmbed](https://github.com/qdrant/fastembed) (ONNX Runtime) instead of SentenceTransformer. The models are the same and the vectors are identical, so **your existing index needs no action** — `all-mpnet-base-v2` keeps working exactly as before.
|
||||||
|
|||||||
+16
-2
@@ -1,4 +1,4 @@
|
|||||||
# DocsGPT backend image.
|
# DocsGPT image: the API, the web UI it serves, and the Celery worker.
|
||||||
#
|
#
|
||||||
# Build args:
|
# Build args:
|
||||||
# EXTRAS comma-separated optional extras to bake in, matching the
|
# EXTRAS comma-separated optional extras to bake in, matching the
|
||||||
@@ -15,6 +15,19 @@
|
|||||||
# docling's layout/table/OCR models. `python -m docsgpt.scripts.verify_offline`
|
# docling's layout/table/OCR models. `python -m docsgpt.scripts.verify_offline`
|
||||||
# under `docker run --network none` proves it.
|
# under `docker run --network none` proves it.
|
||||||
|
|
||||||
|
# The web UI, built by the same script the Python package build runs. The API
|
||||||
|
# serves it from docsgpt/static (docsgpt/ui.py). The output is static files, so
|
||||||
|
# this stage runs on the build machine's platform whatever the target is.
|
||||||
|
FROM --platform=$BUILDPLATFORM node:22-bookworm-slim AS ui
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
COPY frontend/package.json frontend/package-lock.json frontend/
|
||||||
|
RUN cd frontend && npm ci --include=dev --no-audit --no-fund
|
||||||
|
COPY frontend/ frontend/
|
||||||
|
COPY scripts/build_frontend.sh scripts/
|
||||||
|
RUN mkdir docsgpt && bash scripts/build_frontend.sh
|
||||||
|
|
||||||
|
|
||||||
FROM ubuntu:24.04 AS builder
|
FROM ubuntu:24.04 AS builder
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
@@ -87,7 +100,7 @@ RUN if [ "$INSTALL_TESSERACT" = "true" ]; then \
|
|||||||
|
|
||||||
LABEL org.opencontainers.image.source="https://github.com/arc53/DocsGPT" \
|
LABEL org.opencontainers.image.source="https://github.com/arc53/DocsGPT" \
|
||||||
org.opencontainers.image.title="DocsGPT" \
|
org.opencontainers.image.title="DocsGPT" \
|
||||||
org.opencontainers.image.description="DocsGPT backend: API and Celery worker" \
|
org.opencontainers.image.description="DocsGPT: API, web UI and Celery worker" \
|
||||||
org.opencontainers.image.licenses="MIT"
|
org.opencontainers.image.licenses="MIT"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
@@ -136,6 +149,7 @@ RUN if python -c "import docling" 2>/dev/null; then \
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
COPY --chown=appuser:appuser docsgpt /app/docsgpt
|
COPY --chown=appuser:appuser docsgpt /app/docsgpt
|
||||||
|
COPY --from=ui --chown=appuser:appuser /src/docsgpt/static /app/docsgpt/static
|
||||||
# One-release alias so `-A application.app.celery` style entry points keep working.
|
# One-release alias so `-A application.app.celery` style entry points keep working.
|
||||||
COPY --chown=appuser:appuser application/__init__.py /app/application/__init__.py
|
COPY --chown=appuser:appuser application/__init__.py /app/application/__init__.py
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user