Stop Over-Provisioning for Logs: Deploying OpenObserve on Docker

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

The Heavy Cost of Traditional Observability

I once tried to deploy a full ELK (Elasticsearch, Logstash, Kibana) stack for a small startup’s MVP. Within ten minutes, the 4GB RAM on their VPS was maxed out, and the kernel OOM killer started terminating processes. Elasticsearch is powerful, but its Java-based architecture is a resource hog. Most teams managing small to medium infrastructures don’t need a petabyte-scale search engine just to debug a container crash at 2 AM.

That is why I switched to OpenObserve. After running it in production for six months, I’ve found it fundamentally changes the economics of monitoring. Because it is written in Rust, it is blazingly fast and maintains a tiny memory footprint. While an ELK node might struggle with less than 8GB of RAM, OpenObserve can comfortably handle millions of records on a machine with just 512MB.

Why OpenObserve Beats the ELK Stack

OpenObserve isn’t just a lightweight alternative; it’s a consolidated observability platform. The storage engine is the real hero here. Instead of managing complex, brittle indices that require constant manual tuning, OpenObserve stores data in local files or S3-compatible object storage like MinIO. This shift can reduce your storage costs by up to 90% compared to traditional indexing.

Querying data is also significantly easier. If you can write basic SQL, you already know how to search your logs. You don’t have to waste time learning proprietary languages like KQL or Lucene syntax. A simple query like SELECT * FROM "logs" WHERE status='error' AND service='api-gateway' works exactly as you’d expect.

I’ve used this setup to replace three separate tools with one Docker container. It simplifies the stack and makes maintenance almost trivial.

Core Concepts to Master

Before you start the installation, you should understand three fundamental architectural pillars:

  • Storage Flexibility: You can run it in stateful mode using local NVMe drives for speed. Alternatively, go stateless and push everything to AWS S3 for nearly infinite, low-cost retention.
  • Stream-Based Organization: Think of streams as database tables. You can separate data into frontend_logs, db_metrics, or auth_traces to keep your workspace organized.
  • Universal Ingestion: It plays well with others. You can push data using Fluentbit, OpenTelemetry (OTLP), Vector, or even a simple HTTP POST request.

Hands-on Practice: Deploying with Docker Compose

Docker Compose is the best way to keep your configuration version-controlled. The following template sets up a production-ready standalone instance in seconds.

1. Prepare Your Environment

mkdir openobserve && cd openobserve
mkdir data

2. Configure the Docker Compose File

Create a docker-compose.yml file. I have optimized these environment variables for a standard setup. Make sure to change the default password immediately.

services:
  openobserve:
    image: public.ecr.aws/zinclabs/openobserve:latest
    container_name: openobserve
    restart: always
    environment:
      - [email protected]
      - ZO_ROOT_USER_PASSWORD=YourSecurePassword123
      - ZO_DATA_DIR=/data
      - ZO_HTTP_PORT=5080
    ports:
      - "5080:5080"
    volumes:
      - ./data:/data
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5080/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3

3. Boot the System

Run the container in detached mode:

docker-compose up -d

Navigate to http://your-server-ip:5080. Use your defined credentials to access the dashboard. You’ll notice the UI is clean, responsive, and surprisingly similar to modern data platforms.

Sending Your First Log Entry

OpenObserve allows you to start ingesting data without defining a schema beforehand. You can test the ingestion pipeline immediately using curl. This mirrors how a backend application would send logs via an API.

curl http://localhost:5080/api/default/logs/_json \
  -u "[email protected]:YourSecurePassword123" \
  -H "Content-Type: application/json" \
  -d '[{
    "message": "User login successful",
    "user_id": 1024,
    "level": "info",
    "latency_ms": 45
  }]'

Check the “Logs” tab in the dashboard. You will see the entry in the default stream. OpenObserve automatically detects that latency_ms is a number, allowing you to create high-performance aggregations or graphs instantly.

Handling Metrics and Traces

Logs only tell half the story. To see the full picture, you need metrics and traces. OpenObserve supports the Prometheus remote write protocol. If your app already exports Prometheus metrics, just point the output to OpenObserve to centralize your data.

For distributed tracing, it is fully OTLP-native. I usually configure Node.js or Python apps to send traces directly to the OpenObserve endpoint. This setup removes the need for Jaeger or Tempo, saving you another 1GB to 2GB of RAM across your cluster.

Real-World Optimization Tips

After managing several OpenObserve instances, I recommend these three practices to keep your system healthy:

Secure Your Secrets

Don’t commit your passwords to GitHub. Use a .env file to store ZO_ROOT_USER_PASSWORD. OpenObserve supports dozens of configuration flags, and keeping them in a dedicated environment file makes upgrades much smoother.

Switch to S3 for Long-Term Data

Local disks fill up fast. If you need to keep logs for 90 days or more, S3 is the way to go. You can achieve massive scale without ever worrying about running out of disk space. Just add your S3 bucket credentials to the environment section of your compose file.

Automate Retention Policies

Not all logs are created equal. You might want to keep nginx_access logs for only 7 days to save space, while keeping audit_logs for a full year for compliance. You can set these rules in the “Settings” menu. This ensures your storage usage remains predictable and cost-effective.

Is it Worth the Switch?

Moving from a bloated ELK stack to OpenObserve feels like shedding a heavy winter coat in the middle of summer. It delivers high-performance observability without the massive infrastructure tax. If you are tired of your monitoring tools consuming more resources than the actual applications they are supposed to watch, OpenObserve is the solution you’ve been looking for.

Share: