Docker stopped being a trend and became the standard way we deliver and support GLPI for clients. Instead of installing PHP, MariaDB and a web server straight onto the operating system, we package GLPI and its dependencies into versioned containers - which makes the install reproducible, the rollback trivial and maintenance predictable. This guide gathers the commands we actually use day to day in support and the practices we apply to run the service desk in production safely.
How we run GLPI on Docker
The architecture we standardize is deliberately lean: one container for the GLPI application (PHP-FPM and web server), one for the MariaDB database and, when the ticket volume warrants it, a Redis for session and cache. Everything orchestrated by a single docker-compose.yml, behind a reverse proxy with TLS. The data that must survive any container recreation - database, uploaded files and configuration - lives in named volumes, never inside the container. That separation between code (the image, disposable) and state (the volume, precious) is what turns a GLPI version upgrade into a matter of minutes rather than an all-nighter.
Artifact: the GLPI stack we provision
This is the skeleton of the compose file we bring up on every deployment, already with separate volumes and no plaintext credential inside the file:
# docker-compose.yml - production GLPI stack
services:
glpi:
image: glpi/glpi:11.0 # pinned tag, never 'latest'
restart: unless-stopped
depends_on:
- glpidb
volumes:
- glpi_files:/var/glpi # uploaded files and GLPI configuration
networks: [ edge, internal ]
glpidb:
image: mariadb:11.4
restart: unless-stopped
environment:
MARIADB_DATABASE: glpi
MARIADB_USER: glpi
MARIADB_PASSWORD_FILE: /run/secrets/db_password # password via secret, never plaintext
volumes:
- glpi_db:/var/lib/mysql # the database lives here, outside the container
networks: [ internal ]
secrets: [ db_password ]
volumes:
glpi_files:
glpi_db:
networks:
edge: # exposed to the reverse proxy
internal: # private database, no external route
internal: true
secrets:
db_password:
file: ./secrets/db_password.txt # file 600, outside git
The commands we actually use in support
Day to day, a handful of commands solve most interventions. These are the ones the team types almost without thinking:
| Command | When we use it supporting GLPI |
|---|---|
docker compose up -d | Brings up or updates the stack after a change to the compose or the image tag |
docker compose logs -f glpi | Follows a ticket error in real time when the client reports a failure |
docker compose exec glpi bash | Enters the container to run php bin/console (cron, cache, migration) |
docker compose ps | Checks that application and database are up before opening an incident |
docker stats | Diagnoses CPU and memory spikes when the complaint is slowness |
docker compose down (without -v) | Recreates the stack keeping the volumes; the -v would wipe the database |
The common - and costly - mistake we have seen in careless operators is running docker compose down -v thinking it only restarts the containers. The -v flag removes the volumes, and with them the entire GLPI database. In support we treat -v as a destructive command: it appears in no operating procedure, and every volume backup is validated before any maintenance that comes near it.
Best practices we apply in production
- Pinned tag, never
latest- we pin the image version (e.g.glpi/glpi:11.0,mariadb:11.4) so apulldoes not drag in an unexpected version in the middle of maintenance. - Non-root and least privilege - the application does not run as root, and the database sits on the
internalnetwork, with no external route, reachable only by the GLPI container. - Secrets out of the compose - the database password comes in via a Docker secret or a read-only mounted file, never in
environment:as plaintext committed to git. - The volume is sacred - database, files and configuration in named volumes, with a daily logical database dump tested with a real restore (a backup that has never been restored is not a backup).
- Lean, scanned images - a slim base and scanning with Trivy or Docker Scout so we do not carry a known CVE into production.
A detail only someone who supports GLPI in a container knows: upgrading the GLPI version is not just swapping the image tag. After docker compose up -d with the new image, you must run the database migration from the console inside the container, otherwise the application comes up pointing at an old schema and returns a 500 error on the first screen. That is why our upgrade procedure always chains the same order: backup the database volume, swap the tag, up -d, migrate and only then release access to users. When the client uses the NexTool plugin, that same bring-up reloads the ecosystem modules - so we also validate the health of the integrations (webhook queues, sync) before calling the environment stable.
If your GLPI operation still runs installed straight on the server, with no separate volumes and no tested backup, NexTool deploys and supports that environment on Docker the right way - with a versioned stack, predictable upgrades and observability next to the service desk. Talk to us about GLPI support on containers.
This content was produced with the aid of artificial intelligence and reviewed by the Nextool Solutions team.