# InvenTree

Inventory and parts management system with stock tracking and bills of materials.

- Replaces: [Sortly](https://openlogs.fyi/alternatives/sortly)
- Summary: Paid inventory management services, such as Sortly.
- Stack: Python (language), PostgreSQL (database), Redis (database)
- Deployment: docker_compose
- License: MIT (osi) [source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/LICENSE)
- Business model: unknown. The README at the pinned commit does not state a business model, so it stays unknown. ([source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/README.md), read 2026-10-22)
- Difficulty: hard. 5 services (2 database or broker: postgres, redis), 9 volume mounts, 6 env values to set, no elevated host access. Heuristic score 8 of 11: hard. A source checkout is needed, so the rating is at least medium.
- Requirements: not stated
- Repository: [inventree/InvenTree](https://github.com/inventree/InvenTree)

## Install

1. Docker with the Compose plugin and git ([source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md))

   ```text
   A host with Docker, the Docker Compose plugin and git. This entry needs a checkout of the project repository.
   ```

2. Get the source at commit b9793b0 ([source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md))

   ```bash
   git init InvenTree
   cd InvenTree
   git remote add origin https://github.com/inventree/InvenTree.git
   git sparse-checkout init --cone
   git sparse-checkout set contrib/container
   git fetch --depth 1 --filter=blob:none origin b9793b0a1fb803f2d2833d58ac77e6020acc5381
   git checkout FETCH_HEAD
   ```

3. Go to the folder the docs use ([source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md))

   ```bash
   cd contrib/container
   ```

4. The compose file in the checkout: contrib/container/docker-compose.yml (shown here for reading) ([source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/contrib/container/docker-compose.yml))

   ```yaml
   # Docker compose recipe for a production-ready InvenTree setup, with the following containers:
   # - PostgreSQL as the database backend
   # - gunicorn as the InvenTree web server
   # - django-q as the InvenTree background worker process
   # - Caddy as a reverse proxy
   # - redis as the cache manager (optional, enabled by default)
   
   # ---------------------
   # READ BEFORE STARTING!
   # ---------------------
   
   # -----------------------------
   # Setting environment variables
   # -----------------------------
   # Shared environment variables should be stored in the .env file
   # Changes made to this file are reflected across all containers!
   #
   # IMPORTANT NOTE:
   # You should not have to change *anything* within this docker-compose.yml file!
   # Instead, make any changes in the .env file!
   
   # ------------------------
   # InvenTree Image Versions
   # ------------------------
   # By default, this docker-compose script targets the STABLE version of InvenTree,
   # image: inventree/inventree:stable
   #
   # To run the LATEST (development) version of InvenTree,
   # change the INVENTREE_TAG variable (in the .env file) to "latest"
   #
   # Alternatively, you could target a specific tagged release version with (for example):
   # INVENTREE_TAG=0.7.5
   #
   
   # ----------------------------
   # Docker compose customization
   # ----------------------------
   # If you wish to customize the docker-compose script, you should only do so if you understand the stack!
   # Do not expect support for customizations that are not part of the standard InvenTree setup!
   
   services:
       # Database service
       # Use PostgreSQL as the database backend
       inventree-db:
           image: postgres:17
           container_name: inventree-db
           expose:
               - ${INVENTREE_DB_PORT:-5432}/tcp
           environment:
               - PGDATA=/var/lib/postgresql/data/pgdb
               - POSTGRES_USER=${INVENTREE_DB_USER:?You must provide the 'INVENTREE_DB_USER' variable in the .env file}
               - POSTGRES_PASSWORD=${INVENTREE_DB_PASSWORD:?You must provide the 'INVENTREE_DB_PASSWORD' variable in the .env file}
               - POSTGRES_DB=${INVENTREE_DB_NAME:?You must provide the 'INVENTREE_DB_NAME' variable in the .env file}
           volumes:
               # Map 'data' volume such that postgres database is stored externally
               - ${INVENTREE_EXT_VOLUME:?You must specify the 'INVENTREE_EXT_VOLUME' variable in the .env file!}:/var/lib/postgresql/data/:z
           healthcheck:
               test: ['CMD-SHELL', 'pg_isready -U "$${POSTGRES_USER}" -d "$${POSTGRES_DB}"']
               interval: 15s
               timeout: 5s
               retries: 10
               start_period: 20s
           restart: unless-stopped
   
       # redis acts as database cache manager
       inventree-cache:
           image: redis:7-alpine
           container_name: inventree-cache
           # Disable disk persistence to avoid permission errors on Windows bind mounts.
           # The /data volume is retained for layout consistency (#11100); cache data is ephemeral.
           command: redis-server --save "" --appendonly no
           env_file:
               - .env
           expose:
               - ${INVENTREE_CACHE_PORT:-6379}
           volumes:
               - ${INVENTREE_EXT_VOLUME}/redis:/data
           healthcheck:
               test: ['CMD', 'redis-cli', 'ping']
               interval: 15s
               timeout: 5s
               retries: 10
               start_period: 10s
           restart: always
   
       # InvenTree web server service
       # Uses gunicorn as the web server
       inventree-server:
           # If you wish to specify a particular InvenTree version, do so here
           image: inventree/inventree:${INVENTREE_TAG:-stable}
           container_name: inventree-server
           # Only change this port if you understand the stack.
           expose:
               - ${INVENTREE_WEB_PORT:-8000}
           depends_on:
               inventree-db:
                   condition: service_healthy
               inventree-cache:
                   condition: service_healthy
           env_file:
               - .env
           environment:
             INVENTREE_SERVER: http://inventree-server:${INVENTREE_WEB_PORT}
           volumes:
               # Data volume must map to /home/inventree/data
               - ${INVENTREE_EXT_VOLUME}:/home/inventree/data:z
           healthcheck:
               test:
                   [
                       'CMD-SHELL',
                       'invoke server-health --address "http://localhost:$${INVENTREE_WEB_PORT:-8000}"',
                   ]
               interval: 20s
               timeout: 5s
               retries: 10
               start_period: 60s
           restart: unless-stopped
   
       # Background worker process handles long-running or periodic tasks
       inventree-worker:
           # If you wish to specify a particular InvenTree version, do so here
           image: inventree/inventree:${INVENTREE_TAG:-stable}
           container_name: inventree-worker
           command: invoke worker
           depends_on:
               inventree-server:
                   condition: service_healthy
           env_file:
               - .env
           volumes:
               # Data volume must map to /home/inventree/data
               - ${INVENTREE_EXT_VOLUME}:/home/inventree/data:z
           healthcheck:
               test: ['CMD-SHELL', 'invoke worker-health']
               interval: 60s
               timeout: 10s
               retries: 3
               start_period: 180s
           restart: unless-stopped
   
       # caddy acts as reverse proxy and static file server
       # You can adjust the ports that the proxy listens on via the .env file
       # https://hub.docker.com/_/caddy
       inventree-proxy:
           container_name: inventree-proxy
           image: caddy:alpine
           restart: always
           depends_on:
               inventree-server:
                   condition: service_healthy
               inventree-worker:
                   condition: service_healthy
           ports:
               - ${INVENTREE_HTTP_PORT:-80}:80
               - ${INVENTREE_HTTPS_PORT:-443}:443
           env_file:
               - .env
           healthcheck:
               test: ['CMD', 'wget', '--spider', '-q', 'http://127.0.0.1:9090/api/system/health/']
               interval: 20s
               timeout: 5s
               retries: 10
               start_period: 20s
           volumes:
               - ./Caddyfile:/etc/caddy/Caddyfile:ro,z
               - ${INVENTREE_EXT_VOLUME}/static:/var/www/static:z
               - ${INVENTREE_EXT_VOLUME}/media:/var/www/media:z
               - ${INVENTREE_EXT_VOLUME}:/var/log:z
               - ${INVENTREE_EXT_VOLUME}:/data:z
               - ${INVENTREE_EXT_VOLUME}:/config:z
   ```

5. What the compose file check ran with ([source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md))

   ```text
   The compose file check ran in a checkout of inventree/InvenTree at b9793b0a1fb803f2d2833d58ac77e6020acc5381 (a sparse checkout: the top-level files and the folder contrib/container), in the folder contrib/container. The Docker install guide tells the reader to download docker-compose.yml, .env and Caddyfile from the contrib/container folder into one folder, set the data folder and database login in .env and run docker compose up -d.
   ```

6. Start it ([source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md))

   ```bash
   docker compose up -d
   ```

7. Open the app ([source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md))

   ```text
   Open http://inventree.localhost. The docs name this address. The compose file publishes host port 80 for the inventree-proxy service. The docs say a custom domain can be set in .env.
   ```

Compose file check: config_ok on 2026-10-22.

## Gotchas and maintenance

### Gotchas

- The compose file publishes host ports: Host ports: 80 (inventree-proxy), 443 (inventree-proxy). A port without a host address listens on all host network interfaces. ([source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/contrib/container/docker-compose.yml), checked 2026-10-22)
- The compose file mounts host folders: Host paths mounted into containers: ${INVENTREE_EXT_VOLUME}/redis at /data (inventree-cache), ${INVENTREE_EXT_VOLUME} at /home/inventree/data (inventree-server), ${INVENTREE_EXT_VOLUME} at /home/inventree/data (inventree-worker), ./Caddyfile at /etc/caddy/Caddyfile (inventree-proxy), ${INVENTREE_EXT_VOLUME}/static at /var/www/static (inventree-proxy), ${INVENTREE_EXT_VOLUME}/media at /var/www/media (inventree-proxy), ${INVENTREE_EXT_VOLUME} at /var/log (inventree-proxy), ${INVENTREE_EXT_VOLUME} at /data (inventree-proxy) and 1 more. ([source](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/contrib/container/docker-compose.yml), checked 2026-10-22)

### Signals

Computed from a GitHub snapshot taken 2026-10-22.

- Open issues and pull requests: 148
- Stars: 7743, forks: 1591
- Last push: 2026-10-22 (0 days ago)
- Latest release: 1.6.1 on 2026-10-21 (1 days ago)

## Sources

- [Repository: https://github.com/inventree/InvenTree](https://github.com/inventree/InvenTree)
- [License: https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/LICENSE](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/LICENSE)
- [Business model: https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/README.md](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/README.md)
- [Compose file: https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/contrib/container/docker-compose.yml](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/contrib/container/docker-compose.yml)
- [Install step: https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md](https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md)

---
Canonical: https://openlogs.fyi/tools/inventree  
Last updated: 2026-10-22
