3

I need my BFF service to wait for keycloak to be fully launched using condition service_health, and then start its launch. I can't set up a health check for keycloak. When searching for an answer, I come across either strange or outdated answers related to curl, which is no longer in the new version of keycloak. How do I set up the healthcheck keycloak correctly?

services:
  gateway:
    image: 'my-service-bff:0.0.1-SNAPSHOT'
    container_name: 'my-service-bff'
    ports:
      - '8080:8080'
    depends_on:
      keycloak:
        condition: service_healthy
  postgres:
    image: 'postgres:latest'
    container_name: 'postgres-db'
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: keycloakdb
      POSTGRES_USER: keycloakuser
      POSTGRES_PASSWORD: keycloakpass
    healthcheck:
      test: pg_isready -U keycloakuser -d keycloakdb
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 5s
    networks:
      - keycloak-network
  keycloak:
    container_name: keycloak
    image: quay.io/keycloak/keycloak:23.0.4
    environment:
      KC_HEALTH_ENABLED: true
      DB_VENDOR: POSTGRES
      DB_ADDR: postgres
      DB_DATABASE: keycloakdb
      DB_SCHEMA: public
      KEYCLOAK_USER: user
      KEYCLOAK_PASSWORD: user
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin
    ports:
      - "9090:8080"
    command:
      - "start-dev"
    networks:
      - 'keycloak-network'
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      # Unsuccessful attempts:
      # test: [ "CMD", "curl", "-f", "http://0.0.0.0:8080/realms/master" ]
      # test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URI.create(args[0]).toURL().openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java /tmp/HealthCheck.java http://localhost:8080/health/live']
      start_period: 10s
      interval: 30s
      retries: 3
      timeout: 5s

networks: keycloak-network: driver: 'bridge'

volumes: postgres_data: driver: 'local'

The Prototype
  • 131
  • 1
  • 4

3 Answers3

3

You could just add Curl by using the KeyCloak image in a Dockerfile and reference that Dockerfile in your docker-compose.yaml file.

To do that I create a directory inside the docker-compose.yaml directory and call it something simple like KeyCloakDockerfile and in that create your `Dockerfile so structure should look like this:

_
 |_ docker-compose.yaml
 |_ KeyCloakDockerfile/
   |_ Dockerfile

You would create the Dockerfile like so (Assuming it's RHEL or some RedHat derivative):


###### Using As Base Image ######
FROM quay.io/keycloak/keycloak:23.0.4
Non-Interactive Installations

ENV DAEMON_OPTS=-nonat ENV TERM=xterm-256color

######### Update & Upgrade the Image ########## RUN yum update -y && yum upgrade -y

Install Curl

RUN yum install -y curl

Use The ENTRYPOINT From The Original Images Dockerfile.
The Original Dockerfile https://quay.io/repository/keycloak/keycloak/manifest/sha256:122ff5badfb88afe1027bc8e1a9c85532148ee813bee30c01173947a445d4fe7

ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

Then in your docker-compose.yaml you can change you KeyCloak service to look like this:

  keycloak:
    container_name: keycloak
    build:
      context: .
      dockerfile: ./KeyCloakDockerfile/Dockerfile
    environment:
      KC_HEALTH_ENABLED: true
      DB_VENDOR: POSTGRES
      DB_ADDR: postgres
      DB_DATABASE: keycloakdb
      DB_SCHEMA: public
      KEYCLOAK_USER: user
      KEYCLOAK_PASSWORD: user
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin
    ports:
      - "9090:8080"
    command:
      - "start-dev"
    networks:
      - 'keycloak-network'
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      # Unsuccessful attempts:
      test: [ "CMD", "curl", "-f", "http://0.0.0.0:8080/realms/master" ]
      start_period: 10s
      interval: 30s
      retries: 3
      timeout: 5s

This way when you run docker compose up -d if the image has not been built it will build it then run it with the other Services defined in the docker-compose.yaml.

SECURITY SIDENOTE !

Looking the the repository that Image of KeyCloak we're using has some vulerabilities present as is labeled here:

https://quay.io/repository/keycloak/keycloak/manifest/sha256:122ff5badfb88afe1027bc8e1a9c85532148ee813bee30c01173947a445d4fe7?tab=vulnerabilities

It states that version 3.90.0-4.el9_3 should be upgraded to version 0:3.90.0-6.el9_3. This should be paid attentions to when using KeyCloak as good practise.

Definity
  • 141
  • 2
0

I created a HealthCheck using docker compose and keycloak imagem: quay.io/keycloak/keycloak:26.0.7

  healthcheck:
      test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java /tmp/HealthCheck.java http://localhost:9000/health/live']
      interval: 5s
      timeout: 5s
      retries: 30
0

try to use this line

test: ['CMD-SHELL', '[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck { public static void main(String[] args) throws java.lang.Throwable { System.exit(java.net.HttpURLConnection.HTTP_OK == ((java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection()).getResponseCode() ? 0 : 1); } }" > /tmp/HealthCheck.java && java /tmp/HealthCheck.java http://localhost:9000/health/live']