0

The docker compose file:

version: '3'

services:
  rs:
    build: .
    ports:
      - "9090:9090"
  consul:
    image: "consul"
    ports:
      - "8500:8500"
    hostname: "abc"

rs is a go micro server app which will access consul and the consul address configured in a file like:

"microservice": {
        "serviceName": "hello",
        "registry": "consul=abc:8500",

However this don't work, the rs report error log:

register error: Put http://abc:8500/v1/agent/service/register: dial tcp: lookup abc on 127.0.0.11:53: no such host

I can access consul ui in host machine by http://127.0.0.1:8500, it works properly.

How to configure the network let rs can access consul?

jean
  • 2,825
  • 2
  • 35
  • 72
  • `consul` should work as a host name communicating between containers within the same `docker-compose.yml` file. You don't need to set `hostname:`. (It has the same effect as running _e.g._ `sudo hostname stackoverflow.com` on your local Linux system.) – David Maze Mar 31 '20 at 10:54

1 Answers1

1

You have changed hostname of the consul container, however rs service is not aware of this, and it attempts to resolve abc by querying default DNS server which is 127.0.0.11 port 53. You can see this in error message, since this DNS server is unable to resolve abc as it has no information about it.

The easiest way to solve this, and have it working in docker-compose, on the network created between the services in docker-compose is following:

version: '3'

services:
  rs:
    build: .
    # image: aline:3.7
    ports:
      - "9090:9090"
    # command: sleep 600
    networks:
      rs-consul:
  consul:
    image: "consul"
    ports:
      - "8500:8500"
    hostname: "abc"
    networks:
      rs-consul:
        aliases:
          - abc

networks:
  rs-consul:

This will create new network rs-consul (check with docker network ls, it will have some prefix, mine had working_directory_name_ as prefix). And on this network the Consul machine has alias abc. Now your rs service should be able to reach Consul service via http://abc:8500/

I have used commented lines (image:alpine:3.7 and command: sleep 600) instead of build: ., to test the connection, since I don't have your rs service code to use in build:. Once containers are started, I used docker exec -it <conatiner-id> sh to start shell on rs container, then installed curl and was able to retrieve Consul UI page via following command:

curl http://abc:8500/ui/

Hope this helps.

bagljas
  • 791
  • 5
  • 16
  • It works, thx. As docker doc says: "By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name." Why this won't work in this example? If access url "consul:8500", the error log will be "no such host" – jean Apr 01 '20 at 08:57
  • Default container name is same as container ID and is changed on every rebuild. This is not same as service tag in YAML file. E.g. when I ran the docker-compose on my machine I had: `05b35aa56c19 consul` in the output of `docker ps`. To access this consul from the other container I had to do `curl http://05b35aa56c19:8500`. For name to be set you need to use either `hostname: consul` as in the example above or `conainer_name: consul` (https://docs.docker.com/compose/compose-file/#container_name). In either case, this name will be available only on that particular docker network – bagljas Apr 01 '20 at 09:30
  • 1
    But in docker doc about pgsql example in https://docs.docker.com/compose/networking/, the db connection string is "postgres://db:5432". The "db" is a service name. This is confusing, why this can work? – jean Apr 01 '20 at 09:49
  • You are right, service name from docker-compose YAML is discoverable by other containers on the same network. I was able to use `dig` to resolve IP address of `consul` service, even without setting `container_name` or `hostname`, being set. Can you provide minimum configuration for the `rs` service to reproduce this issue? Because it might be issue with that container configuration, as plain alpine image is able to resolve `consul`. Try using `docker exec -it sh` to test if you able to resolve `consul` manually using `nslookup consul` or `dig consul`. – bagljas Apr 01 '20 at 10:49
  • I can not reproduce this after I run docker-compose down. I am new to docker, so ahead of that, I did rm -f image before docker-compose up. The doc says docker-compose down will remove the network also, maybe that's the reason I am keeping failure on that – jean Apr 02 '20 at 02:23
  • Container must be running when you execute `docker exec -it sh`. First bring up your docker-compose setup with `docker-compose up`, then find the container ID with `docker ps` and use it in the `exec` command. However, it's possible that `rs` container shuts down if it's not able to start successfully, in that case you will not be able to `exec` into it. What repo are you using to `build: .` the `rs` service? Is it available on github or some other public git service? – bagljas Apr 02 '20 at 06:50