x-log: &log
driver: json-file
options:
max-size: "10m"
max-file: "3"
x-hc-defaults: &hc
interval: 30s
timeout: 5s
retries: 10
start_period: 90s
services:
ollama:
image: ollama/ollama:${OLLAMA_VERSION}
container_name: ollama
environment:
TZ: ${TZ}
OLLAMA_HOST: 0.0.0.0:11434
# stabilité / perfs CPU
OLLAMA_NUM_PARALLEL: "1"
OLLAMA_MAX_LOADED_MODELS: "2"
OLLAMA_NUM_THREADS: "6"
# verrouillage CPU
GGML_VK_VISIBLE_DEVICES: "-1"
volumes:
- /volume1/docker/ai_stack/ollama:/root/.ollama:rw
healthcheck:
test: [ "CMD", "ollama", "list" ]
<<: *hc
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
networks:
ai_net: {}
ulimits:
nofile: 65535
init: true
logging: *log
restart: unless-stopped
open-webui:
image: ghcr.io/open-webui/open-webui:${OPENWEBUI_VERSION}
container_name: open-webui
depends_on:
ollama:
condition: service_started
environment:
TZ: ${TZ}
OLLAMA_BASE_URL: http://ollama:11434
WEBUI_URL: https://${OPENWEBUI_HOST}
WEBUI_SECRET_KEY: ${WEBUI_SECRET_KEY}
volumes:
- /volume1/docker/ai_stack/open-webui:/app/backend/data:rw
healthcheck:
test: [ "CMD-SHELL", "python3 -c \"import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8080/health', timeout=5).status < 500 else 1)\" || exit 1" ]
<<: *hc
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
networks:
ai_net: {}
edge_proxy: {}
labels:
- traefik.enable=true
- traefik.docker.network=edge_proxy
- traefik.http.routers.openwebui.tls.certresolver=ionosdns
- traefik.http.routers.openwebui.rule=Host(`${OPENWEBUI_HOST}`)
- traefik.http.routers.openwebui.entrypoints=websecure
- traefik.http.routers.openwebui.tls=true
- traefik.http.routers.openwebui.service=openwebui-svc
# Accès privé & VPN Wireguard par défaut
- traefik.http.routers.openwebui.middlewares=chain-private@file
- traefik.http.services.openwebui-svc.loadbalancer.server.port=8080
init: true
logging: *log
restart: unless-stopped
networks:
ai_net:
driver: bridge
name: ai_net
internal: true
edge_proxy:
external: true
name: edge_proxy