Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to share localhost between two different Docker containers?

Tags:

docker

I have two different Docker containers and each has a different image. Each app in the containers uses non-conflicting ports. See the docker-compose.yml:

version: "2"

services:

  service_a:
    container_name: service_a.dev
    image: service_a.dev
    ports:
      - "6473:6473"
      - "6474:6474"
      - "1812:1812"
    depends_on:
      - postgres
    volumes:
      - ../configs/service_a/var/conf:/opt/services/service_a/var/conf

  postgres:
    container_name: postgres.dev
    hostname: postgres.dev
    image: postgres:9.6
    ports:
      - "5432:5432"
    volumes:
      - ../configs/postgres/scripts:/docker-entrypoint-initdb.d/

I can cURL each image successfully from the host machine (Mac OS), e.g. curl -k https://localhost:6473/service_a/api/version works. What I'd like to do is to be able to refer to postgres container from the service_a container via localhost as if these two containers were one and they share the same localhost. I know that it's possible if I use the hostname postgres.dev from inside the service_a container, but I'd like to be able to use localhost. Is this possible? Please note that I am not very well versed in networking or Docker.

Mac version: 10.12.4

Docker version: Docker version 17.03.0-ce, build 60ccb22

I have done quite some prior research, but couldn't find a solution. Relevant: https://forums.docker.com/t/localhost-and-docker-compose-networking-issue/23100/2

like image 766
kolistivra Avatar asked Apr 21 '17 16:04

kolistivra


People also ask

Can 2 Docker containers talk to each other?

If you are running more than one container, you can let your containers communicate with each other by attaching them to the same network. Docker creates virtual networks which let your containers talk to each other. In a network, a container has an IP address, and optionally a hostname.

How do you communicate between two Docker containers in separate networks?

One container can actually belong to multiple networks, so if you wanted containers A, B, and C where A <=> B and B <=> C but A and C cannot communicate, you could do so (Either using Compose's networks key for services or by executing extra docker network connect commands after docker run ).

Can we share container network between Docker hosts?

Bridge networks apply to containers running on the same Docker daemon host. For communication among containers running on different Docker daemon hosts, you can either manage routing at the OS level, or you can use an overlay network.

Can two Docker container listen on same port?

So there is no conflict if multiple containers are using the same port ( :80 in this case). You can access one container from another using its container-name or service-name or ip-address, whereas ip-address is not a good idea because this might change every time you (re)start the container.


2 Answers

The right way: don't use localhost. Instead use docker's built in DNS networking and reference the containers by their service name. You shouldn't even be setting the container name since that breaks scaling.


The bad way: if you don't want to use the docker networking feature, then you can switch to host networking, but that turns off a very key feature and other docker capabilities like the option to connect containers together in their own isolated networks will no longer work. With that disclaimer, the result would look like:

version: "2"

services:

  service_a:
    container_name: service_a.dev
    image: service_a.dev
    network_mode: "host"
    depends_on:
      - postgres
    volumes:
      - ../configs/service_a/var/conf:/opt/services/service_a/var/conf

  postgres:
    container_name: postgres.dev
    image: postgres:9.6
    network_mode: "host"
    volumes:
      - ../configs/postgres/scripts:/docker-entrypoint-initdb.d/

Note that I removed port publishing from the container to the host, since you're no longer in a container network. And I removed the hostname setting since you shouldn't change the hostname of the host itself from a docker container.

The linked forum posts you reference show how when this is a VM, the host cannot communicate with the containers as localhost. This is an expected limitation, but the containers themselves will be able to talk to each other as localhost. If you use a VirtualBox based install with docker-toolbox, you should be able to talk to the containers by the virtualbox IP.


The really wrong way: abuse the container network mode. The mode is available for debugging container networking issues and specialized use cases and really shouldn't be used to avoid reconfiguring an application to use DNS. And when you stop the database, you'll break your other container since it will lose its network namespace.

For this, you'll likely need to run two separate docker-compose.yml files because docker-compose will check for the existence of the network before taking any action. Start with the postgres container:

version: "2"
services:
  postgres:
    container_name: postgres.dev
    image: postgres:9.6
    ports:
      - "5432:5432"
    volumes:
      - ../configs/postgres/scripts:/docker-entrypoint-initdb.d/

Then you can make a second service in that same network namespace:

version: "2"
services:
  service_a:
    container_name: service_a.dev
    image: service_a.dev
    network_mode: "container:postgres.dev"
    ports:
      - "6473:6473"
      - "6474:6474"
      - "1812:1812"
    volumes:
      - ../configs/service_a/var/conf:/opt/services/service_a/var/conf
like image 102
BMitch Avatar answered Oct 25 '22 17:10

BMitch


Specifically for Mac and during local testing, I managed to get the multiple containers working using docker.for.mac.localhost approach. I documented it http://nileshgule.blogspot.sg/2017/12/docker-tip-workaround-for-accessing.html

like image 36
Nilesh Gule Avatar answered Oct 25 '22 19:10

Nilesh Gule