Setting Hostname in Docker Compose

Wondering how to set hostname in Docker Compose? I'll show you that.

You may define it under the service like this:

...
letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    hostname: ledocker
    ...

But do you really need that? The general goal of the hostname is that computers on the network know each other and thus communicate between themselves.

Similarly, the main goal here is to ensure that containers can communicate with each other successfully within a Docker network.

I'm going to discuss two ways on how to make this possible:

Method 1: Non-explicit Communication

Within a Docker network, service names defined within a Docker Compose file can be used to test whether containers can communicate with each other.

Take for example the following reverse proxy config:

version: '3.7'

services:

  nginx-proxy:
    image: jwilder/nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./html:/usr/share/nginx/html
      - ./dhparam:/etc/nginx/dhparam
      - ./vhost:/etc/nginx/vhost.d
      - ./certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./client_max_upload_size.conf:/etc/nginx/conf.d/client_max_upload_size.conf
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
    restart: always
    networks:
      - net

  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    env_file:
      - ./letsencrypt.env
    depends_on:
      - nginx-proxy
    volumes:
      - ./certs:/etc/nginx/certs:rw
      - ./vhost:/etc/nginx/vhost.d
      - ./html:/usr/share/nginx/html
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: always
    networks:
      - net

networks:
  net:
    external: true

Note that the two service names are nginx-proxy and letsencrypt. You can use these names to test whether containers can communicate with each other or not. This can become very helpful during troubleshooting situations.

First, install ping inside the Nginx Reverse Proxy container:

avimanyu@iborg-desktop:~/nginx-proxy$ docker-compose exec nginx-proxy bash -c "apt update && apt install -y iputils-ping"

Now, you can use the ping command inside this container to check whether it can communicate with the Let's Encrypt Container (used for SSL).

avimanyu@iborg-desktop:~/nginx-proxy$ sudo docker-compose exec nginx-proxy ping letsencrypt
PING letsencrypt (172.18.0.3) 56(84) bytes of data.
64 bytes from nginx-proxy_letsencrypt_1.net (172.18.0.3): icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from nginx-proxy_letsencrypt_1.net (172.18.0.3): icmp_seq=2 ttl=64 time=0.057 ms
^C
--- letsencrypt ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 37ms

As you can see above, the reverse proxy container "sees" the second SSL container that sends a response back! In nginx-proxy_letsencrypt_1.net, nginx-proxy_letsencrypt_1 is the SSL container name and net is our custom network.

Let's quickly verify it:

avimanyu@iborg-desktop:~/nginx-proxy$ sudo docker ps
CONTAINER ID   IMAGE                                    COMMAND                  CREATED         STATUS         PORTS     NAMES
a9ef56e22f58   jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   7 minutes ago   Up 7 minutes             nginx-proxy_letsencrypt_1
563133f5d039   jwilder/nginx-proxy                      "/app/docker-entrypo…"   7 minutes ago   Up 7 minutes             nginx-proxy_nginx-proxy_1

To verify the network, you can use the docker network ls command.

avimanyu@iborg-desktop:~/nginx-proxy$ sudo docker network ls
NETWORK ID     NAME                DRIVER    SCOPE
018c50dc4fdc   bridge              bridge    local
27fd2370e735   net                 bridge    local
38ce8d11227b   host                host      local
2440210d0fc5   none                null      local

Method 2: Explicit Communication

Say, for some reason, you want to explicitly specify a hostname to a container. Docker Compose lets you do that too!

Using the hostname configuration option, you can set a different hostname to any service defined within a Docker Compose file, as I have done for the Let's Encrypt service below:

version: '3.7'

services:

  nginx-proxy:
    image: jwilder/nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./html:/usr/share/nginx/html
      - ./dhparam:/etc/nginx/dhparam
      - ./vhost:/etc/nginx/vhost.d
      - ./certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./client_max_upload_size.conf:/etc/nginx/conf.d/client_max_upload_size.conf
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
    restart: always
    networks:
      - net

  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    hostname: ledocker
    env_file:
      - ./letsencrypt.env
    depends_on:
      - nginx-proxy
    volumes:
      - ./certs:/etc/nginx/certs:rw
      - ./vhost:/etc/nginx/vhost.d
      - ./html:/usr/share/nginx/html
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: always
    networks:
      - net

networks:
  net:
    external: true

Here, note that I have explicitly added hostname: ledocker inside the Let's Encrypt service definition. I want to use ledocker as the hostname for the SSL container.

But wait, can we recheck again using the ping command?

avimanyu@iborg-desktop:~/nextcloud$ sudo docker-compose exec nginx-proxy ping ledocker
PING ledocker (172.18.0.3) 56(84) bytes of data.
64 bytes from nginx-proxy_nginx-proxy_1.net (172.18.0.3): icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from nginx-proxy_nginx-proxy_1.net (172.18.0.3): icmp_seq=2 ttl=64 time=0.079 ms
64 bytes from nginx-proxy_nginx-proxy_1.net (172.18.0.3): icmp_seq=3 ttl=64 time=0.061 ms
64 bytes from nginx-proxy_nginx-proxy_1.net (172.18.0.3): icmp_seq=4 ttl=64 time=0.093 ms
64 bytes from nginx-proxy_nginx-proxy_1.net (172.18.0.3): icmp_seq=5 ttl=64 time=0.078 ms
64 bytes from nginx-proxy_nginx-proxy_1.net (172.18.0.3): icmp_seq=6 ttl=64 time=0.075 ms
^C
--- ledocker ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 129ms
rtt min/avg/max/mdev = 0.034/0.070/0.093/0.018 ms

Indeed, yes. It works!

Hungry for more knowledge in this regard? Check out this extremely informative GitHub thread.

Hope you enjoyed this quick tip! You can leave any queries, doubts or suggestions in the comment section below.