-
Notifications
You must be signed in to change notification settings - Fork 460
Docker
- Overview
- Official Docker Images
- Quick Start
- Building Custom Images
- Docker Compose Setup
- Volume Management
- Multi-Container Patterns
- Kubernetes Deployment
- Health Checks
- Networking
- Troubleshooting
- Production Best Practices
- See Also
ExaBGP runs excellently in Docker containers, providing isolated, reproducible deployments. The official Docker image includes all necessary dependencies and follows container best practices.
Key Benefits:
- Isolation: Separate BGP processes per container
- Portability: Consistent deployment across environments
- Scalability: Easy horizontal scaling with orchestration
- Version Control: Pin specific ExaBGP versions
- Resource Limits: Control CPU/memory per instance
ExaBGP does NOT manipulate the routing table (RIB/FIB) - it only speaks the BGP protocol. Route installation must be handled by external processes or network devices.
# Pull latest version
docker pull exabgp/exabgp:latest
# Pull specific version
docker pull exabgp/exabgp:5.0.0
# Available tags
docker pull exabgp/exabgp:main # Development version
docker pull exabgp/exabgp:4.2 # Maintenance 4.x branch# Alternative source
docker pull ghcr.io/exa-networks/exabgp:latest- Base: Python 3.13 slim-bookworm
- Size: ~150MB
-
User: Non-root user
exa - Init: Uses dumb-init for proper signal handling
- Dependencies: iproute2 included
Create a configuration file exabgp.conf:
neighbor 192.168.1.1 {
router-id 10.0.0.1;
local-address 10.0.0.2;
local-as 65000;
peer-as 65001;
static {
route 203.0.113.1/32 next-hop self;
}
}Run ExaBGP:
docker run -d \
--name exabgp \
--network host \
-v $(pwd)/exabgp.conf:/etc/exabgp/exabgp.conf:ro \
exabgp/exabgp:latest \
/etc/exabgp/exabgp.confConfiguration with API process:
process health-check {
run /usr/local/bin/health_check.py;
encoder json;
}
neighbor 192.168.1.1 {
router-id 10.0.0.1;
local-address 10.0.0.2;
local-as 65000;
peer-as 65001;
api {
processes [ health-check ];
}
}Run with health check script:
docker run -d \
--name exabgp \
--network host \
-v $(pwd)/exabgp.conf:/etc/exabgp/exabgp.conf:ro \
-v $(pwd)/health_check.py:/usr/local/bin/health_check.py:ro \
exabgp/exabgp:latest \
/etc/exabgp/exabgp.confFROM exabgp/exabgp:latest
# Add custom health check scripts
COPY health_checks/ /opt/exabgp/health_checks/
RUN chmod +x /opt/exabgp/health_checks/*.py
# Add custom configuration
COPY exabgp.conf /etc/exabgp/exabgp.conf
# Install additional dependencies
USER root
RUN apt-get update && \
apt-get install -y curl netcat-openbsd && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
USER exa
ENTRYPOINT ["/usr/bin/dumb-init", "--", "exabgp"]
CMD ["/etc/exabgp/exabgp.conf"]Build:
docker build -t myorg/exabgp-custom:1.0 .# syntax=docker/dockerfile:1.4
FROM python:3.13-bookworm AS builder
# Install uv for fast builds
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /build
# Copy ExaBGP source
COPY . /build/
# Build wheel
RUN uv build --wheel
# Install to /opt/exabgp
RUN pip install --target /opt/exabgp dist/*.whl
# Production image
FROM python:3.13-slim-bookworm
COPY --from=builder /opt/exabgp /opt/exabgp
ENV PYTHONPATH=/opt/exabgp
ENV PATH=/opt/exabgp/bin:$PATH
# Install runtime dependencies
RUN apt-get update && \
apt-get install -y iproute2 dumb-init curl && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Create ExaBGP user and directories
RUN useradd -r -u 1000 exa && \
mkdir -p /etc/exabgp /run/exabgp /var/log/exabgp && \
mkfifo /run/exabgp/exabgp.{in,out} && \
chown -R exa:exa /etc/exabgp /run/exabgp /var/log/exabgp && \
chmod 600 /run/exabgp/exabgp.{in,out}
# Environment configuration
RUN echo "[exabgp.daemon]" > /etc/exabgp/exabgp.env && \
echo "user = 'exa'" >> /etc/exabgp/exabgp.env && \
echo "[exabgp.log]" >> /etc/exabgp/exabgp.env && \
echo "all = false" >> /etc/exabgp/exabgp.env && \
echo "configuration = true" >> /etc/exabgp/exabgp.env
USER exa
WORKDIR /etc/exabgp
ENTRYPOINT ["/usr/bin/dumb-init", "--", "exabgp"]
CMD ["--help"]version: '3.8'
services:
exabgp:
image: exabgp/exabgp:latest
container_name: exabgp
network_mode: host
restart: unless-stopped
volumes:
- ./config/exabgp.conf:/etc/exabgp/exabgp.conf:ro
- ./scripts:/opt/scripts:ro
- exabgp-logs:/var/log/exabgp
environment:
- EXABGP_LOG_LEVEL=INFO
- EXABGP_API_ACK=true
command: /etc/exabgp/exabgp.conf
healthcheck:
test: ["CMD", "pgrep", "-f", "exabgp"]
interval: 30s
timeout: 10s
retries: 3
volumes:
exabgp-logs:version: '3.8'
services:
# ExaBGP Node 1
exabgp-node1:
image: exabgp/exabgp:latest
hostname: exabgp-node1
network_mode: host
restart: unless-stopped
volumes:
- ./config/node1.conf:/etc/exabgp/exabgp.conf:ro
- ./scripts/health_check.py:/opt/scripts/health_check.py:ro
- node1-logs:/var/log/exabgp
environment:
- NODE_ID=1
- SERVICE_IP=203.0.113.1
- PRIMARY_METRIC=100
command: /etc/exabgp/exabgp.conf
# ExaBGP Node 2
exabgp-node2:
image: exabgp/exabgp:latest
hostname: exabgp-node2
network_mode: host
restart: unless-stopped
volumes:
- ./config/node2.conf:/etc/exabgp/exabgp.conf:ro
- ./scripts/health_check.py:/opt/scripts/health_check.py:ro
- node2-logs:/var/log/exabgp
environment:
- NODE_ID=2
- SERVICE_IP=203.0.113.1
- PRIMARY_METRIC=101
command: /etc/exabgp/exabgp.conf
# Web service (example application)
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html:ro
depends_on:
- exabgp-node1
- exabgp-node2
volumes:
node1-logs:
node2-logs:version: '3.8'
services:
exabgp:
image: exabgp/exabgp:latest
network_mode: host
restart: unless-stopped
volumes:
- ./config:/etc/exabgp:ro
- ./scripts:/opt/scripts:ro
command: /etc/exabgp/exabgp.conf
labels:
- "prometheus.scrape=true"
- "prometheus.port=9576"
# Prometheus exporter
exabgp-exporter:
image: lusis/exabgp_exporter:latest
ports:
- "9576:9576"
environment:
- EXABGP_HOST=localhost
- EXABGP_PORT=5000
depends_on:
- exabgp
# Prometheus
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
# Grafana
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
- ./monitoring/dashboards:/etc/grafana/provisioning/dashboards:ro
depends_on:
- prometheus
volumes:
prometheus-data:
grafana-data:Mount configuration as read-only:
docker run -d \
-v $(pwd)/exabgp.conf:/etc/exabgp/exabgp.conf:ro \
exabgp/exabgp:latestMount scripts directory with execute permissions:
docker run -d \
-v $(pwd)/scripts:/opt/scripts:ro \
-v $(pwd)/exabgp.conf:/etc/exabgp/exabgp.conf:ro \
exabgp/exabgp:latestEnsure scripts are executable:
chmod +x scripts/*.pyPersist logs using named volume:
docker run -d \
-v exabgp-logs:/var/log/exabgp \
-v $(pwd)/exabgp.conf:/etc/exabgp/exabgp.conf:ro \
exabgp/exabgp:latestView logs:
docker exec exabgp tail -f /var/log/exabgp/exabgp.logFor interactive control:
docker run -d \
-v $(pwd)/run:/run/exabgp \
-v $(pwd)/exabgp.conf:/etc/exabgp/exabgp.conf:ro \
exabgp/exabgp:latestSend commands:
echo "announce route 203.0.113.1/32 next-hop self" > run/exabgp.inExaBGP as sidecar to application:
services:
app:
image: myapp:latest
network_mode: "service:exabgp"
depends_on:
- exabgp
exabgp:
image: exabgp/exabgp:latest
hostname: app-bgp
ports:
- "179:179" # BGP port
volumes:
- ./config/exabgp.conf:/etc/exabgp/exabgp.conf:ro
- shared-scripts:/opt/scripts
command: /etc/exabgp/exabgp.conf
volumes:
shared-scripts:Multiple containers sharing network:
services:
exabgp:
image: exabgp/exabgp:latest
network_mode: host
volumes:
- ./exabgp.conf:/etc/exabgp/exabgp.conf:ro
haproxy:
image: haproxy:latest
network_mode: host
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
depends_on:
- exabgpservices:
exabgp:
image: exabgp/exabgp:latest
environment:
- SERVICE_NAME=web
- SERVICE_IP=203.0.113.1
- CONSUL_ADDR=consul:8500
volumes:
- ./scripts/consul_discovery.py:/opt/scripts/discovery.py:ro
- ./exabgp.conf:/etc/exabgp/exabgp.conf:ro
consul:
image: consul:latest
ports:
- "8500:8500"services:
# FlowSpec controller
flowspec-controller:
image: myorg/flowspec-controller:latest
environment:
- EXABGP_HOST=exabgp
- EXABGP_PORT=5000
depends_on:
- exabgp
# ExaBGP FlowSpec announcer
exabgp:
image: exabgp/exabgp:latest
network_mode: host
volumes:
- ./flowspec.conf:/etc/exabgp/exabgp.conf:ro
command: /etc/exabgp/exabgp.conf
# DDoS detection (example)
fastnetmon:
image: fastnetmon/fastnetmon:latest
network_mode: host
environment:
- EXABGP_HOST=localhost
depends_on:
- exabgpSee Kubernetes.md for comprehensive Kubernetes integration documentation.
Quick Example:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: exabgp
namespace: bgp
spec:
selector:
matchLabels:
app: exabgp
template:
metadata:
labels:
app: exabgp
spec:
hostNetwork: true
containers:
- name: exabgp
image: exabgp/exabgp:latest
args: ["/etc/exabgp/exabgp.conf"]
volumeMounts:
- name: config
mountPath: /etc/exabgp
readOnly: true
volumes:
- name: config
configMap:
name: exabgp-configAdd to Dockerfile or docker-compose.yml:
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD pgrep -f exabgp || exit 1More sophisticated health check:
#!/bin/bash
# health_check.sh
# Check if ExaBGP process is running
if ! pgrep -f "exabgp" > /dev/null; then
echo "ExaBGP process not running"
exit 1
fi
# Check if BGP session is established (requires netstat)
if ! netstat -tn | grep -q ":179.*ESTABLISHED"; then
echo "No established BGP sessions"
exit 1
fi
echo "ExaBGP healthy"
exit 0healthcheck:
test: ["/opt/scripts/health_check.sh"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sMonitor application and announce via BGP:
#!/usr/bin/env python3
# app_health.py
import sys
import time
import requests
def check_app_health():
try:
response = requests.get('http://localhost:8080/health', timeout=2)
return response.status_code == 200
except:
return False
# Announce route when healthy
while True:
if check_app_health():
sys.stdout.write('announce route 203.0.113.1/32 next-hop self\n')
else:
sys.stdout.write('withdraw route 203.0.113.1/32 next-hop self\n')
sys.stdout.flush()
time.sleep(10)Recommended for BGP (needs direct access to network):
docker run -d --network host exabgp/exabgp:latestAdvantages:
- Direct access to host network interfaces
- BGP uses standard port 179
- No NAT/port mapping complexity
- Full routing table visibility
Considerations:
- Less isolation
- Containers share host network stack
- Port conflicts possible
For development/testing only:
docker run -d \
-p 179:179 \
--network bridge \
exabgp/exabgp:latestNot recommended for production - BGP requires proper network access.
# Create network
docker network create --driver bridge bgp-network
# Run ExaBGP
docker run -d \
--network bgp-network \
--name exabgp \
exabgp/exabgp:latestFor multiple BGP speakers with unique IPs:
# Create macvlan network
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
bgp-macvlan
# Run with unique IP
docker run -d \
--network bgp-macvlan \
--ip 192.168.1.10 \
--name exabgp1 \
exabgp/exabgp:latestCheck logs:
docker logs exabgpCommon issues:
- Invalid configuration syntax
- Missing configuration file
- Port 179 already in use
- Permission issues
Debug networking:
# Check if BGP port is accessible
docker exec exabgp netstat -tlnp | grep 179
# Test connectivity to peer
docker exec exabgp ping -c 3 192.168.1.1
# Check routing table (if host network)
docker exec exabgp ip route
# Verify BGP process
docker exec exabgp ps aux | grep exabgpValidate configuration:
# Check configuration syntax
docker run --rm \
-v $(pwd)/exabgp.conf:/etc/exabgp/exabgp.conf:ro \
exabgp/exabgp:latest \
--test /etc/exabgp/exabgp.confCheck script permissions:
# Inside container
docker exec exabgp ls -la /opt/scripts/
# Should be executable (chmod +x)
chmod +x scripts/*.pyEnable verbose logging:
[exabgp.log]
all = true
destination = /var/log/exabgp/exabgp.logOr use environment variable:
docker run -d \
-e EXABGP_LOG_LEVEL=DEBUG \
exabgp/exabgp:latestMonitor resources:
# Container stats
docker stats exabgp
# Set resource limits
docker run -d \
--memory="512m" \
--cpus="1.0" \
exabgp/exabgp:latest# Good
image: exabgp/exabgp:5.0.0
# Avoid
image: exabgp/exabgp:latestservices:
exabgp:
image: exabgp/exabgp:5.0.0
read_only: true
tmpfs:
- /tmp
- /runservices:
exabgp:
image: exabgp/exabgp:5.0.0
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256Mservices:
exabgp:
image: exabgp/exabgp:5.0.0
restart: unless-stoppedservices:
exabgp:
image: exabgp/exabgp:5.0.0
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"services:
exabgp:
image: exabgp/exabgp:5.0.0
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_ADMIN # Only if needed
- NET_RAW# Store configs in git
git/
βββ docker-compose.yml
βββ config/
β βββ exabgp.conf
β βββ exabgp.env
βββ scripts/
βββ health_check.py
βββ announce.pyservices:
exabgp-test:
image: exabgp/exabgp:5.0.0
profiles: ["test"]
command: --test /etc/exabgp/exabgp.conf
volumes:
- ./config:/etc/exabgp:roRun tests:
docker compose --profile test up exabgp-testExpose metrics:
services:
exabgp:
image: exabgp/exabgp:5.0.0
labels:
- "prometheus.scrape=true"
- "prometheus.port=9576"
- "prometheus.path=/metrics"# Backup script
#!/bin/bash
docker exec exabgp cat /etc/exabgp/exabgp.conf > backup/exabgp.conf.$(date +%Y%m%d)Full production-ready docker-compose.yml:
version: '3.8'
services:
exabgp:
image: exabgp/exabgp:5.0.0
container_name: exabgp-prod
hostname: bgp-node1
network_mode: host
restart: unless-stopped
volumes:
- ./config/exabgp.conf:/etc/exabgp/exabgp.conf:ro
- ./config/exabgp.env:/etc/exabgp/exabgp.env:ro
- ./scripts:/opt/scripts:ro
- exabgp-logs:/var/log/exabgp
environment:
- NODE_ID=1
- CLUSTER=production
- REGION=us-east-1
healthcheck:
test: ["CMD", "/opt/scripts/health_check.sh"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
labels: "service=exabgp"
security_opt:
- no-new-privileges:true
deploy:
resources:
limits:
cpus: '2.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 256M
labels:
- "com.example.service=exabgp"
- "com.example.environment=production"
- "prometheus.scrape=true"
- "prometheus.port=9576"
command: /etc/exabgp/exabgp.conf
volumes:
exabgp-logs:
driver: local
driver_opts:
type: none
o: bind
device: /var/log/exabgp- Kubernetes Integration - Deploy ExaBGP on Kubernetes
- Prometheus Integration - Monitoring with Prometheus
- Cloud Platforms - AWS, GCP, Azure integration
- Configuration Syntax - ExaBGP configuration reference
- API Overview - Control ExaBGP via API
- High Availability - HA deployment patterns
- Debugging - Troubleshooting guide
- Official ExaBGP Docker Image
- Docker Documentation
- Docker Compose Documentation
- Facebook Katran - ExaBGP at hyperscale
π» Ghost written by Claude (Anthropic AI)
π Home
π Getting Started
π§ API
π‘οΈ Use Cases
π Address Families
βοΈ Configuration
π Operations
π Reference
- Architecture
- BGP State Machine
- Communities (RFC)
- Extended Communities
- BGP Ecosystem
- Capabilities (AFI/SAFI)
- RFC Support
π Migration
π Community
π External
- GitHub Repo β
- Slack β
- Issues β
π» Ghost written by Claude (Anthropic AI)