docker.recipes

HashiCorp Consul Service Discovery

advanced

Service mesh and configuration with Consul cluster, ACL, and UI.

Overview

HashiCorp Consul is a distributed service mesh solution that provides service discovery, configuration management, and secure service-to-service communication across any cloud or runtime environment. Originally developed by HashiCorp in 2014, Consul has become the backbone for microservices architectures requiring dynamic service registration, health checking, and distributed configuration management. Unlike simple key-value stores like etcd, Consul offers a comprehensive service networking platform with built-in DNS interface, HTTP API, and advanced features like service intentions for zero-trust networking. This deployment creates a production-grade Consul cluster with three server nodes for high availability, complemented by Prometheus for metrics collection and Grafana for visualization. The three-server configuration ensures fault tolerance with proper quorum consensus, while the dedicated consul-agent demonstrates client-side service registration patterns. Prometheus integrates with Consul's built-in metrics endpoint to monitor cluster health, service discovery events, and performance metrics across the entire service mesh. This stack is ideal for platform engineering teams implementing microservices architecture, DevOps engineers managing multi-datacenter deployments, and organizations transitioning from monolithic applications to distributed systems. The combination of Consul's service mesh capabilities with Prometheus monitoring provides complete visibility into service communication patterns, health status, and performance bottlenecks. Companies like Criteo, Citadel, and many Fortune 500 enterprises rely on similar Consul deployments to manage thousands of services across hybrid cloud environments.

Key Features

  • Multi-raft consensus algorithm with 3-node server cluster for Byzantine fault tolerance
  • DNS-based service discovery on port 8600 with automatic SRV record generation
  • HTTP API for dynamic service registration and health check configuration
  • Web UI dashboard for visual service topology and key-value store management
  • Gossip protocol for efficient cluster membership and failure detection
  • Built-in health checking with HTTP, TCP, and script-based health monitors
  • Prometheus metrics integration with /v1/agent/metrics endpoint
  • Key-value store with hierarchical configuration management and watch capabilities

Common Use Cases

  • 1Microservices platforms requiring dynamic service registration and discovery
  • 2Multi-region application deployments with cross-datacenter service communication
  • 3Legacy application modernization with gradual service mesh adoption
  • 4Configuration management for applications requiring real-time config updates
  • 5Load balancer backends requiring automatic upstream service detection
  • 6Development environments mimicking production service discovery patterns
  • 7Container orchestration platforms needing external service registry integration

Prerequisites

  • Minimum 2GB RAM for 3-node Consul cluster plus monitoring stack
  • Available ports 8500 (HTTP), 8600 (DNS), 3000 (Grafana), 9090 (Prometheus)
  • prometheus.yml configuration file in current directory with Consul scrape targets
  • GRAFANA_PASSWORD environment variable set for admin authentication
  • Understanding of service discovery concepts and REST API interaction
  • Network connectivity allowing inter-container communication on consul_net bridge

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 consul-server-1:
3 image: hashicorp/consul:latest
4 command: agent -server -bootstrap-expect=3 -ui -client=0.0.0.0 -bind=0.0.0.0
5 ports:
6 - "8500:8500"
7 - "8600:8600/udp"
8 environment:
9 - CONSUL_BIND_INTERFACE=eth0
10 volumes:
11 - consul_server_1:/consul/data
12 networks:
13 - consul_net
14
15 consul-server-2:
16 image: hashicorp/consul:latest
17 command: agent -server -retry-join=consul-server-1 -client=0.0.0.0 -bind=0.0.0.0
18 environment:
19 - CONSUL_BIND_INTERFACE=eth0
20 volumes:
21 - consul_server_2:/consul/data
22 depends_on:
23 - consul-server-1
24 networks:
25 - consul_net
26
27 consul-server-3:
28 image: hashicorp/consul:latest
29 command: agent -server -retry-join=consul-server-1 -client=0.0.0.0 -bind=0.0.0.0
30 environment:
31 - CONSUL_BIND_INTERFACE=eth0
32 volumes:
33 - consul_server_3:/consul/data
34 depends_on:
35 - consul-server-1
36 networks:
37 - consul_net
38
39 consul-agent:
40 image: hashicorp/consul:latest
41 command: agent -retry-join=consul-server-1 -client=0.0.0.0 -bind=0.0.0.0
42 environment:
43 - CONSUL_BIND_INTERFACE=eth0
44 depends_on:
45 - consul-server-1
46 networks:
47 - consul_net
48
49 prometheus:
50 image: prom/prometheus:latest
51 ports:
52 - "9090:9090"
53 volumes:
54 - ./prometheus.yml:/etc/prometheus/prometheus.yml
55 - prometheus_data:/prometheus
56 networks:
57 - consul_net
58
59 grafana:
60 image: grafana/grafana:latest
61 ports:
62 - "3000:3000"
63 environment:
64 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
65 volumes:
66 - grafana_data:/var/lib/grafana
67 networks:
68 - consul_net
69
70volumes:
71 consul_server_1:
72 consul_server_2:
73 consul_server_3:
74 prometheus_data:
75 grafana_data:
76
77networks:
78 consul_net:

.env Template

.env
1# Consul Cluster
2GRAFANA_PASSWORD=secure_grafana_password
3
4# Consul UI at http://localhost:8500
5# DNS at localhost:8600

Usage Notes

  1. 1Consul UI at http://localhost:8500
  2. 2DNS interface at port 8600/UDP
  3. 33-node server cluster for HA
  4. 4Service registration via API
  5. 5KV store for configuration

Individual Services(6 services)

Copy individual services to mix and match with your existing compose files.

consul-server-1
consul-server-1:
  image: hashicorp/consul:latest
  command: agent -server -bootstrap-expect=3 -ui -client=0.0.0.0 -bind=0.0.0.0
  ports:
    - "8500:8500"
    - 8600:8600/udp
  environment:
    - CONSUL_BIND_INTERFACE=eth0
  volumes:
    - consul_server_1:/consul/data
  networks:
    - consul_net
consul-server-2
consul-server-2:
  image: hashicorp/consul:latest
  command: agent -server -retry-join=consul-server-1 -client=0.0.0.0 -bind=0.0.0.0
  environment:
    - CONSUL_BIND_INTERFACE=eth0
  volumes:
    - consul_server_2:/consul/data
  depends_on:
    - consul-server-1
  networks:
    - consul_net
consul-server-3
consul-server-3:
  image: hashicorp/consul:latest
  command: agent -server -retry-join=consul-server-1 -client=0.0.0.0 -bind=0.0.0.0
  environment:
    - CONSUL_BIND_INTERFACE=eth0
  volumes:
    - consul_server_3:/consul/data
  depends_on:
    - consul-server-1
  networks:
    - consul_net
consul-agent
consul-agent:
  image: hashicorp/consul:latest
  command: agent -retry-join=consul-server-1 -client=0.0.0.0 -bind=0.0.0.0
  environment:
    - CONSUL_BIND_INTERFACE=eth0
  depends_on:
    - consul-server-1
  networks:
    - consul_net
prometheus
prometheus:
  image: prom/prometheus:latest
  ports:
    - "9090:9090"
  volumes:
    - ./prometheus.yml:/etc/prometheus/prometheus.yml
    - prometheus_data:/prometheus
  networks:
    - consul_net
grafana
grafana:
  image: grafana/grafana:latest
  ports:
    - "3000:3000"
  environment:
    - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
  volumes:
    - grafana_data:/var/lib/grafana
  networks:
    - consul_net

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 consul-server-1:
5 image: hashicorp/consul:latest
6 command: agent -server -bootstrap-expect=3 -ui -client=0.0.0.0 -bind=0.0.0.0
7 ports:
8 - "8500:8500"
9 - "8600:8600/udp"
10 environment:
11 - CONSUL_BIND_INTERFACE=eth0
12 volumes:
13 - consul_server_1:/consul/data
14 networks:
15 - consul_net
16
17 consul-server-2:
18 image: hashicorp/consul:latest
19 command: agent -server -retry-join=consul-server-1 -client=0.0.0.0 -bind=0.0.0.0
20 environment:
21 - CONSUL_BIND_INTERFACE=eth0
22 volumes:
23 - consul_server_2:/consul/data
24 depends_on:
25 - consul-server-1
26 networks:
27 - consul_net
28
29 consul-server-3:
30 image: hashicorp/consul:latest
31 command: agent -server -retry-join=consul-server-1 -client=0.0.0.0 -bind=0.0.0.0
32 environment:
33 - CONSUL_BIND_INTERFACE=eth0
34 volumes:
35 - consul_server_3:/consul/data
36 depends_on:
37 - consul-server-1
38 networks:
39 - consul_net
40
41 consul-agent:
42 image: hashicorp/consul:latest
43 command: agent -retry-join=consul-server-1 -client=0.0.0.0 -bind=0.0.0.0
44 environment:
45 - CONSUL_BIND_INTERFACE=eth0
46 depends_on:
47 - consul-server-1
48 networks:
49 - consul_net
50
51 prometheus:
52 image: prom/prometheus:latest
53 ports:
54 - "9090:9090"
55 volumes:
56 - ./prometheus.yml:/etc/prometheus/prometheus.yml
57 - prometheus_data:/prometheus
58 networks:
59 - consul_net
60
61 grafana:
62 image: grafana/grafana:latest
63 ports:
64 - "3000:3000"
65 environment:
66 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
67 volumes:
68 - grafana_data:/var/lib/grafana
69 networks:
70 - consul_net
71
72volumes:
73 consul_server_1:
74 consul_server_2:
75 consul_server_3:
76 prometheus_data:
77 grafana_data:
78
79networks:
80 consul_net:
81EOF
82
83# 2. Create the .env file
84cat > .env << 'EOF'
85# Consul Cluster
86GRAFANA_PASSWORD=secure_grafana_password
87
88# Consul UI at http://localhost:8500
89# DNS at localhost:8600
90EOF
91
92# 3. Start the services
93docker compose up -d
94
95# 4. View logs
96docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/consul-cluster/run | bash

Troubleshooting

  • Consul leader election failed: Check server logs for port conflicts and ensure all three servers can communicate on port 8300
  • Service registration returns 500 error: Verify consul-agent is connected to cluster using 'consul members' command
  • DNS queries to port 8600 timeout: Confirm CONSUL_BIND_INTERFACE=eth0 environment variable and UDP port exposure
  • Prometheus cannot scrape Consul metrics: Add 'prometheus_retention_time' to Consul config and verify /v1/agent/metrics endpoint accessibility
  • Grafana dashboard shows no data: Check Prometheus data source configuration points to prometheus:9090 internal hostname
  • Consul UI shows failed health checks: Review service definition health check intervals and ensure target services respond correctly

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space