Repository navigation
Provider Docling Localhost
Run the Atlas Docling provider natively on the host. Atlas containers reach it
through host.docker.internal when DOC_PROCESSOR_SOURCE=docling-localhost.
It needs Python 3.10 or later and uv.
cd services/docling/provider/localhost
uv syncThis installs the locked dependencies, including docling==2.102.1 and
torch==2.13.0. The PyPI torch wheel supports CUDA on Linux x86_64 and MPS on
Apple Silicon, so no separate torch install is needed. Do not install another
torch with uv pip install: uv run restores the locked version.
From the repository root, start Atlas once so it generates and preserves
DOCLING_API_TOKEN in .env before the provider imports its settings:
# Terminal 1: return to the repository root after §1.1
cd ../../../..
./start.sh --doc-processor-source docling-localhostThe provider reads .env once, when it starts. If you started it before Atlas
created the token, restart it.
# Terminal 2, opened at the repository root
cd services/docling/provider/localhost
uv run server.pyThe server loads the repository .env (four levels up), then listens on
http://127.0.0.1:18159 by default (DOCLING_LOCALHOST_BIND_HOST and
DOCLING_LOCALHOST_PORT). Variables exported in the shell override .env.
The first conversion downloads Docling's layout and table models from Hugging Face, so it takes longer. Later runs reuse the cache.
Use Bash from the repository root after §1.1 installs the native dependencies.
Use the same shell settings as the running provider.
The loader reads repository .env with the server's shell precedence and ignores ATLAS_ENV_FILE.
It preserves usable token bytes and refuses absent, empty or whitespace-only credentials before curl.
An unset or empty native port uses 18159.
# Terminal 3, opened at the repository root while Atlas and the provider run
if ! docling_values="$(uv run --project services/docling/provider/localhost python - <<'PYTHON'
import os
import shlex
from pathlib import Path
from dotenv import load_dotenv
if Path(".env").exists():
load_dotenv(Path(".env"))
token = os.getenv("DOCLING_API_TOKEN", "")
if not token.strip():
raise SystemExit("DOCLING_API_TOKEN must be set in the shell or repository .env.")
port = int(os.getenv("DOCLING_LOCALHOST_PORT") or 18159)
print(f"export DOCLING_API_TOKEN={shlex.quote(token)}")
print(f"export DOCLING_LOCALHOST_PORT={shlex.quote(str(port))}")
print(f"export DOCLING_URL={shlex.quote(f'http://localhost:{port}')}")
PYTHON
)"; then
exit 1
fi
eval "$docling_values"
curl -X POST "${DOCLING_URL}/v1/document/convert" \
-H "Authorization: Bearer ${DOCLING_API_TOKEN}" \
-F "file=@document.pdf" \
-F "output_format=markdown" \
-F "table_mode=accurate"Atlas generates DOCLING_API_TOKEN in repository .env during §1.2.
The server loads that file once at startup; exported shell values take precedence, including empty values.
It ignores ATLAS_ENV_FILE.
With required authentication, an absent or empty token leaves protected routes unavailable.
Run this configuration block from services/docling/provider/localhost before starting the server.
Keep the generated token in repository .env, or export a token for the server shell.
These exports configure the server:
export DOCLING_LOCALHOST_PORT=18159 # Server port (default: 18159)
export DOCLING_LOCALHOST_BIND_HOST=127.0.0.1 # Listen address (see below)
export DOCLING_AUTH_MODE=required
export DOCLING_MAX_FILE_SIZE=52428800
export DOCLING_UPLOAD_TIMEOUT_SECONDS=120
export DOCLING_INFERENCE_TIMEOUT_SECONDS=900
export DOCLING_DEVICE=cpu # Device: cpu (default), cuda, mps
export DOCLING_OUTPUT_FORMAT=markdown # Format: markdown, html, json, doctags
export DOCLING_USE_OCR=auto # OCR: auto, always, never
export DOCLING_TABLE_MODE=accurate # Table mode: accurate, fast
export DOCLING_ENABLE_FORMULAS=true # Formula enrichment: true, false
export DOCLING_ENABLE_CODE_BLOCKS=true # Code enrichment: true, false
export HF_TOKEN=your_token_here # Hugging Face token (if needed)On Linux, containers reach the host through the Docker bridge, not loopback.
Bind the bridge IP, or 0.0.0.0 with DOCLING_AUTH_MODE=required.
The request's use_ocr and table_mode values override their environment
defaults. Device, formula enrichment and code enrichment are applied through
Docling's pinned PdfPipelineOptions API. Request validation rejects an
unsupported output format; the server never returns Markdown in its place.
export DOCLING_LOCALHOST_PORT=55021
uv run server.pySet the same DOCLING_LOCALHOST_PORT in the repository .env, so Atlas
containers use that port.
The provider uses Docling's converter: PDF, DOCX, PPTX, XLSX, HTML and
images (PNG, JPEG, TIFF). Docling does not convert legacy Office files (.doc,
.xls, .ppt). The Atlas backend sends those to Tika; see the
Document Processor README.
Uploaded Docling JSON retains data:, http: and https: image references.
Filesystem paths, file: URIs and other schemes are ignored before enrichment
or export, including page images. Embedded images and images from other input
formats keep their existing handling. The log reports only the discarded
count. The same rule applies to the GPU provider and LightRAG bundle.
- markdown - Markdown (default)
- html - HTML
- json - Docling document as JSON
- doctags - Docling's native DocTags format
Run §1.4 first in the same shell to export the usable token and native URL.
Before repeating §1.4, update or unset client-shell token and port exports to match the running provider.
The loader preserves existing exports, so changing repository .env alone does not replace them.
curl -X POST "${DOCLING_URL}/v1/document/convert" \
-H "Authorization: Bearer ${DOCLING_API_TOKEN}" \
-F "file=@report.pdf" \
-F "output_format=markdown"curl -X POST "${DOCLING_URL}/v1/document/convert" \
-H "Authorization: Bearer ${DOCLING_API_TOKEN}" \
-F "file=@scanned.pdf" \
-F "use_ocr=always" \
-F "table_mode=accurate"curl -X POST "${DOCLING_URL}/v1/document/convert" \
-H "Authorization: Bearer ${DOCLING_API_TOKEN}" \
-F "file=@document.docx" \
-F "enable_chunking=true" \
-F "chunk_size=512" \
-F "chunk_overlap=50"- accurate: the accurate TableFormer model (default).
- fast: the fast TableFormer model; quicker, with lower table quality.
- auto: OCR only where the document needs it, for example scanned pages.
- always: full-page OCR on every page.
- never: no OCR.
- Mathematical formulas (
DOCLING_ENABLE_FORMULAS) - Code blocks (
DOCLING_ENABLE_CODE_BLOCKS) - Document structure: headings, paragraphs, lists and tables
# Terminal 1, repository root: generate/preserve .env credentials and run Atlas
./start.sh --doc-processor-source docling-localhost
# Terminal 2, after Atlas has generated .env: start the provider
cd services/docling/provider/localhost
uv run server.pyAtlas remains in the foreground in Terminal 1; use the separate Terminal 2 for the native provider.
# Terminal 1, repository root: start Atlas first
./start.sh --base-port 55000 --doc-processor-source docling-localhost
# Terminal 2, repository root: the provider reads the port and token from .env
cd services/docling/provider/localhost
uv run server.pyEdit .env file:
DOC_PROCESSOR_SOURCE=docling-localhostThen start stack:
# Terminal 1, repository root
./start.sh
# Terminal 2, after Atlas has generated/preserved the credential
cd services/docling/provider/localhost
uv run server.pyFor long-lived use, run the provider under a service manager (systemd or
launchd) with restart-on-failure. After a conversion timeout the provider
exits with status 70, and a bare uv run server.py stays stopped.
Conversion time and memory depend on the device, the page count, tables, OCR
and table_mode. Atlas publishes no per-page figures. Benchmark
representative documents on the host before capacity planning.
# Use a different port, then set the same value in the repository .env
export DOCLING_LOCALHOST_PORT=18160
uv run server.pyDOCLING_DEVICE defaults to cpu; the server does not detect a GPU. Set
DOCLING_DEVICE=cuda or DOCLING_DEVICE=mps, then check that torch can see
the device:
uv run python -c "import torch; print(torch.cuda.is_available(), torch.backends.mps.is_available())"# Set a Hugging Face token if the download needs one
export HF_TOKEN=your_token_here
uv run server.py
# Check free disk space for the Hugging Face cache
df -h# Reinstall dependencies
uv sync --reinstall
# Or use fresh environment
rm -rf .venv
uv sync- Use
table_mode=fastfor faster, less accurate table extraction. - Use
use_ocr=neverwhen the documents have a text layer. - Set
DOCLING_DEVICEto an available GPU device (§8.2).
Docling downloads its layout and table models on first use and caches them in
the Hugging Face cache (~/.cache/huggingface/ by default).
The device comes from DOCLING_DEVICE only: cpu (default), cuda or
mps. An invalid device makes /health report unavailable.
Run §1.4 in the same shell first to export DOCLING_API_TOKEN and DOCLING_URL.
Use those settings for the Python and batch examples below.
import requests
import os
with open("document.pdf", "rb") as f:
response = requests.post(
f"{os.environ['DOCLING_URL']}/v1/document/convert",
headers={"Authorization": f"Bearer {os.environ['DOCLING_API_TOKEN']}"},
files={"file": f},
data={
"output_format": "markdown",
"table_mode": "accurate",
"enable_chunking": True,
"chunk_size": 512
}
)
result = response.json()
print(result["content"])
print(f"Processed {result['metadata']['pages']} pages")
print(f"Found {result['metadata']['tables']} tables")# Process multiple files; the response is JSON with the text in "content"
for file in *.pdf; do
curl -X POST "${DOCLING_URL}/v1/document/convert" \
-H "Authorization: Bearer ${DOCLING_API_TOKEN}" \
-F "file=@$file" \
-F "output_format=markdown" \
> "${file%.pdf}.json"
doneAtlas documentation.
- 1. Overview
- 2. Quick Start
- 3. Core Concepts
- 4. Tracks
-
5. Services
- 5.1. Service Catalog
-
5.2. Service Guides
- 5.2.1. airflow
- 5.2.2. asset-baker
- 5.2.3. asset-worker
- 5.2.4. backend
- 5.2.5. backup
- 5.2.6. blender-mcp
- 5.2.7. celery
- 5.2.8. chatterbox
- 5.2.9. cloud-providers
- 5.2.10. cloudflared
- 5.2.11. comfyui
- 5.2.12. crawl4ai
- 5.2.13. doc-processor
- 5.2.14. docling
- 5.2.15. docling-lightrag-adapter
- 5.2.16. fal
- 5.2.17. globals
- 5.2.18. grafana
- 5.2.19. hermes
- 5.2.20. iceberg-rest
- 5.2.21. jenkins
- 5.2.22. jupyterhub
- 5.2.23. kong
- 5.2.24. label-studio
- 5.2.25. langfuse
- 5.2.26. lightrag
- 5.2.27. litellm
- 5.2.28. llm-graph-builder
- 5.2.29. local-deep-researcher
- 5.2.30. loki
- 5.2.31. mcp-servers
- 5.2.32. minio
- 5.2.33. mlflow
- 5.2.34. multi2vec-clip
- 5.2.35. n8n
- 5.2.36. neo4j
- 5.2.37. ollama
- 5.2.38. open-webui
- 5.2.39. openclaw
- 5.2.40. otel-collector
- 5.2.41. parakeet
- 5.2.42. prometheus
- 5.2.43. ray
- 5.2.44. redis
- 5.2.45. redpanda
- 5.2.46. searxng
- 5.2.47. spark
- 5.2.48. speaches
- 5.2.49. stt-provider
- 5.2.50. supabase
- 5.2.51. supavisor
- 5.2.52. tei-reranker
- 5.2.53. tempo
- 5.2.54. tika
- 5.2.55. trino
- 5.2.56. trueforge
- 5.2.57. tts-provider
- 5.2.58. verba
- 5.2.59. vllm-metal
- 5.2.60. weaviate
- 5.2.61. zeppelin
- 5.3. Provider And Extension Guides
- 6. Configuration
- 7. Operations
- 8. Architecture
- 9. Development
- 10. Reference