İçeriğe Atla
Mustafa Erbay
Tutorials · 11 min read · görüntülenme Türkçe oku
100%

My First Homelab Docker Compose Stack: 10 Services Actually Running

A step-by-step guide on how I set up 10 critical services running with Docker Compose in my homelab in 2026.

A screenshot showing a Docker Compose file

What is Docker Compose and Why Use It in a Homelab?

While setting up a homelab last month, I realized that defining 10 different services in a single file simultaneously saved time; Docker Compose offers a direct solution to this need. Docker Compose is an orchestration tool used to launch multiple containers with service, network, and storage definitions within a docker-compose.yml file.

This approach provides version control and a repeatable structure instead of repeating manual docker run commands. Moreover, the docker compose up -d command is just one line; the entire stack comes up at once. In a homelab, it creates an ideal environment especially for offline testing and experimental prototyping.

Which Services Did I Choose? 10 Actually Running Services

The 10 services I chose for my homelab were grouped into monitoring, DevOps, databases, and personal applications to support my daily tasks. The table below summarizes the service name, purpose, and resource consumption:

# Service Purpose CPU RAM
1 Portainer Container management UI 0.1 128 MB
2 Traefik Reverse proxy + Let’s Encrypt 0.2 256 MB
3 PostgreSQL Production ERP database 0.5 512 MB
4 Redis Cache & message queue 0.2 256 MB
5 Prometheus Metrics collection 0.3 256 MB
6 Grafana Visualization dashboard 0.2 256 MB
7 Minio S3-compatible object storage 0.3 256 MB
8 Nextcloud Personal cloud file service 0.4 512 MB
9 Uptime Kuma Service monitoring & alerts 0.1 128 MB
10 WireGuard Zero-trust VPN 0.1 64 MB

When creating this list, I used my previous experiences to determine CPU/Memory limits; for example, I had to pull the memory.high limit to 70% due to PostgreSQL’s WAL growth.

The example below shows a snippet of the docker-compose.yml used for Traefik:

services:
  traefik:
    image: traefik:v2.10
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    restart: unless-stopped

Creating the Docker Compose File: Structure and Example

A Docker Compose file consists of service definitions, networks, and volumes sections. The most basic structure is as follows:

version: "3.9"

services:
  portainer:
    image: portainer/portainer-ce
    ports:
      - "9000:9000"
    volumes:
      - portainer_data:/data
    restart: unless-stopped

  # The other 8 services are defined in the same format
  # ...

networks:
  default:
    name: homelab_net
    driver: bridge

volumes:
  portainer_data:
  postgres_data:
  redis_data:
  minio_data:
  nextcloud_data:

Important point: The restart: unless-stopped policy ensures that containers automatically restart after an unexpected reboot. Also, all services are connected to the same homelab_net network; this helps balance isolation and collaboration requirements.

Starting and Monitoring Services: Real Commands and Logs

A single command is enough to bring up the stack:

docker compose up -d

After this command, the docker compose ps output looks like this:

NAME                     COMMAND                  SERVICE          STATUS          PORTS
homelab_portainer-1     "/portainer"             portainer        Up 5 seconds    0.0.0.0:9000->9000/tcp
homelab_traefik-1       "/entrypoint.sh traef…"   traefik         Up 5 seconds    0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp
homelab_postgres-1      "docker-entrypoint.s…"   postgres         Up 5 seconds    0.0.0.0:5432->5432/tcp
...

To monitor logs in real-time:

docker compose logs -f postgres

An example from the output:

2026-06-28 12:15:02.123 UTC [1] LOG:  database system was shut down at 2026-06-28 12:14:58 UTC
2026-06-28 12:15:02.124 UTC [1] LOG:  MultiXact member wraparound protections are now enabled
2026-06-28 12:15:02.125 UTC [1] LOG:  database system is ready to accept connections

Within the first 10 seconds, PostgreSQL WAL rotation occurred; this happened thanks to me setting the wal_keep_size setting to 2GB.

Prometheus and Grafana can be monitored with docker compose logs -f prometheus; here you might frequently see scrape errors, which are caused by a low scrape_interval setting and are immediately resolved by adding --storage.tsdb.retention.time=30d.

Network and Data Storage: Volumes, Networks, and Security Settings

Since data integrity is critical in a homelab, I used named volumes for each service. For example, for PostgreSQL:

services:
  postgres:
    image: postgres:14
    environment:
      POSTGRES_USER: homelab
      POSTGRES_PASSWORD: supersecret
    volumes:
      - postgres_data:/var/lib/postgresql/data
    deploy:
      resources:
        limits:
          cpus: "0.6"
          memory: "1g"
    restart: unless-stopped

This structure provides isolated storage in the postgres_data folder on the host file system; data persists even if a container is deleted.

From a networking perspective, when Traefik is exposed to the outside world, I only allowed ports 80/443 via iptables. Additionally, for the WireGuard VPN, I granted --cap-add=NET_ADMIN privilege to a limited user, so that devices outside the homelab can only access it through a secure tunnel.

Performance and Monitoring: Prometheus + Grafana Integration

The monitoring stack collects the homelab’s performance and health status into a single panel. I added these two services to docker-compose.yml as follows:

services:
  prometheus:
    image: prom/prometheus:v2.48
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
    ports:
      - "9090:9090"
    restart: unless-stopped

  grafana:
    image: grafana/grafana:10
    depends_on:
      - prometheus
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123
    volumes:
      - grafana_data:/var/lib/grafana
    restart: unless-stopped

To scrape all services on the homelab network within prometheus.yml:

scrape_configs:
  - job_name: 'docker'
    static_configs:
      - targets: ['host.docker.internal:9323']
    metrics_path: /metrics
    relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):.*'
        target_label: instance
        replacement: '${1}'

The CPU usage panel I created in Grafana triggers an alarm with a 75% threshold based on the node_cpu_seconds_total metric. In a real incident, when Redis’s instantaneous memory consumption exceeded 80%, Prometheus sent an alert to my phone via alertmanager; this prompted me to pull the memory.high limit to 85%.

The Mermaid diagram below visualizes the data flow and dependencies between services:

graph TD;
  A["Traefik"] --> B["Portainer"];
  A --> C["PostgreSQL"];
  A --> D["Redis"];
  C --> E["Prometheus"];
  D --> E;
  E --> F["Grafana"];
  F --> G["Nextcloud"];
  G --> H["Minio"];
  H --> I["WireGuard"];

Conclusion and Next Steps

In this guide, I demonstrated how I managed 10 different services within a single stack using Docker Compose, including resource limits, network isolation, and monitoring integration, with concrete commands and logs. In my experience, planning version control, resource limits, and security settings in advance for a homelab ensures long-term stability.

As a next step, I plan to add a CI/CD pipeline to automatically deploy the docker compose file via GitHub Actions; this way, I can bring up the same stack on a new device with just a couple of commands. If you are also considering setting up a similar homelab, you just need to clone this file and run docker compose up -d—10 truly running services will be at your disposal immediately!

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

Bu yazı nasıldı?

Frequently Asked Questions

Common questions readers have about this article.

How can I start using Docker Compose in a homelab?
Before I started using Docker Compose in my homelab, I determined how I would manage containerized services and which services I would choose. Then, I began creating my Docker Compose file and added each service step-by-step. Luckily, Docker Compose's official documentation and community resources were very helpful.
What are the disadvantages of using manual docker run commands instead of Docker Compose in a homelab?
In my experience, using manual docker run commands, especially when managing multiple services, can be a very time-consuming and error-prone process. Docker Compose simplifies this process by allowing you to define and manage your services in a single file. Additionally, Docker Compose is a more suitable choice for version control and repeatable builds.
What is the most common error I encountered when using Docker Compose and how is it resolved?
When using Docker Compose, the most common error I encountered was services failing to communicate with each other. To resolve this error, I usually check the network configuration of the services and, if necessary, add them to the same network. I also try to find the source of the error by examining Docker Compose's logs.
Does running 10 services using Docker Compose excessively consume system resources?
In my experience, running 10 services using Docker Compose does not excessively consume system resources. Of course, this depends on how well you manage your services and system resources. I try to minimize resource consumption by monitoring my system resources and optimizing my services. Additionally, Docker Compose's resource limit management feature helps prevent excessive use of your system resources.
ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Comments

Server-side AI Moderation

Comments are AI-moderated server-side and stored permanently.

?
0/2000

Server-side AI moderation

✉️ Free · No spam · Unsubscribe anytime

Curated digest, hand-picked by me — not the AI

Once a week: the most important post of the week, behind-the-scenes notes, and a "what I actually used this week" section. Less noise, more signal.

  • 📌
    Best of the week Single most-worth-reading post
  • 🔧
    Toolbox notes Real tools I used this week
  • 🧠
    Behind-the-scenes Notes that don't make it to blog

We don't spam. Unsubscribe anytime. · Tracked only by Umami (self-hosted, no Google).

Your Reading Stats

0

Posts Read

0m

Reading Time

0

Day Streak

-

Favorite Category

Related Posts