Sliq
Sliq

Reputation: 16484

How to use service name as URL in Docker?

What I want to do:

My docker-composer file contains several services, which each have a service name. All services use the exact same image. I want them to be reachable via the service name (like curl service-one, curl service-two) from the host. The use-case is that these are microservices that should be reachable from a host system.

services:
    service-one:
        container_name: container-service-one
        image: customimage1
    service-two:
        container_name: container-service-two
        image: customimage1

What's the problem

Lots of tutorials say that that's the way to build microservices, but it's usually done by using ports, but I need services names instead of ports.

What I've tried

There are lots of very old answers (5-6 years), but not a single one gives a working answer. There are ideas like parsing the IP of each container and then using that, or just using hostnames internally between docker containers, or complex third party tools like building your own DNS. It feels weird that I'm the only one who needs several APIs reachable from a host system, this feels like standard use-case, so I think I'm missing something here.

Can somebody tell me where to go from here?

Upvotes: 1

Views: 3945

Answers (1)

Noam Yizraeli
Noam Yizraeli

Reputation: 5394

I'll start from basic to advanced as far as I know.

For starter, every service that's part of the docker network (by default everyone that's part of the compose file) so accessing each other by their service name is already there "for free".

If you want to use the service names from the host itself you can set a reverse proxy like nginx and by the server name (in your case would be equal to service name) route the appropriate port on the host running the docker containers. the basic idea is to intercept all communication to port 80 on the server and send the communication by the incoming DNS name. Here's an example:

compose file:

version: "3.9"
services:
  nginx-router:
    image: "nginx:latest"
    volumes:
      - type: bind
        source: ./nginx.conf
        target: /nginx/nginx.conf
    ports:
      - "80:80"
  service1:
    image: "nginx:latest"
    ports:
      - "8080:80"
  service2:
    image: "httpd:latest"
    ports:
      - "8081:80"

nginx.conf

worker_processes auto;

pid /tmp/nginx.pid;

events {
    worker_connections 8000;
    multi_accept on;
}

http {
    server {
        listen 80;
        server_name 127.0.0.1;

        location / {
            proxy_set_header Host $host;
            proxy_pass http://service1:80;
        }
    }
    
    server {
        listen 80;
        server_name localhost;

        location / {
            proxy_set_header Host $host;
            proxy_pass http://service2:80;
        }
    }
}

in this example if my server name is localhost I'm routing to service2 which is an httpd image or Apache HTTP and we're getting it works which is the default apache image HTML page: httpd output

and when we're accessing through 127.0.0.1 server name we should see nginx and indeed this is what we're getting: nginx output

in your case you'd use the service names instead after setting them as a DNS record and using this DNS record to route to the appropriate service.

Upvotes: 1

Related Questions