Graylog Docker Compose: A Complete Self-Hosted Setup Guide
Disclosure: This post contains one or more links to providers we have a real, registered affiliate/referral relationship with. We may earn a commission at no extra cost to you if you sign up through them.
Setting up Graylog Docker Compose is one of the fastest ways to get a working centralized logging stack on a single VPS or bare-metal box. This guide walks through a real, working Graylog Docker Compose configuration, explains each service’s role, and covers the operational details you need to keep the stack healthy long after the first docker compose up.
Graylog is a log management platform built on top of OpenSearch (or Elasticsearch, depending on version) and MongoDB. Running it via Docker Compose means you don’t need to hand-install three separate services with three separate init scripts — you define the whole stack in one file, start it with one command, and tear it down just as cleanly. This article assumes basic familiarity with Docker and Docker Compose but no prior Graylog experience.
Why Use Graylog Docker Compose Instead of a Manual Install
Manually installing Graylog means installing a JVM, MongoDB, and OpenSearch separately, matching compatible versions, and hand-writing systemd units for each one. A Graylog Docker Compose setup collapses all of that into a single declarative file. Version pinning is explicit, networking between services is handled automatically by Compose’s internal DNS, and the entire stack can be reproduced on a new host in minutes.
There are a few concrete advantages worth calling out:
docker-compose.yml produces the same stack on any host with Docker installed.docker compose up -d is far less risky than an in-place OS package upgrade.docker compose down -v without leaving stray files across your filesystem.If you already run other services under Compose — for example if you’ve set up a Postgres Docker Compose stack or a Redis Docker Compose instance for other applications — this workflow will feel familiar. The same mental model of “one YAML file, one command” applies here.
Core Components of the Graylog Stack
Before writing the Compose file, it helps to understand what each container is actually doing. A Graylog Docker Compose deployment typically has three services.
MongoDB: Configuration Storage
MongoDB stores Graylog’s configuration data: users, dashboards, input definitions, alert rules, and index set metadata. It does not store your actual log messages — that’s OpenSearch’s job. MongoDB’s storage requirements stay relatively small and predictable even as log volume grows, because it only holds metadata, not the log events themselves.
OpenSearch: Log Storage and Search
OpenSearch (the search engine Graylog uses in current releases, having replaced Elasticsearch in the officially supported stack) is where the actual log data lives and gets indexed. This is almost always the most resource-hungry container in the stack — it needs enough heap memory to index incoming messages and enough disk to retain them for your chosen retention window. Undersizing this container is the single most common cause of a sluggish Graylog Docker Compose deployment.
Graylog Server: Ingestion, Processing, and UI
The Graylog server container handles everything else: accepting incoming log messages over various inputs (GELF, Syslog, Beats, raw TCP/UDP), running extractors and pipeline rules against them, and serving the web interface you use to search and build dashboards. It talks to MongoDB for configuration and to OpenSearch for storing and querying messages.
Writing the Graylog Docker Compose File
Here is a minimal, working docker-compose.yml for a single-node Graylog Docker Compose stack. It’s intentionally close to the configuration documented in Graylog’s own installation guide, with values you should adjust for your environment.
version: "3.8"
services:
mongodb:
image: mongo:6.0
restart: unless-stopped
volumes:
- mongo_data:/data/db
opensearch:
image: opensearchproject/opensearch:2.15.0
restart: unless-stopped
environment:
- "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g"
- "discovery.type=single-node"
- "DISABLE_SECURITY_PLUGIN=true"
- "action.auto_create_index=false"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- opensearch_data:/usr/share/opensearch/data
graylog:
image: graylog/graylog:6.1
restart: unless-stopped
environment:
- GRAYLOG_PASSWORD_SECRET=changeme_use_a_long_random_string
- GRAYLOG_ROOT_PASSWORD_SHA2=changeme_sha256_hash_of_your_password
- GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9000/
entrypoint: /usr/bin/tini -- wait-for-it opensearch:9200 -- /docker-entrypoint.sh
depends_on:
- mongodb
- opensearch
ports:
- "9000:9000"
- "1514:1514/udp"
- "12201:12201/udp"
volumes:
- graylog_data:/usr/share/graylog/data
volumes:
mongo_data:
opensearch_data:
graylog_data:
A few notes on this file worth understanding before you deploy it:
GRAYLOG_PASSWORD_SECRET must be a long, random string — Graylog uses it to salt stored passwords.GRAYLOG_ROOT_PASSWORD_SHA2 is the SHA-256 hash of your admin password, not the plaintext password itself.DISABLE_SECURITY_PLUGIN=true disables OpenSearch’s built-in authentication, which is fine for a single-node stack behind a firewall but not appropriate for a publicly exposed instance.12201/udp is the default GELF UDP input port, and 1514/udp is a common Syslog input port — you’ll enable the corresponding inputs from the Graylog UI after first boot.Generating the Root Password Hash
Graylog requires the root password as a SHA-256 hash, not plaintext, in the Compose environment variables. You can generate it directly from the command line:
echo -n "your-strong-password" | sha256sum
Copy the resulting hash (excluding the trailing filename marker) into GRAYLOG_ROOT_PASSWORD_SHA2.
Starting the Stack
With the file saved as docker-compose.yml, bring the stack up in detached mode:
docker compose up -d
docker compose ps
docker compose logs -f graylog
Graylog can take a minute or two to become reachable on first boot while it waits for OpenSearch to finish initializing. If you need to debug a slow or failing startup, the same log-reading techniques covered in this site’s Docker Compose logs debugging guide apply directly here — docker compose logs -f graylog is your primary tool for watching the ingestion and startup sequence in real time.
Configuring Inputs After First Boot
Once the Graylog Docker Compose stack is running, log in to the web UI at http://<your-host>:9000 with the root username and the plaintext password you hashed earlier. The first practical task is enabling an input so Graylog actually starts receiving logs.
Enabling a GELF UDP Input
GELF (Graylog Extended Log Format) is Graylog’s own structured logging format and is usually the simplest input to start with, especially if your applications already log via a GELF driver.
1. Navigate to System → Inputs.
2. Select GELF UDP from the dropdown and click Launch new input.
3. Set the bind address to 0.0.0.0 and the port to 12201 (matching the port mapping in the Compose file).
4. Save, and the input should show as running.
You can test it immediately from any host with nc:
echo '{"version": "1.1", "host": "test-host", "short_message": "hello from gelf"}' | nc -u -w1 localhost 12201
If everything is wired correctly, this message appears in the Graylog search view within a few seconds.
Enabling Docker Container Logging via GELF
If the goal is to centralize logs from other Docker Compose stacks on the same or different hosts, point each container’s logging driver at Graylog directly instead of relying on docker compose logs. This can be set per-service in any other Compose file on your infrastructure:
services:
app:
image: my-app:latest
logging:
driver: gelf
options:
gelf-address: "udp://your-graylog-host:12201"
tag: "my-app"
This is a natural next step once your Postgres Docker Compose or n8n self-hosted stacks are running — instead of docker compose logs on each host individually, every container ships its logs to one central Graylog instance where you can search across all of them at once.
Persistence, Backups, and Data Volumes
The Compose file above defines three named volumes — mongo_data, opensearch_data, and graylog_data. Understanding what lives in each matters before you script backups or plan a migration.
mongo_data holds all Graylog configuration: dashboards, users, roles, alert conditions, and index set definitions. This is small but critical — losing it means rebuilding your entire configuration by hand.opensearch_data holds the actual indexed log messages. This grows continuously and is the volume you need to size and monitor most closely.graylog_data holds Graylog server-specific state, including its internal node ID and some cached configuration.A simple, scriptable backup approach for a single-node Graylog Docker Compose stack is to stop the stack briefly and archive the volume directories, or use docker run with a throwaway container to tar each volume without downtime:
docker run --rm \
-v mongo_data:/data \
-v "$(pwd)":/backup \
alpine tar czf /backup/mongo_data_backup.tar.gz -C /data .
Repeat the same pattern for graylog_data if you want to preserve node identity across a restore. opensearch_data backups are usually handled separately via OpenSearch’s own snapshot API for larger deployments, since a raw tar of a live index can be inconsistent under write load.
Scaling and Production Considerations
A single-node Graylog Docker Compose file is fine for development, small teams, or moderate log volume, but a few things change as usage grows.
Memory Sizing for OpenSearch
The OPENSEARCH_JAVA_OPTS heap size in the example above (1GB) is a starting point, not a production recommendation. OpenSearch generally performs best when given roughly half of the host’s available RAM as heap, up to a ceiling of around 32GB (beyond which Java’s compressed object pointers stop being effective — a detail documented in the OpenSearch documentation). If searches feel slow or ingestion starts lagging, check heap usage before assuming the problem is elsewhere.
Disk and Retention
Log data is inherently disk-hungry. Configure Graylog’s index rotation and retention strategy under System → Indices to automatically delete or close old indices before disk fills up. Running out of disk space on the OpenSearch volume is one of the most common ways a Graylog Docker Compose stack becomes unresponsive, since OpenSearch enforces disk watermarks and will refuse writes when free space drops too low.
Choosing Where to Host the Stack
Because OpenSearch and Graylog together are memory- and disk-intensive, undersized VPS instances tend to struggle once real log volume arrives. If you’re standing up a dedicated logging host, providers like DigitalOcean and Hetzner offer VPS tiers with enough RAM and SSD-backed storage to run a single-node Graylog Docker Compose stack comfortably without needing to shard across multiple nodes.
Networking and TLS
For anything beyond local testing, put the Graylog web interface behind a reverse proxy with TLS termination rather than exposing port 9000 directly. This also lets you enforce authentication at the proxy layer as an additional safeguard, similar to the reverse-proxy patterns commonly used for other self-hosted Compose stacks like n8n.
Troubleshooting Common Issues
A few problems come up repeatedly with Graylog Docker Compose deployments, and most trace back to the same handful of causes.
GRAYLOG_PASSWORD_SECRET/GRAYLOG_ROOT_PASSWORD_SHA2 values are malformed. Check docker compose logs graylog for the specific exception.vm.max_map_count kernel setting that’s too low on the host. This needs to be raised at the host OS level (sysctl -w vm.max_map_count=262144), not inside the container.GRAYLOG_HTTP_EXTERNAL_URI matches how you’re actually accessing the instance; a mismatch here can cause redirect loops in the browser.If you’re new to debugging multi-container stacks generally, the techniques in this site’s guide on rebuilding Docker Compose services are useful for cleanly forcing a container to pick up a config change without tearing down the whole stack.
Recommended: Ready to put this into practice? DigitalOcean is a tool we use for exactly this, and we have a real, disclosed affiliate relationship with them.
FAQ
Does Graylog Docker Compose require Elasticsearch or OpenSearch specifically?
Current Graylog releases officially support OpenSearch as the search backend. Older Graylog versions supported Elasticsearch, but new Graylog Docker Compose deployments should use OpenSearch to stay aligned with the officially supported and tested configuration.
Can I run Graylog Docker Compose on a single small VPS?
Yes, for low-to-moderate log volume. The main constraint is OpenSearch’s memory requirement — a stack with too little RAM will feel slow or become unresponsive under load, so size the host based on expected ingestion volume rather than guessing.
How do I update Graylog to a newer version in this Compose setup?
Change the image tag for the graylog service (and, if needed, the compatible OpenSearch/MongoDB versions per Graylog’s compatibility matrix), then run docker compose pull followed by docker compose up -d. Always check the release notes for breaking changes before upgrading a production instance.
Is a Graylog Docker Compose setup suitable for production, or only for testing?
A single-node setup is commonly used in production for smaller environments, but larger deployments typically move to a multi-node OpenSearch cluster and dedicated Graylog server nodes rather than a single Compose file, since a one-node stack has no built-in redundancy.
Conclusion
A Graylog Docker Compose stack gives you a fully working centralized logging platform — ingestion, storage, search, and dashboards — defined in a single reproducible file. The setup shown here covers MongoDB for configuration, OpenSearch for storage and search, and the Graylog server itself, along with the inputs, volumes, and sizing considerations that determine whether the stack stays healthy as log volume grows. Start with the minimal configuration, confirm ingestion works with a simple GELF test message, and then tune memory, retention, and networking as your actual log volume and team size demand. For further detail on the underlying container orchestration model this stack relies on, the official Docker Compose documentation is the authoritative reference.
Leave a Reply