version: '3.8' services: # Traefik 负载均衡器 traefik: image: traefik:v3.0 container_name: traefik restart: unless-stopped ports: - "80:80" - "443:443" - "8080:8080" # Traefik Dashboard volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./traefik.yml:/etc/traefik/traefik.yml:ro - ./certs:/certs:ro environment: - CONSUL_ENDPOINTS=consul1:8500,consul2:8500,consul3:8500 depends_on: - consul1 - consul2 - consul3 networks: - traefik-net labels: - "traefik.enable=true" - "traefik.http.routers.dashboard.rule=Host(`traefik.local`)" - "traefik.http.routers.dashboard.service=api@internal" # Consul 集群节点 1 consul1: image: consul:1.16.1 container_name: consul1 hostname: consul1 restart: unless-stopped ports: - "8500:8500" volumes: - consul1_data:/consul/data command: > consul agent -server -bootstrap-expect=3 -datacenter=dc1 -data-dir=/consul/data -node=consul1 -bind=0.0.0.0 -client=0.0.0.0 -retry-join=consul2 -retry-join=consul3 -ui-config='{"enabled": true}' -log-level=INFO networks: - traefik-net labels: - "traefik.enable=true" - "traefik.http.routers.consul.rule=Host(`consul.local`)" - "traefik.http.services.consul.loadbalancer.server.port=8500" # Consul 集群节点 2 consul2: image: consul:1.16.1 container_name: consul2 hostname: consul2 restart: unless-stopped volumes: - consul2_data:/consul/data command: > consul agent -server -bootstrap-expect=3 -datacenter=dc1 -data-dir=/consul/data -node=consul2 -bind=0.0.0.0 -client=0.0.0.0 -retry-join=consul1 -retry-join=consul3 -log-level=INFO networks: - traefik-net # Consul 集群节点 3 consul3: image: consul:1.16.1 container_name: consul3 hostname: consul3 restart: unless-stopped volumes: - consul3_data:/consul/data command: > consul agent -server -bootstrap-expect=3 -datacenter=dc1 -data-dir=/consul/data -node=consul3 -bind=0.0.0.0 -client=0.0.0.0 -retry-join=consul1 -retry-join=consul2 -log-level=INFO networks: - traefik-net # 示例 Web 应用 web-app: image: nginx:alpine container_name: web-app restart: unless-stopped volumes: - ./web-content:/usr/share/nginx/html:ro environment: - CONSUL_URL=http://consul1:8500 networks: - traefik-net labels: - "traefik.enable=true" - "traefik.http.routers.web.rule=Host(`app.local`)" - "traefik.http.services.web.loadbalancer.server.port=80" - "traefik.http.routers.web.middlewares=web-auth" - "traefik.http.middlewares.web-auth.basicauth.users=admin:$$2y$$10$$..." # 示例 API 应用 api-app: image: node:18-alpine container_name: api-app restart: unless-stopped working_dir: /app volumes: - ./api:/app command: ["node", "server.js"] environment: - CONSUL_URL=http://consul1:8500 - NODE_ENV=production networks: - traefik-net labels: - "traefik.enable=true" - "traefik.http.routers.api.rule=Host(`api.local`) && PathPrefix(`/api`)" - "traefik.http.services.api.loadbalancer.server.port=3000" - "traefik.http.routers.api.middlewares=api-cors" - "traefik.http.middlewares.api-cors.headers.accesscontrolallowmethods=GET,POST,PUT,DELETE" - "traefik.http.middlewares.api-cors.headers.accesscontrolalloworigin=*" volumes: consul1_data: consul2_data: consul3_data: networks: traefik-net: driver: bridge ipam: config: - subnet: 172.20.0.0/16