services: opensearch: image: docker.io/langflowai/openrag-opensearch:${OPENRAG_VERSION:-latest} build: context: . dockerfile: Dockerfile container_name: ${COMPOSE_PROJECT_NAME:-openrag}-opensearch environment: - discovery.type=single-node - OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_PASSWORD} - OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g - OPENRAG_BACKEND_PORT=${OPENRAG_BACKEND_PORT:-8000} - OPENRAG_BACKEND_HOST=${OPENRAG_BACKEND_HOST:-openrag-backend} - OPENRAG_BACKEND_INTERNAL_URL=${OPENRAG_BACKEND_INTERNAL_URL:-http://${OPENRAG_BACKEND_HOST:-openrag-backend}:${OPENRAG_BACKEND_PORT:-8000}} # NOTE: do NOT add `extra_hosts: openrag-backend:host-gateway` here. # `extra_hosts` writes to /etc/hosts, which libc resolves BEFORE # docker DNS — so the alias overrides docker-compose service-name # resolution unconditionally and routes OpenSearch's JWKS lookup to # the host gateway. In CI the host has nothing on port 8000, so JWT # validation breaks (every /search returns 401). Dev-local users who # run `make backend` on the host need the alias and should add it via # an override file (see AGENTS.md → Operational constraints). ports: - "${OPENSEARCH_PORT:-9200}:9200" - "${OPENSEARCH_PERF_PORT:-9600}:9600" volumes: - opensearch-data:/usr/share/opensearch/data stop_grace_period: 2m healthcheck: test: ["CMD-SHELL", "curl -ku admin:$$OPENSEARCH_PASSWORD 'https://localhost:9200/_cluster/health' -s | grep -qE '\"status\":\"(green|yellow)\"'"] interval: 15s timeout: 10s retries: 20 start_period: 60s restart: unless-stopped dashboards: image: docker.io/opensearchproject/opensearch-dashboards:3.8.0 container_name: ${COMPOSE_PROJECT_NAME:-openrag}-dashboards depends_on: - opensearch environment: OPENSEARCH_HOSTS: '["https://${OPENSEARCH_HOST:-opensearch}:${OPENSEARCH_INTERNAL_PORT:-9200}"]' OPENSEARCH_USERNAME: "${OPENSEARCH_USERNAME:-admin}" OPENSEARCH_PASSWORD: ${OPENSEARCH_PASSWORD} ports: - "${OPENSEARCH_DASHBOARDS_PORT:-5601}:5601" openrag-backend: image: docker.io/langflowai/openrag-backend:${OPENRAG_VERSION:-latest} build: context: . dockerfile: Dockerfile.backend container_name: ${COMPOSE_PROJECT_NAME:-openrag}-backend depends_on: - langflow environment: - OPENSEARCH_HOST=${OPENSEARCH_HOST:-opensearch} - LANGFLOW_URL=http://langflow:7860 - OPENRAG_BACKEND_INTERNAL_URL=${OPENRAG_BACKEND_INTERNAL_URL:-http://openrag-backend:${OPENRAG_BACKEND_PORT:-8000}} - OPENRAG_BACKEND_ROUTER_ENABLE=${OPENRAG_BACKEND_ROUTER_ENABLE:-false} - LANGFLOW_PUBLIC_URL=${LANGFLOW_PUBLIC_URL} - LANGFLOW_AUTO_LOGIN=${LANGFLOW_AUTO_LOGIN} - LANGFLOW_SUPERUSER=${LANGFLOW_SUPERUSER} - LANGFLOW_SUPERUSER_PASSWORD=${LANGFLOW_SUPERUSER_PASSWORD} - LANGFLOW_CHAT_FLOW_ID=${LANGFLOW_CHAT_FLOW_ID} - LANGFLOW_INGEST_FLOW_ID=${LANGFLOW_INGEST_FLOW_ID} - LANGFLOW_URL_INGEST_FLOW_ID=${LANGFLOW_URL_INGEST_FLOW_ID} - DISABLE_INGEST_WITH_LANGFLOW=${DISABLE_INGEST_WITH_LANGFLOW:-false} - OPENRAG_EMBEDDING_OVERFLOW_POLICY=${OPENRAG_EMBEDDING_OVERFLOW_POLICY:-} - INGEST_SAMPLE_DATA=${INGEST_SAMPLE_DATA:-true} - NUDGES_FLOW_ID=${NUDGES_FLOW_ID} - OPENSEARCH_PORT=${OPENSEARCH_INTERNAL_PORT:-9200} - OPENSEARCH_USERNAME=${OPENSEARCH_USERNAME:-admin} - OPENSEARCH_PASSWORD=${OPENSEARCH_PASSWORD} # Single-node compose clusters don't meet the multi-node readiness counts, # so default the node-count check off here (override to re-enable). - OPENSEARCH_NODE_COUNT_CHECK_ENABLED=${OPENSEARCH_NODE_COUNT_CHECK_ENABLED:-false} - OPENAI_API_KEY=${OPENAI_API_KEY} - AZURE_OPENAI_API_KEY=${AZURE_OPENAI_API_KEY:-${AZURE_API_KEY:-}} - AZURE_OPENAI_ENDPOINT=${AZURE_OPENAI_ENDPOINT:-${AZURE_API_BASE:-}} - AZURE_OPENAI_API_VERSION=${AZURE_OPENAI_API_VERSION:-${AZURE_API_VERSION:-}} - LLM_PROVIDER=${LLM_PROVIDER:-} - EMBEDDING_PROVIDER=${EMBEDDING_PROVIDER:-} - LLM_MODEL=${LLM_MODEL:-} - EMBEDDING_MODEL=${EMBEDDING_MODEL:-} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - WATSONX_API_KEY=${WATSONX_API_KEY} - WATSONX_ENDPOINT=${WATSONX_ENDPOINT} - WATSONX_PROJECT_ID=${WATSONX_PROJECT_ID} # Red Hat OpenShift AI. Two endpoints because vLLM serves one model per # InferenceService; RHOAI_TLS_VERIFY is a CA bundle path (or `false` for a # port-forward in development only). - RHOAI_ENDPOINT=${RHOAI_ENDPOINT:-} - RHOAI_EMBEDDINGS_ENDPOINT=${RHOAI_EMBEDDINGS_ENDPOINT:-} - RHOAI_API_KEY=${RHOAI_API_KEY:-} - RHOAI_TLS_VERIFY=${RHOAI_TLS_VERIFY:-} - RHOAI_EMBEDDING_MAX_CONCURRENCY=${RHOAI_EMBEDDING_MAX_CONCURRENCY:-} - OLLAMA_ENDPOINT=${OLLAMA_ENDPOINT} - GOOGLE_OAUTH_CLIENT_ID=${GOOGLE_OAUTH_CLIENT_ID} - GOOGLE_OAUTH_CLIENT_SECRET=${GOOGLE_OAUTH_CLIENT_SECRET} - MICROSOFT_GRAPH_OAUTH_CLIENT_ID=${MICROSOFT_GRAPH_OAUTH_CLIENT_ID} - MICROSOFT_GRAPH_OAUTH_CLIENT_SECRET=${MICROSOFT_GRAPH_OAUTH_CLIENT_SECRET} - WEBHOOK_BASE_URL=${WEBHOOK_BASE_URL} - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - AWS_S3_ENDPOINT=${AWS_S3_ENDPOINT} - AWS_REGION=${AWS_REGION} - IBM_COS_API_KEY=${IBM_COS_API_KEY} - IBM_COS_SERVICE_INSTANCE_ID=${IBM_COS_SERVICE_INSTANCE_ID} - IBM_COS_ENDPOINT=${IBM_COS_ENDPOINT} - IBM_COS_HMAC_ACCESS_KEY_ID=${IBM_COS_HMAC_ACCESS_KEY_ID} - IBM_COS_HMAC_SECRET_ACCESS_KEY=${IBM_COS_HMAC_SECRET_ACCESS_KEY} - IBM_COS_AUTH_ENDPOINT=${IBM_COS_AUTH_ENDPOINT} - OPENSEARCH_INDEX_NAME=${OPENSEARCH_INDEX_NAME:-documents} - OPENRAG_OPENSEARCH_NUMBER_OF_SHARDS=${OPENRAG_OPENSEARCH_NUMBER_OF_SHARDS:-1} - OPENRAG_OPENSEARCH_NUMBER_OF_REPLICAS=${OPENRAG_OPENSEARCH_NUMBER_OF_REPLICAS:-0} - OPENRAG_ENSURE_INDEX_REPLICAS_ON_STARTUP=${OPENRAG_ENSURE_INDEX_REPLICAS_ON_STARTUP:-false} - LANGFLOW_KEY=${LANGFLOW_KEY} - SEGMENT_WRITE_KEY=${SEGMENT_WRITE_KEY:-} - ENVIRONMENT=${ENVIRONMENT:-production} - LANGFLOW_KEY_RETRIES=${LANGFLOW_KEY_RETRIES:-15} - LANGFLOW_KEY_RETRY_DELAY=${LANGFLOW_KEY_RETRY_DELAY:-2.0} - LANGFLOW_VERSION=${LANGFLOW_VERSION} - LOG_FORMAT=${LOG_FORMAT} - SERVICE_NAME=${SERVICE_NAME} - SESSION_SECRET=${SESSION_SECRET:-your-secret-key-change-in-production} - JWT_SIGNING_KEY=${JWT_SIGNING_KEY} - OPENRAG_ENCRYPTION_KEY=${OPENRAG_ENCRYPTION_KEY} - LOG_LEVEL=${LOG_LEVEL:-INFO} - NO_COLOR=${NO_COLOR:-} - ACCESS_LOG=${ACCESS_LOG:-true} - LANGFLOW_TIMEOUT=${LANGFLOW_TIMEOUT:-2400} - LANGFLOW_CONNECT_TIMEOUT=${LANGFLOW_CONNECT_TIMEOUT:-30} - INGESTION_TIMEOUT=${INGESTION_TIMEOUT:-3600} - UPLOAD_BATCH_SIZE=${UPLOAD_BATCH_SIZE:-25} - OPENRAG_MAX_UPLOAD_MB=${OPENRAG_MAX_UPLOAD_MB:-100} - MAX_WORKERS=${MAX_WORKERS:-4} - IBM_AUTH_ENABLED=${IBM_AUTH_ENABLED:-false} - OPENRAG_AZURE_BLOB_ENABLED=${OPENRAG_AZURE_BLOB_ENABLED:-true} - PLATFORM_AUTH_DEV_MODE=${PLATFORM_AUTH_DEV_MODE:-false} - DOCLING_SERVE_URL=${DOCLING_SERVE_URL:-http://host.docker.internal:5001} - DOCLING_SERVE_VERIFY_SSL=${DOCLING_SERVE_VERIFY_SSL:-true} - CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGINS-http://localhost:3000} # Backend LLM tracing to Langfuse (opt-in, default off). Shares the # LANGFUSE_* keys with the langflow service below so both land in one # project. Metadata only unless content capture is opted into. - OPENRAG_TRACING_ENABLED=${OPENRAG_TRACING_ENABLED:-false} - OPENRAG_TRACING_CAPTURE_CONTENT=${OPENRAG_TRACING_CAPTURE_CONTENT:-false} - OPENRAG_TRACING_ALLOW_CONTENT_IN_SAAS=${OPENRAG_TRACING_ALLOW_CONTENT_IN_SAAS:-false} - LANGFUSE_SECRET_KEY=${LANGFUSE_SECRET_KEY:-} - LANGFUSE_PUBLIC_KEY=${LANGFUSE_PUBLIC_KEY:-} - LANGFUSE_BASE_URL=${LANGFUSE_BASE_URL:-} - LANGFUSE_HOST=${LANGFUSE_HOST:-} # Instana APM (opt-in, default off — see the INSTANA_* block in .env.example). # The agent runs on the HOST (`make instana-agent-up`, host networking), so a # containerized backend reaches it via the host.docker.internal alias mapped # in extra_hosts below — not via 127.0.0.1, which is the container loopback. - INSTANA_ENABLED=${INSTANA_ENABLED:-false} - INSTANA_AGENT_HOST=${INSTANA_AGENT_HOST:-host.docker.internal} - INSTANA_AGENT_PORT=${INSTANA_AGENT_PORT:-42699} # Performance guardrails — see the INSTANA_* block in .env.example for the # measurements behind these two defaults. Forwarded with a default rather # than bare so the safe value applies even when .env predates them: # `logging` avoids an unbounded per-warning span/event leak in the tracer, # `error` avoids a full stack capture on every httpx/urllib3/sqlalchemy # exit span. # # The two substitution forms differ on purpose. `-` (unset only) lets an # explicit empty value through, which is how you opt back into tracing # logging spans. `:-` (unset or empty) is required for the stack-trace # level because the tracer rejects an empty string, logging "Invalid # stack-trace value" on every boot and silently reverting to `all` — the # expensive setting this exists to avoid. Opt out with `all`, not ``. - INSTANA_TRACING_DISABLE=${INSTANA_TRACING_DISABLE-logging} - INSTANA_STACK_TRACE=${INSTANA_STACK_TRACE:-error} # Redact free-text query parameters before spans leave the host — a # privacy default, not a performance one. The tracer's own default # (contains-ignore-case:key,pass,secret) only catches credential-shaped # names, so without this OpenRAG's search text # (GET /v2/files/search?q=..., and the `search`/`filename` params) is # exported to Instana verbatim. Forwarded with `:-` (unset or empty), # same reasoning as INSTANA_STACK_TRACE above: an empty value fails the # tracer's own parser and falls back to the weak built-in default, so an # explicit empty override must not silently defeat this. Uses `\Z` # rather than a `$`-anchor (see the NOTE in .env.example) so the value # survives the Makefile's `include`/`export` of `.env` unmangled. - INSTANA_SECRETS=${INSTANA_SECRETS:-regex:.*key.*,.*pass.*,.*secret.*,.*token.*,q\Z,search\Z,filename\Z} # Listed bare rather than as `VAR=${VAR}` on purpose: the tracer tests these # for *presence*, not truthiness, so forwarding an empty string would set a # blank service name and log an "Unknown INSTANA_LOG_LEVEL" warning on every # boot. The bare form is omitted from the container entirely when unset. - INSTANA_SERVICE_NAME - INSTANA_LOG_LEVEL - INSTANA_ZONE volumes: - ${OPENRAG_DOCUMENTS_PATH:-./openrag-documents}:/app/openrag-documents:U,z - ${OPENRAG_KEYS_PATH:-./keys}:/app/keys:U,z - ${OPENRAG_FLOWS_PATH:-./flows}:/app/flows:U,z - ${OPENRAG_FLOWS_BACKUP_PATH:-./flows/backup}:/app/flows/backup:U,z - ${OPENRAG_CONFIG_PATH:-./config}:/app/config:U,z - ${OPENRAG_DATA_PATH:-./data}:/app/data:U,z # Linux: Docker Engine does not auto-inject host.docker.internal; map it to the host gateway extra_hosts: - "host.docker.internal:host-gateway" openrag-frontend: image: docker.io/langflowai/openrag-frontend:${OPENRAG_VERSION:-latest} build: context: . dockerfile: Dockerfile.frontend args: OPENRAG_FRONTEND_BASE_PATH: ${OPENRAG_FRONTEND_BASE_PATH:-} container_name: ${COMPOSE_PROJECT_NAME:-openrag}-frontend depends_on: - openrag-backend environment: - OPENRAG_BACKEND_HOST=openrag-backend ports: - "${FRONTEND_PORT:-3000}:3000" langflow: image: docker.io/langflowai/openrag-langflow:${OPENRAG_VERSION:-latest} build: context: . dockerfile: Dockerfile.langflow container_name: ${COMPOSE_PROJECT_NAME:-openrag}-langflow ports: - "${LANGFLOW_PORT:-7860}:7860" volumes: - ${OPENRAG_FLOWS_PATH:-./flows}:/app/flows:U,z - ${LANGFLOW_DATA_PATH:-./langflow-data}:/app/langflow-data:U,z # Linux: Docker Engine does not auto-inject host.docker.internal; map it to the host gateway extra_hosts: - "host.docker.internal:host-gateway" environment: - LANGFLOW_ALLOW_CUSTOM_COMPONENTS=${LANGFLOW_ALLOW_CUSTOM_COMPONENTS:-false} # Prefer the bind-mounted index so `scripts/update_openrag_component_index.py` # takes effect on `docker compose restart langflow` without an image rebuild. - LANGFLOW_COMPONENTS_INDEX_PATH=/app/flows/component_index.json - LANGFUSE_SECRET_KEY=${LANGFUSE_SECRET_KEY:-} - LANGFUSE_PUBLIC_KEY=${LANGFUSE_PUBLIC_KEY:-} - LANGFUSE_BASE_URL=${LANGFUSE_BASE_URL:-} - LANGFUSE_HOST=${LANGFUSE_HOST:-} - LANGFLOW_DEACTIVATE_TRACING # Hop token is injected per Langflow run. Seed a non-empty placeholder # so load_from_db can resolve OPENRAG_LLM_TOKEN; Langflow treats "" as # missing. Do not pass a vendor key here. - OPENAI_API_KEY=${LANGFLOW_OPENAI_API_KEY:-} - OPENRAG_LLM_TOKEN=None - OPENRAG_LLM_BASE_URL=${OPENRAG_LLM_BASE_URL:-} - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - WATSONX_APIKEY=${WATSONX_API_KEY} - WATSONX_URL=${WATSONX_URL:-${WATSONX_ENDPOINT}} - WATSONX_PROJECT_ID=${WATSONX_PROJECT_ID} - WATSONX_MAX_RETRIES=${WATSONX_MAX_RETRIES:-10} - WATSONX_DELAY_TIME=${WATSONX_DELAY_TIME:-0.5} - OLLAMA_BASE_URL=${OLLAMA_ENDPOINT} - LANGFLOW_CONFIG_DIR=/app/langflow-data - LANGFLOW_DATABASE_URL=${LANGFLOW_DATABASE_URL:-sqlite:////app/langflow-data/langflow.db?timeout=60} - LANGFLOW_DB_CONNECTION_SETTINGS=${LANGFLOW_DB_CONNECTION_SETTINGS:-{"pool_timeout":60}} - LANGFLOW_SECRET_KEY=${LANGFLOW_SECRET_KEY} - JWT=None - OWNER=None - OWNER_NAME=None - OWNER_EMAIL=None - CONNECTOR_TYPE=system - CONNECTOR_TYPE_URL=url - DOCUMENT_ID=None - SOURCE_URL=None - ALLOWED_USERS=[] - ALLOWED_GROUPS=[] - ALLOWED_PRINCIPALS=[] - OPENRAG-QUERY-FILTER="{}" - OPENRAG_INGEST_URL=OPENRAG_INGEST_URL - OPENRAG_INGEST_TOKEN=OPENRAG_INGEST_TOKEN - OPENRAG_INGEST_RUN_ID=OPENRAG_INGEST_RUN_ID - OPENRAG_INGEST_BATCH_SIZE=100 - OPENSEARCH_PASSWORD=${OPENSEARCH_PASSWORD} - OPENSEARCH_HOST=${OPENSEARCH_HOST:-opensearch} - OPENSEARCH_PORT=${OPENSEARCH_INTERNAL_PORT:-9200} - OPENSEARCH_URL=https://${OPENSEARCH_HOST:-opensearch}:${OPENSEARCH_INTERNAL_PORT:-9200} - OPENSEARCH_INDEX_NAME=${OPENSEARCH_INDEX_NAME:-documents} - DOCLING_SERVE_URL=${DOCLING_SERVE_URL:-http://host.docker.internal:5001} - DOCLING_SERVE_VERIFY_SSL=${DOCLING_SERVE_VERIFY_SSL:-true} - DOCLING_TASK_ID=None - FILENAME=None - MIMETYPE=None - FILESIZE=0 - SELECTED_EMBEDDING_MODEL=${SELECTED_EMBEDDING_MODEL:-text-embedding-3-small} - LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT=JWT,OPENRAG-QUERY-FILTER,OPENSEARCH_PASSWORD,OPENSEARCH_URL,DOCLING_SERVE_URL,DOCLING_SERVE_VERIFY_SSL,DOCLING_TASK_ID,OWNER,OWNER_NAME,OWNER_EMAIL,CONNECTOR_TYPE,DOCUMENT_ID,SOURCE_URL,ALLOWED_USERS,ALLOWED_GROUPS,ALLOWED_PRINCIPALS,FILENAME,MIMETYPE,FILESIZE,SELECTED_EMBEDDING_MODEL,OPENAI_API_KEY,OPENRAG_LLM_TOKEN,OPENRAG_LLM_BASE_URL,ANTHROPIC_API_KEY,WATSONX_APIKEY,WATSONX_URL,WATSONX_PROJECT_ID,OLLAMA_BASE_URL,OPENSEARCH_INDEX_NAME,OPENRAG_INGEST_URL,OPENRAG_INGEST_TOKEN,OPENRAG_INGEST_RUN_ID,OPENRAG_INGEST_BATCH_SIZE - LANGFLOW_LOG_LEVEL=${LANGFLOW_LOG_LEVEL:-INFO} - LANGFLOW_WORKERS=${LANGFLOW_WORKERS:-1} - LANGFLOW_RATE_LIMIT_PER_MINUTE=${LANGFLOW_RATE_LIMIT_PER_MINUTE:-100} - LANGFLOW_AUTO_LOGIN=${LANGFLOW_AUTO_LOGIN} - LANGFLOW_SUPERUSER=${LANGFLOW_SUPERUSER} - LANGFLOW_SUPERUSER_PASSWORD=${LANGFLOW_SUPERUSER_PASSWORD} - LANGFLOW_NEW_USER_IS_ACTIVE=${LANGFLOW_NEW_USER_IS_ACTIVE} - LANGFLOW_ENABLE_SUPERUSER_CLI=${LANGFLOW_ENABLE_SUPERUSER_CLI} # - DEFAULT_FOLDER_NAME=OpenRAG - HIDE_GETTING_STARTED_PROGRESS=true - LANGFLOW_SSRF_ALLOWED_HOSTS=${LANGFLOW_SSRF_ALLOWED_HOSTS:-localhost,127.0.0.1,host.docker.internal} # Azurite: local Azure Storage emulator for manually testing the Azure Blob # connector without a paid Azure account. Opt-in only — gated behind the # "azurite" compose profile so it never starts with the normal stack. # Start it with `make azurite-up` (or `docker compose --profile azurite up -d azurite`). # Connect the connector with AZURE_STORAGE_CONNECTION_STRING="UseDevelopmentStorage=true" # (from inside the compose network use host "azurite": the well-known dev # endpoint http://azurite:10000/devstoreaccount1). azurite: image: mcr.microsoft.com/azure-storage/azurite:latest container_name: azurite profiles: ["azurite"] # --skipApiVersionCheck: the azure-storage-blob SDK may negotiate a newer # Storage API version than the pinned Azurite image supports; skip the check # so the emulator accepts requests (safe for local dev only). command: "azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --location /data --skipApiVersionCheck" ports: - "10000:10000" # Blob - "10001:10001" # Queue - "10002:10002" # Table volumes: - azurite-data:/data # Instana host agent: forwards traces/metrics to the Instana SaaS ingress # named by INSTANA_AGENT_ENDPOINT. The default below is one regional ingress; # get the right one for your tenant from Infrastructure > Add a Host, which # also issues the INSTANA_AGENT_KEY the agent needs. # Opt-in only — gated behind the "instana" compose profile. # # WARNING: local development only. This container runs privileged, in the host # PID namespace, with a read-write Docker socket — any one of those is # root-equivalent on the host. The agent needs them for host/infrastructure # metrics, but do not run this on a shared or production host. # # Start it with `make instana-agent-up`. Uses host networking so the agent # publishes 42699 directly on localhost, matching the dev-local topology # (backend runs on the host via `make backend`, not in Docker). # NOTE: flags below are a starting point — re-verify against the exact # Docker install command from the tenant's own "Add a Host Agent" wizard # (Infrastructure > Add a Host) before relying on this, since IBM adjusts # recommended flags between agent releases. instana-agent: # Pinned rather than :latest — this container runs privileged, with host PID # and a Docker socket mount, so an upstream retag would silently change what # runs as root on a developer machine. Override with INSTANA_AGENT_IMAGE_TAG # to test a newer agent; bump the default here once it is verified. image: icr.io/instana/agent:${INSTANA_AGENT_IMAGE_TAG:-1.323.1} container_name: instana-agent profiles: ["instana"] network_mode: host pid: host privileged: true environment: - INSTANA_AGENT_ENDPOINT=${INSTANA_AGENT_ENDPOINT:-ingress-coral-saas.instana.io} - INSTANA_AGENT_ENDPOINT_PORT=${INSTANA_AGENT_ENDPOINT_PORT:-443} - INSTANA_AGENT_KEY=${INSTANA_AGENT_KEY} volumes: # docker.sock stays read-write: talking to the Docker API means writing to # the socket, so :ro here would break container discovery. The rest are # :ro because the agent only reads them. Note this narrows scope rather # than enforcing a boundary — `privileged: true` above lets the container # remount them writable. If a future agent release needs write access, # these flags are the first thing to revert. - /var/run/docker.sock:/var/run/docker.sock - /dev:/dev:ro - /sys:/sys:ro - /var/log:/var/log:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro volumes: opensearch-data: azurite-data: