Search code examples
nginxdockervirtualizationdocker-composedocker-network

Docker - nginx proxy - access hosts between containers


I have web application.

  1. Public web app (app1)
  2. api web app (app2)

I make docker configuration for this apps. Each application in its container. To access this applications from web, configured container with nginx, where nginx proxy all requests.
So i can run - http://app1.dev/ and http://app2.dev/

But i need have access from app1 to http://app2.dev/ (access hosts app2.dev from app1 container).

Ping (from app1 container):

PING app2.dev (127.0.53.53) 56(84) bytes of data.
64 bytes from 127.0.53.53: icmp_seq=1 ttl=64 time=0.027 ms
64 bytes from 127.0.53.53: icmp_seq=2 ttl=64 time=0.038 ms
64 bytes from 127.0.53.53: icmp_seq=3 ttl=64 time=0.038 ms

What i should configure else, to have access to http://app2.dev/ host from app1 container?

Nginx proxy config

upstream app1_upstream {
    server app1;
}
upstream app1_upstream {
    server app2;
}
server {
    listen 80;

    server_name app1.dev
                app2.dev;

    location / {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;

        if ($host = "app1.dev") {
            proxy_pass http://app1;
        }

        if ($host = "app2.dev") {
            proxy_pass http://app2;
        }
    }

    error_log  /var/log/nginx/proxy_error.log;
    access_log /var/log/nginx/proxy_access.log;
}

Docker compose

version: '2'
services:
    proxy:
        build: ./proxy/
        ports:
            - "80:80"
            - "443:443"
        links:
            - app1
            - app2
            - app1:app1
            - app2:app2
        hostname: proxy

    app1:
        build: ./app1/
        volumes:
            - ../app1/:/var/www/app1
        hostname: app1

    app2:
        build: ./app2/
        volumes:
            - ../app2/:/var/www/app2
        hostname: app2

docker-compose ps

app1      /sbin/my_init  Up      80/tcp                                   
app2     /sbin/my_init  Up      80/tcp                                   
proxy_1   /sbin/my_init  Up      0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp

Solution

  • Not sure what version of docker you running, but if you are (or are able to) run 1.10 you should use a docker network instead of using "link".

    If you run all three containers on the same docker network then they will have access to one another through their container name.

    That will allow you to make the call from app1 to app2 without going back through your proxy (although I would call that an anti-pattern as if you were to change the interface to app2 you would have to update app1 and the proxy, I would have app1 call app2 through your proxy so you maintain one interface).

    For more info on Docker networks: https://docs.docker.com/engine/userguide/networking/dockernetworks/

    TLDR:

    # create bridge network (for single host)
    docker networks create my-network
    

    then change your compose too:

    version: '2'
    services:
        proxy:
            build: ./proxy/
            ports:
                - "80:80"
                - "443:443"
            networks:
                - my-network
            hostname: proxy
    
        app1:
            build: ./app1/
            volumes:
                - ../app1/:/var/www/app1
            networks:
                - my-network
            hostname: app1
    
        app2:
            build: ./app2/
            volumes:
                - ../app2/:/var/www/app2
            networks:
                - my-network
            hostname: app2
    
    networks:
       my-network:
        external: true