php - Docker/Symfony/Reactjs/Keycloak : How to make an HTTP request from a container to another with separated docker-compose files? ← (PHP, Symfony, React, MySQL, HTML)

I have 3 services : My backend (Backoffice and Api) in Symfony, My frontend app in Reactjs and a Keycloak service for SSO authentication.

I want to use Keycloak authentication for my backoffice and my frontend app.

I have 3 separated docker-compose files:

My Backend docker-compose file:

version: "3.3"
services:
  web:
    container_name: web_app
    build:
      context: ./.docker/web
    ports:
      - 8000:80
    volumes:
      - .:/var/www/backend
    working_dir: /var/www/backend
    depends_on:
      - mysql

  mysql:
    container_name: mysql_app
    image: mysql:5.7
    command: mysqld --sql_mode=NO_ENGINE_SUBSTITUTION --character-set-server=utf8 --collation-server=utf8_general_ci --skip-character-set-client-handshake
    restart: on-failure
    ports:
      - 3307:3306
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: app

  phpmyadmin:
    container_name: phpmyadmin_app
    image: phpmyadmin/phpmyadmin
    ports:
      - 8001:80
    environment:
      PMA_HOST: mysql
      PMA_USER: root
      PMA_PASSWORD: root
    depends_on:
      - mysql

volumes:
  mysql_data:
    driver: local

networks:
  default:
    external:
      name: app-network

My Frontend docker-compose file:

version: "3.3"
services:
  nodejs:
    container_name: nodejs_app
    image: "node:10"
    ports:
      - 3001:3000
    user: "node"
    environment:
      - NODE_ENV=development
    volumes:
      - .:/usr/src/frontend
    working_dir: /usr/src/frontend
    command: >
      sh -c "npm install && npm start"

networks:
  default:
    external:
      name: app-network

My Keycloak docker-compose file:

version: "3.3"
services:
  keycloak_mysql:
    image: mysql:5.7
    volumes:
      - keycloak_data:/var/lib/mysql
    ports:
      - 3308:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: keycloak
  keycloak:
    image: quay.io/keycloak/keycloak:latest
    environment:
      DB_VENDOR: MYSQL
      DB_ADDR: keycloak_mysql
      DB_DATABASE: keycloak
      DB_USER: root
      DB_PASSWORD: root
      KEYCLOAK_USER: admin
      KEYCLOAK_PASSWORD: admin
    ports:
      - 8080:8080
    depends_on:
      - keycloak_mysql

volumes:
  keycloak_data:
    driver: local

networks:
  default:
    external:
      name: app-network

My backend .env file :

OAUTH_KEYCLOAK_SERVER_URL=http://localhost:8080/auth
OAUTH_KEYCLOAK_CLIENT_ID=app
OAUTH_KEYCLOAK_CLIENT_SECRET=
OAUTH_KEYCLOAK_REALMS=app

And a network created with the following command : docker network create app-network

First, when I try to authenticate on my Backoffice, i'm redirected good to Keycloak login page. Then, after typing my credentials, I'm redirected back to my backoffice with the following error:

cURL error 7: Failed to connect to localhost port 8080: Connection refused (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for http://localhost:8080/auth/realms/app/protocol/openid-connect/token

I'm not very familiar with docker and networking.

How Can I solve this problem ?


UPDATE 1:

Now I've added a subnet to my network: docker network create --subnet 172.23.0.0/24 app-network

And added static IPs to my containers:

services:
  # Backend docker-compose file
  web:
    networks:
      default:
        ipv4_address: 172.23.0.11
    ...
    ...
  mysql:
    networks:
      default:
        ipv4_address: 172.23.0.15
    ...
    ...
  phpmyadmin:
    networks:
      default:
        ipv4_address: 172.23.0.14

  # Frontend docker-compose file
  nodejs:
    networks:
      default:
        ipv4_address: 172.23.0.12

  # Keycloak docker-compose file
  keycloak_mysql:
    networks:
      default:
        ipv4_address: 172.23.0.16
    ...
    ...
  keycloak:
    networks:
      default:
        ipv4_address: 172.23.0.13

And the following command: docker network inspect app-network gives me:

[
    {
        "Name": "app-network",
        "Id": "31984c890cfbf8206dacf18dd3e831c45cb133ab5391b45edf609cd2232eaffa",
        "Created": "2021-07-14T12:19:07.6486215Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.23.0.0/24"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "14ab20cf0c5517d9ec9b9d136d65bc07e847d154364ab831a7825c913943a768": {
                "Name": "phpmyadmin",
                "EndpointID": "81d31a65c37e121dbb4948e933e8edf37213612e9b3f6eb4ac66e4a0443a0117",
                "MacAddress": "02:42:ac:17:00:0e",
                "IPv4Address": "172.23.0.14/24",
                "IPv6Address": ""
            },
            "1cec44b30b8f942803d1bc3525ba5875d73f7253fbac021c67bf76ebf4488f7c": {
                "Name": "web",
                "EndpointID": "9a58e55dd679585af744af01b69d21eb94995a54ead0d24a5fe64e306c599452",
                "MacAddress": "02:42:ac:17:00:0b",
                "IPv4Address": "172.23.0.11/24",
                "IPv6Address": ""
            },
            "21f54bb4a453e701f1628b4c5e122d3a1e32411608603d193bd5787e2ff1ac38": {
                "Name": "nodejs",
                "EndpointID": "3272a80565ea0ff627c947635c04f5ad8fa47d1822db62e3e0d5f9052270d062",
                "MacAddress": "02:42:ac:17:00:0c",
                "IPv4Address": "172.23.0.12/24",
                "IPv6Address": ""
            },
            "7d0a8dec8ff6baac31e208c5ccea6fca6954d088a87b884ddd96c95d1c6a2930": {
                "Name": "keycloak_mysql_1",
                "EndpointID": "2517e766e4af674185c4d8612c5e169e6e12ab4658497dfe95cd08ba3d3f6153",
                "MacAddress": "02:42:ac:17:00:10",
                "IPv4Address": "172.23.0.16/24",
                "IPv6Address": ""
            },
            "822abcc2e5b7e2231f08534050618bc4842405a0f7a287274b9240c291ce87e3": {
                "Name": "mysql",
                "EndpointID": "5b3f47483495e48d0026c84dffe86d4cecd529b9f87ca0d40902280cca01be86",
                "MacAddress": "02:42:ac:17:00:0f",
                "IPv4Address": "172.23.0.15/24",
                "IPv6Address": ""
            },
            "998210a92b66d1342c9df35b30e341f7631c62604f6b7d0d0d3ac128d2c78420": {
                "Name": "keycloak_1",
                "EndpointID": "3e7e346a159593e4863abd7bc20d2b7f398a6fd2763981b2584ecc02d325c92e",
                "MacAddress": "02:42:ac:17:00:0d",
                "IPv4Address": "172.23.0.13/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

I can access to my keycloak container in my web container with doing: curl http://keycloak:8080 or curl http://172.23.0.13:8080

So I've updated my backend .env file to: OAUTH_KEYCLOAK_SERVER_URL=http://keycloak:8080/auth

But my browser does not recognize http://keycloak:8080 url when the redirection occurs.

On my browser, I'm only able to access to:

My backend: http://localhost:8000
My frontend: http://localhost:3001
My keycloak: http://localhost:8080

Is it also possible to access to my containers from the host by Ips ?


SOLUTION:

I edited my /etc/hosts and I added:

127.0.0.1 keycloak
127.0.0.1 web
127.0.0.1 nodejs

Now it's working fine

Answer



Solution:

By default containers created by docker-compose all have their own network namespace - i.e. their own (virtual) network interface and their own IP address - and so trying to connect to http://localhost:8080/ from the app container will not connect to the Keycloak container but to the app container itself.

To connect to the Keycloak container you need to use a hostname / IP that maps / is forwarded to the Keycloak container. Since all you containers are connected to the app-network you can just use the container name for this:

OAUTH_KEYCLOAK_SERVER_URL=http://keycloak:8080/auth

See the for more. (And short side note: you don't need to expose the ports of your mysql containers on the host for the app container to be able to connect)

If the same base url is used for redirecting your browser though be sure to use a host/IP that can be resolved from your host where the browser is running on, e.g. the hostname of the host itself where the respective ports are then forwarded to the right container.

Answer



Solution:

From your backend point of view (or from every other container in this context) localhost is the container itself. so if you want to use the portforwarding on your host machine you have to use the bridge ip adress.

Should be something like 172.17.0.1.

so your config would read something like:
OAUTH_KEYCLOAK_SERVER_URL=http://172.17.0.1:8080/auth

Source