javadockerkeycloak

Keycloak - Java App Redirect within Docker


I have a java web application with tomcat and keycloak for authentication. Both services (the app and Keycloak) are running in separate Docker containers, connected through a docker bridge network

In my app profile was configured with keycloak.json as:

{
  "realm": "${realm}",
  "auth-server-url": "http://keycloak:8080/auth",
  "ssl-required": "none",
  "resource": "${client_id}",
  "public-client": true,
  "confidential-port": 0
}

I had a problem when trying to access http://localhost:8090/system, the app redirected the browser to this Keycloak URL:

http://keycloak:8080/auth/realms/tdoc-api/protocol/openid-connect/auth...

Which failed on browser showingERR_CONNECTION_REFUSED, cause I understand this service can not be resolved externally from the host.

Also I tried changing keycloak.json to:

{
  "realm": "${realm}",
  "auth-server-url": "http://localhost:8012/auth",
  "ssl-required": "none",
  "resource": "${client_id}",
  "public-client": true,
  "confidential-port": 0
}

But my app failed when trying to log in showing a 500 internal server error:

[WARN ] 12:08:46.150 org.keycloak.adapters.KeycloakDeployment.resolveUrls() - Failed to load URLs from http://localhost:8012/auth/realms/${realm}/.well-known/openid-configuration
java.net.ConnectException: Connection refused (Connection refused)

Because it can not resolve from inside the container my service exposed locally in 8012 port. Which I think was the answer provided in this post: https://stackoverflow.com/a/74929659

Does anyone know why didnt work for me this solution?

I was able to fix it setting a environment in docker-compose.yml:

More context of my docker environment:

version: '3'
services:
  app-db:
    image: mysql:5.7
    ports:
      - "3309:3306"
    environment:
      MYSQL_ROOT_PASSWORD: example
    networks:
      - my-network

  my-app:
    build: .
    ports:
      - "8090:8080"
      - "8000:8000"
    environment:
      - JAVA_OPTS=...
    volumes:
      - ./app:/usr/local/tomcat/webapps/my-app
    depends_on:
      - app-db
    networks:
      - my-network

  keycloak:
    image: quay.io/keycloak/keycloak:16.1.1
    ports:
      - "8012:8080"
    environment:
      - DB_VENDOR=mysql
      - DB_ADDR=keycloak-db
      - DB_PORT=3306
      - DB_USER=keycloak_user
      - DB_PASSWORD=keycloak_pass
      - DB_DATABASE=keycloak
      - PROXY_ADDRESS_FORWARDING=true
      - KEYCLOAK_FRONTEND_URL=http://localhost:8012/auth
    volumes:
      - ./themes:/opt/jboss/keycloak/themes
    depends_on:
      - keycloak-db
    networks:
      - my-network

  keycloak-db:
    image: mysql:5.7
    ports:
      - "3307:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=keycloak_pass
      - MYSQL_DATABASE=keycloak
      - MYSQL_USER=keycloak_user
      - MYSQL_PASSWORD=keycloak_pass
    volumes:
      - ./volumes/mysql:/var/lib/mysql
    networks:
      - my-network

networks:
  my-network:
    external: true
    name: my-network


Solution

    1. Why http://keycloak:8080/auth didn't work?

      As you noticed, this works only inside Docker, where keyclock is resolvable via the internal Docker network. But when the browser gets redirected to that URL, it tries to resolve http://keycloak:8080 from your host OS, which fails — because keycloak is not a real hostname on your host machine. That's why it ends up with ERR_CONNECTION_REFUSED error.

    2. Why http://localhost:8012/auth didn't work?

      With this auth-server-url, your app (inside the my-app container) tried to connect to localhost:8012, but in container-land, localhost means "inside this container", not your host machine.

      So it's trying to find Keycloak inside the same container (where it doesn't exist), and fails with Connection refused exception.

    3. Why KEYCLOAK_FRONTEND_URL=http://localhost:8012/auth works as expected?

      When you set KEYCLOAK_FRONTEND_URL, you told Keycloak itself: "When generating URLs (like the redirect URI), use http://localhost:8012/auth."

      This works because:

      • Your Java app talks to Keycloak using the internal http://keycloak:8080/auth URL.

      • The browser gets redirected to the correct host-facing URL: http://localhost:8012/auth.

      That solves both sides:

      • internal container -> container hostname

      • browser -> localhost-bound service