/consul-compose-swarm

An example for part of a microservice template that uses docker copose, docker swarm and consul

Primary LanguageGoMIT LicenseMIT

Microservice Registry

Environment

I run single node docker swarm for on-premises microservice deployments in systems that do not have a high availability requirement. This allows the benefits of DevOps for creating the microservices even though I'm deploying to a single server that is not in the cloud.

During the development process our team likes to use Docker compose invoked via docker-compose up to stand up the system for testing. In deployment we prefer docker stack deploy in order to take advantage of service health monitoring that comes with docker swarm.

Problem

One of our developers reported that there is a service discovery problem when standing up a collection of services that is caused by naming convention differences between swarm and compose. This repo attempts to recreate that problem, but after testing with both compose and swarm it appears that in both instances the webserver service can successfull connect to the mongo database at the hostname db with the URI string mongodb://db:27017.

Our team reported that both swarm and compose offer a DNS service that supports inter-service communication. However, there are subtle differences in the way the two systems create DNS names. Compose appends _1 to the end of each service name in the compose file and swarm does not append this suffix. For example, this snippet of a docker-compose.yml defines a service named broker.

version: '3.1'
services:
  broker:
    healthcheck:
      test: "exit 0"
    image:  fathom5/broker:swarm
    networks: 
      - grace
    depends_on: 
      - mongo
    ports:
      - "8001:8001"

    ...

If this service and the other services in the file were stood up using docker-compose up the resulting DNS name for the broker would be gracev0_broker_1. Whereas if the system were launched with the command docker stack deploy -c docker-compose.yml grace-v0 then the resulting DNS name for broker would be gracev0_broker.

This seemed to be a problem because it changes the DNS names hard coded into all of the other microservices. The normal answer to avoid hard coding service DNS names is to provide a service registry in the system so that all of the microservices look up the DNS names for servcies they want to communicate with in that registry.

Assume for a moment that there was another service, like Consul to provide a service registry that was also set up in the docker-compose.yml file.

version: '3.1'
services:
  registry:
    image:  consul
    networks: 
      - grace
    ports:
      - "8500:8500"

Then all the other microservices could cosult the registry for <address>:<port> information about the other services.

But, how do people get the right address for the registry service? The registry will solve the problem of service identification for all other services, but we have not addressed the underlying problem that consul is still going to have two different DNS names depending on how the mesh was stood up.

  • Compose - gracev0_consul_1
  • Swarm - gracev0_consul

Proposed solution

This repo provides a worked example for providing a service registry with Consul and providing a small package to resolve the registry DNS name.