DockerSelf-HostingAI

RAGFlow with Docker: RAG over PDFs and scanned documents (Linux, Windows, Mac)

Before you start

  • 21 min read

Boxes marked Run in terminal are what you type; plain text explains why. Check what you need first

What you get in one minute#

RAGFlow is an open-source RAG engine that reads your PDFs, Word files and scanned pages with its own layout and OCR models, cuts them into chunks, and answers questions with citations that point back to the source page.

RAGFlow official logo

Logo: the official RAGFlow project (github.com/infiniflow/ragflow)

It is the tool to pick when your documents are messy: scans, tables, two-column papers, manuals. You run one Docker Compose stack, add a chat model and an embedding model, and keep everything on your own machine if the models are local. This guide pins the last stable release, adds a local Ollama, and spends extra time on what trips people up: the vm.max_map_count setting and RAM.

  • Reads scans. The default PDF parser, DeepDoc, does OCR, table recognition and layout analysis. The "Naive" parser skips all of that.
  • Shows its work. You can open and edit every chunk, test retrieval, and see which chunks an answer used.
  • Private if you want it. With Ollama, documents, chunks and questions never leave the host.
At a glanceDetail
Version used herev0.27.3 (stable, October 2026). The newest tag is v1.0.0-rc3, a release candidate created the day this page was checked (see "The 1.0 line" below)
LicenceApache-2.0
Download sizeDocs: about 2 GB compressed, about 7 GB unpacked. Docker Hub lists 3.6 GB for this tag.
RAMOfficial starting point 16 GB. We did not measure; see "How much RAM it really needs".
Ports80 (web), 9380 (API), 9381 (admin API); dependency ports 1200, 3306, 9000, 9001, 6379
Official docsragflow.io/docs and the GitHub repository

How it fits together#

You upload a file, RAGFlow parses it, an embedding model turns each chunk into a vector, Elasticsearch stores them, and at question time the best chunks go to a chat model that writes the answer.

You upload a PDF to the RAGFlow web UI, which stores the file in MinIO and queues a DeepDoc parse; chunks go to Ollama bge-m3, vectors and text go to Elasticsearch, and the best chunks plus your question go to Ollama llama3.2, which writes an answer with sources

Diagram: one document and one question in v0.27.3, October 2026. MySQL (accounts, settings) and Valkey (task queue) also run and are left out.

Before you start#

SystemWhat you need
LinuxAn x86-64 machine, Docker Engine with Compose v2.26.1 or newer, git, 4 cores, 16 GB RAM, 50 GB free disk
WindowsDocker Desktop with the WSL 2 backend, git, and enough memory for WSL 2 (default: 50% of your RAM, so a 16 GB PC gives Docker only 8 GB)
MacDocker Desktop and git. An Intel Mac matches the official x86 images; Apple Silicon has no arm64 image for v0.27.3 (below).

Check the tools first:

Run in terminalbash
docker --version
docker compose version
git --version

Docker must be 24.0.0 or newer, Compose v2.26.1 or newer.

  • [ ] Docker is running with 16 GB of RAM to use and 50 GB of free disk
  • [ ] ports 80 and 443 are free (or you plan to change them, see the HTTPS section)
  • [ ] your CPU is x86-64 (the official image is amd64 only)
  • [ ] a safe place for .env, which will hold the passwords
  • [ ] for public HTTPS only: a domain, DNS pointing at the host, ports 80 and 443 open

Apple Silicon. The v0.27.3 quickstart says RAGFlow does not maintain ARM images. Docker Desktop can emulate amd64, but RAGFlow does not document it and we did not try it. Use an Intel or Linux machine, or read "The 1.0 line".

Tested on October 2026: not test-run by DIY Lab Hub. Every command comes from the official quickstart, README, FAQ and compose files at tag v0.27.3. Parts that are ours are marked "our own".

Step 1: Set vm.max_map_count#

Elasticsearch refuses to run when the kernel allows too few memory maps per process. The default is 65530; RAGFlow needs at least 262144. Forgetting it gives Can't connect to ES cluster. Infinity, the other engine, does not need it.

Tip: The value resets on reboot (Linux) and when Docker restarts (Windows, Mac). If RAGFlow worked yesterday and Elasticsearch loops today, check this first.

Linux#

Run in terminalbash
sysctl vm.max_map_count
sudo sysctl -w vm.max_map_count=262144
echo 'vm.max_map_count=262144' | sudo tee -a /etc/sysctl.d/99-ragflow.conf

The first line shows the value, the second applies it, the third keeps it after a reboot (the docs say /etc/sysctl.conf; a file in /etc/sysctl.d does the same).

Windows (PowerShell)#

Docker Desktop keeps the setting in its docker-desktop WSL instance. The quickstart gives:

Run in terminalpowershell
wsl -d docker-desktop -u root
sysctl -w vm.max_map_count=262144
exit

This resets when Docker restarts. To keep it, put this in %USERPROFILE%\.wslconfig, run wsl --shutdown, and start Docker Desktop again:

File contenttext
[wsl2]
kernelCommandLine = "sysctl.vm.max_map_count=262144"

In the same file, add memory=16GB under [wsl2] if your PC has the RAM; the default is 50% of it (Microsoft's .wslconfig documentation).

Mac (Terminal)#

Docker Desktop on a Mac runs Linux in a VM. The quickstart sets the value there:

Run in terminalbash
docker run --rm --privileged --pid=host alpine sysctl -w vm.max_map_count=262144

This resets when Docker Desktop restarts; the quickstart also describes a permanent LaunchDaemon route. Give Docker Desktop at least 16 GB under Settings, Resources.

Check it worked#

sysctl vm.max_map_count prints vm.max_map_count = 262144. On Windows run wsl -d docker-desktop -u root sysctl vm.max_map_count; on a Mac use the docker run line above without -w and the value.

Step 2: Download RAGFlow and pin the version#

The repository holds the Compose files. Check out the release tag so the files match the image (the README says this keeps entrypoint.sh in step). Everything lives under ~/docker_volumes/ragflow/: the repository in app/, backups in backups/.

Linux#

Run in terminalbash
mkdir -p ~/docker_volumes/ragflow/backups
git clone https://github.com/infiniflow/ragflow.git ~/docker_volumes/ragflow/app
cd ~/docker_volumes/ragflow/app/docker
git checkout -f v0.27.3

Windows (PowerShell)#

-c core.autocrlf=false keeps Linux line endings in the scripts Compose mounts into the container (our own precaution; issue 266 shows exec ./entrypoint.sh: no such file or directory on Windows, cause not named).

Codepowershell
New-Item -ItemType Directory -Force "$HOME\docker_volumes\ragflow\backups" | Out-Null
git clone -c core.autocrlf=false https://github.com/infiniflow/ragflow.git "$HOME\docker_volumes\ragflow\app"
cd "$HOME\docker_volumes\ragflow\app\docker"
git checkout -f v0.27.3

Mac (Terminal)#

Same commands as Linux:

Run in terminalbash
mkdir -p ~/docker_volumes/ragflow/backups
git clone https://github.com/infiniflow/ragflow.git ~/docker_volumes/ragflow/app
cd ~/docker_volumes/ragflow/app/docker
git checkout -f v0.27.3

Check it worked#

git describe --tags prints v0.27.3, and grep RAGFLOW_IMAGE .env shows RAGFLOW_IMAGE=infiniflow/ragflow:v0.27.3 first (the other lines are commented mirrors).

Step 3: Change the passwords before the first start#

The .env file warns: do not deploy with default passwords. All four defaults are infini_rag_flow. The databases take their password when their data folder is first created, so set new ones before the first start. We also set COMPOSE_PROJECT_NAME=ragflow (our own) so volumes are named ragflow_... instead of after the folder docker, which other projects may share.

Linux#

Run in terminalbash
cd ~/docker_volumes/ragflow/app/docker
for k in ELASTIC_PASSWORD MYSQL_PASSWORD MINIO_PASSWORD REDIS_PASSWORD; do
  sed -i.bak "s/^$k=.*/$k=$(openssl rand -hex 24)/" .env
done
printf '\nCOMPOSE_PROJECT_NAME=ragflow\n' >> .env
rm .env.bak
chmod 600 .env

Windows (PowerShell)#

Run in terminalpowershell
cd "$HOME\docker_volumes\ragflow\app\docker"
$f = Join-Path (Get-Location) '.env'
$t = [System.IO.File]::ReadAllText($f)
foreach ($k in 'ELASTIC_PASSWORD','MYSQL_PASSWORD','MINIO_PASSWORD','REDIS_PASSWORD') {
  $b = [byte[]]::new(24)
  [System.Security.Cryptography.RandomNumberGenerator]::Fill($b)
  $v = -join ($b | ForEach-Object { $_.ToString('x2') })
  $t = $t -replace "(?m)^$k=.*", "$k=$v"
}
$t += "`nCOMPOSE_PROJECT_NAME=ragflow`n"
[System.IO.File]::WriteAllText($f, $t)

Mac (Terminal)#

Same commands as Linux (sed -i.bak works on both GNU and macOS sed):

Run in terminalbash
cd ~/docker_volumes/ragflow/app/docker
for k in ELASTIC_PASSWORD MYSQL_PASSWORD MINIO_PASSWORD REDIS_PASSWORD; do
  sed -i.bak "s/^$k=.*/$k=$(openssl rand -hex 24)/" .env
done
printf '\nCOMPOSE_PROJECT_NAME=ragflow\n' >> .env
rm .env.bak
chmod 600 .env

Copy .env to your password manager now.

Tip: .env is a tracked file. Upgrading with git checkout -f throws your edits and passwords away; the update section shows the safe way.

Check it worked#

grep -E "^(ELASTIC|MYSQL|MINIO|REDIS)_PASSWORD" .env (PowerShell: Select-String "_PASSWORD=" .env) shows four random strings, none infini_rag_flow.

Step 4: Start the stack and wait for it#

The default profile is CPU. The first run downloads the images.

Linux#

Run in terminalbash
docker compose -f docker-compose.yml up -d
docker compose -f docker-compose.yml logs -f ragflow-cpu

Windows (PowerShell)#

Run in terminalpowershell
docker compose -f docker-compose.yml up -d
docker compose -f docker-compose.yml logs -f ragflow-cpu

Mac (Terminal)#

Same commands as Linux:

Run in terminalbash
docker compose -f docker-compose.yml up -d
docker compose -f docker-compose.yml logs -f ragflow-cpu

Ctrl+C leaves the log view; the stack keeps running.

Check it worked#

Wait for the banner the quickstart shows as its success sign (official expected output):

Codetext
     ____   ___    ______ ______ __
    / __ \ /   |  / ____// ____// /____  _      __
   / /_/ // /| | / / __ / /_   / // __ \| | /| / /
  / _, _// ___ |/ /_/ // __/  / // /_/ /| |/ |/ /
 /_/ |_|/_/  |_|\____//_/    /_/ \____/ |__/|__/

 * Running on all addresses (0.0.0.0)

Then open http://localhost (port 80, so no port number) and register the first account. Opening the page before the banner can show network anomaly; wait and reload.

Then close the door: set REGISTER_ENABLED=0 and ENABLE_REGISTER=0 in .env and run docker compose -f docker-compose.yml up -d again. Registration ships switched on, so anyone who can open the page can create an account.

Step 5: Run Ollama and pull two models#

The official docs use Ollama as the local example, with llama3.2 (3B chat model, 2.0 GB) and bge-m3 (567M multilingual embedding model, 1.2 GB). We run Ollama as a second Compose project on RAGFlow's network, so nothing is published to your host. This layout is our own; the official route is below.

Linux#

Run in terminalbash
mkdir -p ~/docker_volumes/ollama/data
cd ~/docker_volumes/ollama
cat > compose.yaml <<'EOF'
services:
  ollama:
    image: ollama/ollama:0.40.13
    container_name: ollama
    restart: unless-stopped
    volumes:
      - ./data:/root/.ollama
    networks:
      - ragflow
networks:
  ragflow:
    external: true
    name: ragflow_ragflow
EOF
docker compose up -d
docker exec ollama ollama pull llama3.2
docker exec ollama ollama pull bge-m3

Windows (PowerShell)#

Codepowershell
New-Item -ItemType Directory -Force "$HOME\docker_volumes\ollama\data" | Out-Null
cd "$HOME\docker_volumes\ollama"
@'
services:
  ollama:
    image: ollama/ollama:0.40.13
    container_name: ollama
    restart: unless-stopped
    volumes:
      - ./data:/root/.ollama
    networks:
      - ragflow
networks:
  ragflow:
    external: true
    name: ragflow_ragflow
'@ | Set-Content -Encoding utf8 compose.yaml
docker compose up -d
docker exec ollama ollama pull llama3.2
docker exec ollama ollama pull bge-m3

Mac (Terminal)#

Same commands as Linux.

Docker on Windows and Mac gives the container no GPU; for a GPU use the native Ollama app (below).

Check it worked#

Run in terminalbash
docker exec ollama ollama list
docker compose -f ~/docker_volumes/ragflow/app/docker/docker-compose.yml exec ragflow-cpu curl -s http://ollama:11434/

The list shows both models. The second command tests the connection from inside the RAGFlow container and should answer Ollama is running (the official check, with our service name). In PowerShell write the path as "$HOME\docker_volumes\ragflow\app\docker\docker-compose.yml".

Using an Ollama that is already on your host#

A native Ollama suits a GPU. RAGFlow's docs then use http://host.docker.internal:11434, which the Compose file maps to the host. On Linux, native Ollama listens on 127.0.0.1 only: set OLLAMA_HOST=0.0.0.0:11434 (systemctl edit ollama.service, per the Ollama FAQ) and firewall port 11434, as the RAGFlow docs warn.

Step 6: Connect the models and parse a scanned PDF#

Linux#

In the browser, open your avatar at the top right, then Model providers, and choose Ollama. Add two models:

Model nameModel typeBase URL
llama3.2chathttp://ollama:11434
bge-m3embeddinghttp://ollama:11434

Then open System Model Settings and set llama3.2 as Chat model and bge-m3 as Embedding model.

Windows (PowerShell)#

Same screens and values as Linux.

Mac (Terminal)#

Same screens and values as Linux.

Tip: The model name and type must match Ollama's, letter for letter. Copy the name from docker exec ollama ollama list.

Now the documents:

  1. Open Dataset, then Create dataset. Name it, choose bge-m3 as embedding model and the General chunking method.
  2. In the dataset configuration, check the PDF parser: DeepDoc (the default) does the OCR, table and layout work. Keep it for scans.
  3. Add file, upload a PDF, then press the play button to parse. A scan takes longer than a text PDF, because OCR runs on every page.
  4. Open the parsed file to see the chunks. Double-click one to fix a recognition error or add keywords.
  5. In Retrieval testing, ask something whose answer you know is on a given page, and check the right chunk comes back before you build a chat.
  6. In Chat, create an assistant, pick the dataset and llama3.2, and ask the same question. The answer shows the chunks it used.

Tip: Choose the embedding model before you parse anything. Once a file is parsed, the v0.27.3 docs say it cannot be changed: every chunk must live in the same vector space.

Check it worked#

The file shows a finished parse, the chunks hold readable text from your scan, and retrieval testing returns the page you expected.

Put it behind HTTPS (with or without Traefik)#

This is for a server with a domain. If RAGFlow only runs at home on http://localhost, skip it.

RAGFlow publishes ports 80 and 443 itself, and a proxy on the same host needs them. Move RAGFlow to 8080 and 8443 in .env (the README's "change the serving port" knob), then run docker compose -f docker-compose.yml up -d again:

File contenttext
SVR_WEB_HTTP_PORT=8080
SVR_WEB_HTTPS_PORT=8443

Tip: Anything that proxies to RAGFlow must use the new port. A Caddyfile that still says localhost:80 ends at your proxy itself.

With Traefik#

Our own override file puts the RAGFlow container on the external proxy network. Save it as docker-compose.traefik.yml next to docker-compose.yml:

File contentyaml
services:
  ragflow-cpu:
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.ragflow.rule=Host(`<your-domain>`)"
      - "traefik.http.routers.ragflow.entrypoints=https"
      - "traefik.http.routers.ragflow.tls=true"
      - "traefik.http.services.ragflow.loadbalancer.server.port=80"
networks:
  proxy:
    external: true

Naming the first file with -f switches off Compose's automatic docker-compose.override.yml, so pass both files:

Run in terminalbash
docker network create proxy
docker compose -f docker-compose.yml -f docker-compose.traefik.yml up -d

Without Traefik: Caddy#

Choose this if you have no Traefik yet and run one small server. Caddy gets and renews certificates by itself.

Your caseWhat Caddy doesWhat you do
Public domainAutomatic Let's Encrypt certificatePoint a DNS A record at the server; open ports 80 and 443
Home only, no domaintls internal: Caddy's own local certificateTrust Caddy's root certificate on each device (below)

Caddyfile (RAGFlow listens on 8080 after the change above):

File contenttext
ragflow.example.com {
    reverse_proxy localhost:8080
}

Home-only variant (point ragflow.home.arpa at the server in your router or hosts file):

File contenttext
ragflow.home.arpa {
    tls internal
    reverse_proxy localhost:8080
}
  • Linux: install from the official apt repository (caddyserver.com/docs/install), save the Caddyfile as /etc/caddy/Caddyfile, then sudo systemctl reload caddy.
  • Windows (PowerShell): winget install CaddyServer.Caddy, then caddy run --config Caddyfile.
  • Mac: brew install caddy, then caddy run --config Caddyfile.
  • Docker: put the Caddyfile in ~/docker_volumes/caddy/, join RAGFlow's network, and use reverse_proxy ragflow-cpu:80:
File contentyaml
services:
  caddy:
    image: caddy:2.11.7
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ~/docker_volumes/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
      - ~/docker_volumes/caddy/data:/data
    networks:
      - ragflow
networks:
  ragflow:
    external: true
    name: ragflow_ragflow

Home-only: trust Caddy's root certificate (pki/authorities/local/root.crt in Caddy's data folder).

  • Linux: sudo caddy trust on the Caddy machine; on other devices copy root.crt to /usr/local/share/ca-certificates/ and run sudo update-ca-certificates.
  • Windows: caddy trust in an administrator PowerShell; on other devices install root.crt into "Trusted Root Certification Authorities".
  • Mac: caddy trust; on other Macs add root.crt in Keychain Access as "Always Trust".

Streamed chat answers work: Caddy's docs say text/event-stream responses are flushed immediately. Check it worked: curl -I https://ragflow.example.com answers over HTTP/2.

Security and testing#

  • Passwords and registration. New passwords in Step 3, registration off after your account (Step 4); chmod 600 .env on Linux and Mac.
  • Published ports. The official Compose file publishes Elasticsearch (1200), MySQL (3306), MinIO (9000, 9001) and Valkey (6379) on every interface, although RAGFlow reaches them over the Docker network. On a server, block them with the firewall and expose only 80 and 443. Binding them to loopback with ES_PORT=127.0.0.1:1200 is valid Compose syntax (our own idea, not tested).
  • Ollama. In this guide it is not published at all. Never publish 11434 to the internet.
  • What leaves the machine. Image pulls, the repository clone, Ollama model pulls, and possibly DeepDoc model files from Hugging Face on first parse (FAQ). A cloud chat or embedding provider would receive your chunks and questions. We found no telemetry setting in the .env, README or docs; we did not capture traffic.
  • Test. docker compose -f docker-compose.yml ps shows all services up, the log shows the banner, retrieval testing returns the right chunk, and a chat answer cites it.

How much RAM it really needs#

There is no official measured number. The docs give a starting point and the compose files show where memory goes. We did not run the stack, so this table is what the official files say plus our reading.

PieceWhat the official files sayOur reading
Whole stack16 GB RAM or more, 4 cores, 50 GB diskA starting point for the stack alone, not stack plus models
ElasticsearchCapped by MEM_LIMIT=8073741824 bytes (7.5 GiB); heap sized automatically from the cap (Elastic docs)The biggest single user
MySQL and ValkeyInnoDB buffer pool 1 GiB; Valkey --maxmemory 1gbAbout 2 GB together
RAGFlow containerNo cap; "some parsers ... require significant memory" (FAQ)Grows with parsing; scans cost more than text PDFs
Ollama modelsllama3.2 2.0 GB, bge-m3 1.2 GB downloadsAt least that much RAM while loaded

The caps alone add up to about 9.5 GiB before parsing and models. On 16 GB that is possible but tight; 32 GB is comfortable (our estimate). On Windows the real ceiling is WSL 2's share, 50% of the PC's RAM by default.

Tip: If parsing stops near the end or the log shows Killed, suspect RAM. The FAQ's first fix is a bigger MEM_LIMIT in .env.

Elasticsearch or Infinity#

Elasticsearch 8.11.3 is the default and needs the vm.max_map_count step. Infinity (infiniflow/infinity:v0.7.4-x64-v3) does not, but its README asks for an x86-64 CPU with AVX2. The docs list no RAM saving for Infinity, so do not switch to save memory unless you test it. Choose before you parse anything: the official switch is docker compose -f docker/docker-compose.yml down -v plus DOC_ENGINE=infinity, and -v deletes every volume.

Common mistakes#

MistakeWhy it happensDo this instead
Skipping vm.max_map_count, or setting it onceIt resets on reboot (Linux) and Docker restart (Windows, Mac); Elasticsearch loops and you see Can't connect to ES clusterMake it permanent (/etc/sysctl.d, .wslconfig) and check it first when RAGFlow stops
localhost or 127.0.0.1 as the Ollama addressInside the RAGFlow container that is the container itself (issue 19287, the FAQ)http://ollama:11434 here, or http://host.docker.internal:11434 for an Ollama on the host
Starting RAGFlow without checking out the tagCompose files and image drift apart; an answer in issue 14029 says to clone the tagged version, as the README doesgit checkout -f v0.27.3 and keep RAGFLOW_IMAGE on the same tag
Default passwords, open registration, published database portsThe stack starts fine, so nothing forces youNew passwords before the first start, REGISTER_ENABLED=0, a firewall
Changing passwords after the first startElasticsearch and MySQL read the password when their data folder is created, so stack and data disagreeSet them before the first start
docker compose down -v "to clean up"-v deletes the volumes; the upgrade page warns about itdocker compose down without -v, after a backup
Parsing a scan with the "Naive" PDF parserIt is faster; the docs say it skips OCR, tables and layout and is not recommended for scansKeep DeepDoc (default)
Too little memory for DockerWSL 2 gets 50% of your RAM by default; parsing is then killed (issue 7580, Killed ... task_executor.py)Raise memory= in .wslconfig or Docker Desktop, then MEM_LIMIT
AI assistant: writes infiniflow/ragflow:v0.21.1-slim or another -slim tagOld tutorials had two editions; the README says only one ships since v0.22.0 and the suffix is goneThe plain tag from docker/.env (v0.27.3)
AI assistant: says to open http://localhost:93809380 is the API; the README says the page is on port 80Open http://localhost; use 9380 for API calls

Tip: Before you paste any RAGFlow command from an AI answer, open docker/.env at your tag. It is the truth for image names, ports and variables.

Troubleshooting#

ProblemSolution
Elasticsearch restarts in a loopCheck vm.max_map_count (Step 1), then docker compose -f docker-compose.yml logs es01 --tail 100
Browser says network anomalyRAGFlow is still starting. Wait for the banner in docker compose -f docker-compose.yml logs ragflow-cpu, then reload
Fail to access model(Ollama/...)Ollama is down, the model is not pulled, the name differs, or the URL is unreachable from the RAGFlow container (below)
Parsing stuck below 1%, or stops near the end with no errorClick the red cross and parse again; read logs ragflow-cpu --tail 100. Usually RAM: more Docker memory, bigger MEM_LIMIT, fewer files at once
Garbled or empty chunks from a scanConfirm the PDF parser is DeepDoc, inspect the chunks, try a cleaner scan or the Docling or vision-model parser in the dataset settings
Index failureRAGFlow could not write chunks to the engine: check Elasticsearch health and disk space

Can't connect to ES cluster#

The quickstart ties this to vm.max_map_count being below 262144 after a reboot. Set it again (Step 1) and run docker compose -f docker-compose.yml up -d.

Max retries exceeded with url: /api/chat ... Connection refused#

The official Ollama page shows this for a wrong base URL. Test from inside the RAGFlow container: docker compose -f docker-compose.yml exec ragflow-cpu curl -s http://ollama:11434/ must print Ollama is running. Fix that before touching RAGFlow settings.

Known bugs#

  • Chat hangs with an Ollama model (issue 20065, open): the reporter saw no reply on v0.27.2 and the then-current main, while v0.26.4 worked. No fix is recorded. Try a smaller chat model and watch docker exec ollama ollama ps.
  • On the 1.0 candidate line, upload temp files fill /tmp (issue 21159) and Docling Serve on a private address is blocked (issue 21425). Both are open.

Diagnostics: docker compose -f docker-compose.yml ps, docker stats --no-stream, docker volume ls --filter name=ragflow_.

Updates and backups#

Update#

The upgrade page says to change both code and image: stop, update the code, check out the new tag, set RAGFLOW_IMAGE, pull, start. Its example uses git checkout -f, which overwrites your edited .env. Use git stash instead (our own change):

Run in terminalbash
cd ~/docker_volumes/ragflow/app/docker
cp .env ~/docker_volumes/ragflow/backups/env-before-update
docker compose -f docker-compose.yml down
git fetch --tags
git stash
git checkout <new-tag>
git stash pop
grep RAGFLOW_IMAGE .env
docker compose -f docker-compose.yml pull
docker compose -f docker-compose.yml up -d

In PowerShell the same commands work; the copy is Copy-Item .env "$HOME\docker_volumes\ragflow\backups\env-before-update". Read the release notes and take a backup first. Never add -v to down.

Backup#

The data lives in named volumes (ragflow_esdata01, ragflow_mysql_data, ragflow_minio_data, ragflow_redis_data). Our own script stops the stack for a consistent copy, tars each volume, copies .env, and starts again:

File contentbash
#!/usr/bin/env bash
set -euo pipefail
B=~/docker_volumes/ragflow/backups; D=$(date +%F)
cd ~/docker_volumes/ragflow/app/docker
docker compose -f docker-compose.yml stop
for v in esdata01 mysql_data minio_data redis_data; do
  docker run --rm -v "ragflow_$v":/data:ro -v "$B":/backup alpine:3.22 \
    tar czf "/backup/$v-$D.tar.gz" -C /data .
done
cp .env "$B/env-$D" && chmod 600 "$B/env-$D"
docker compose -f docker-compose.yml start

Save it as ~/docker_volumes/ragflow/backup.sh, chmod +x it, and add 0 3 * * * ~/docker_volumes/ragflow/backup.sh with crontab -e (Linux and Mac). On Windows use this PowerShell version (backup.ps1 in the same folder) and a Task Scheduler entry at 03:00:

Codepowershell
$B = "$HOME\docker_volumes\ragflow\backups"; $D = Get-Date -Format yyyy-MM-dd
Set-Location "$HOME\docker_volumes\ragflow\app\docker"
docker compose -f docker-compose.yml stop
foreach ($v in 'esdata01','mysql_data','minio_data','redis_data') {
  docker run --rm -v "ragflow_${v}:/data:ro" -v "${B}:/backup" alpine:3.22 tar czf "/backup/$v-$D.tar.gz" -C /data .
}
Copy-Item .env "$B\env-$D"
docker compose -f docker-compose.yml start
Run in terminalpowershell
schtasks /Create /SC DAILY /ST 03:00 /TN "RAGFlow backup" /TR "powershell -NoProfile -File $HOME\docker_volumes\ragflow\backup.ps1"

Restore test#

Test once with a throwaway volume: docker volume create restore_test, extract a tarball into it with docker run --rm -v restore_test:/data -v ~/docker_volumes/ragflow/backups:/backup alpine:3.22 tar xzf /backup/mysql_data-<date>.tar.gz -C /data, list it with docker run --rm -v restore_test:/data alpine:3.22 ls /data, then docker volume rm restore_test. A real restore is docker compose down, extracting each tarball into its empty volume, and up -d. We did not run this.

Performance and resources#

  • Watch it. docker stats --no-stream shows memory per container; run it while a big PDF parses.
  • Knobs in .env. MEM_LIMIT caps the engine containers; DOC_BULK_SIZE (default 4) and EMBEDDING_BATCH_SIZE (default 16) set how much is parsed and embedded at once, and larger values use more memory (FAQ).
  • GPU. The default is CPU. For DeepDoc on an Nvidia GPU the README says sed -i '1i DEVICE=gpu' .env before starting; we did not test it.

The 1.0 line#

The live docs today tell new users to check out v1.0.0-rc3. This guide stays on v0.27.3 on purpose: rc3 is a release candidate with no release notes yet, and the first 1.0 candidate says its data upgrade from v0.27.2 cannot be rolled back.

v0.27.3 (this guide)v1.0.0-rc3
StatusStable release, October 2026Release candidate, October 2026
BackendPythonGo rewrite; queue moved to NATS, cache to Kvrocks
Imageamd64 only, 3.6 GB on Docker Hubamd64 and arm64, about 360 MB on Docker Hub
DeepDocCPU or GPUCPU only
macOSNo arm64 imagearm64 image, but the docs say the Go backend does not support macOS for source builds

For an Apple Silicon image the 1.0 line is the only official arm64 choice. Read its release notes, back up, and follow its own quickstart, not this page's commands.

FAQ#

Is RAGFlow free? The code is Apache-2.0 and the images cost nothing. Cloud models cost money per use; the hosted cloud.ragflow.io has its own plans.

Does it work fully offline? After the images and Ollama models are pulled, questions and answers do. The FAQ says some parsers download DeepDoc model files from Hugging Face if not cached, so do your first parse while online.

Sources#

Checked against the official docs on 2026-10-30.