Deploying Keycloak docker image 25.0 in Azure Container App

Hello Keycloak ommunity,

Our team is trying to deploy the Keycloak 25.0 image in Azure Container Apps, and we have encountered many issues, especially with exposing the admin console using Azure Container Apps’ built-in ingress.

We need to know if Keycloak can work on container App or its not supported, as there is no offcial documentation.

And if someone can help on this erreur:

upstream connect error or disconnect/reset before headers. retried and the latest reset reason: connection termination

Here our dockerfile configuration


Thanks

We have battled extensively with keycloak to make it work in Azure. We now have it working, fully clustered, Postgres connected, with health, metrics and admin console all working. Wasn’t easy as documentation is badly lacking.

May I recommend you run the kc.sh build AFTER you set the database settings. In your case, it’ll be right at the end.

Try adding these at the end of your Dockerfile before your run the kc.sh build:

ENV KC_DB_URL_PROPERTIES=?sslmode=verify-full

# Download azure root cert
# https://github.com/keycloak/keycloak/issues/17606
RUN curl https://dl.cacerts.digicert.com/DigiCertGlobalRootCA.crt.pem -o /opt/keycloak/.postgresql/root.crt

and add that after the build:

# Enabling SHA1 algorithm in SSL validation to fix flawed Azure Postgres Cert
# https://github.com/keycloak/keycloak/issues/17320
USER root
RUN ["sed", "-i", "s/SHA1, //g", "/usr/share/crypto-policies/DEFAULT/java.txt"]

Hopefully this gives you better results.

Forgot to mention you’ll obviously have to add this too:

RUN mkdir -p /opt/keycloak/.postgresql

@uvznab Thank you soo much for your answer back.

Please what container solution did you use ? Kub Cluster or Azure Container App.
In our case, we use azure container app, and the application is UP, but we find problem to expose in port 8443, or Maybe Azure Container app ingress is not well configured.

upstream connect error or disconnect/reset before headers. retried and the latest reset reason: connection termination

image

Thank you

Definitely Azure Container App. We tried everything, from VM’s, web apps, KT8 to Azure functions. All worked, except… each had their own flaws. So far, Container App works the best.
Expose port 8080. And, when you’re ready, port 9000 too.
You don’t need SSL on KC - that’s provided so elegantly on your ingress LB.

Could you provide your deployment files (e.g. bicep)? I’m struggling to get even the basic ‘start-dev’ example up and running on azure container app.

Not sure what does “up and running” look like without a security context if you were successful… Can you share your error messages/console output?

I’m in the same boat. I’ve been fighting with Azure all day with no success. I’ve gotten the furthest with a Web App setup to pull the image from ```

I wasn't able to get anywhere running it as a container app.  

Is it supposed to respond to a non-localhost address while in dev mode?

I see that I was unclear in my original post.

I currently have my test cluster up and running as an Azure Container App now. I will post a minimal example later when I have time.

@uvznab how do you configured your infinispan cluster? Currently I’m using AzurePing (aka discovery via Azure Blob Storage), but it would be nice to get rid of that dependency.

Keycloak Web app setup works fine in production except:

  • Server “falls asleep” on the lower tier and needs time to “wake up”
  • Can only expose one port, which means you lose metrics, health and management API

Container app doesn’t have those limitations - but it’s tiny notch up in complexity. Really small differences.

If you use dev-mode without SSL, I’m pretty sure it won’t respond to a non-localhost address

We’re using JDBCPing on Azure through the Postgres database. It has proven less complicated than AzurePing, more reliable, but mostly, cheaper (assuming you need the database regardless).
Here’s what we did:

  1. Created a cache-ispn-jdbc-ping.xml file with our database setting
  2. Modified the Dockerfile to copy that xml to /opt/keycloak/conf
  3. Set the env var cache-config-file=cache-ispn-jdbc-ping.xml
  4. To be sure, we ran keycloak with infinispan logs on to make sure it’s working fine (KC_LOG_LEVEL=org.infinispan:DEBUG,org.jgroups:DEBUG)

If there’s interest, I’ll publish a full writeup on each step.

@tidecloak thanks! I basically do exactly the same, but using AzurePing instead of JDBCPing.

How do you chose the correct ip addr for bind_addr, currently I do -Djgroups.bind_addr=match-address:100.\*, but this doesn’t feels future-proof.

That’s part of the beauty in JDBCPing: no more that TCP rubbish.
There’s no bind_addr, bind_port and the likes.
Instead, you have a connection_url as a connection string pointing to your postgres database, and you’re set.

That can’t be correct.

JDBCPing is discover, but you still need transport.

I’m using AzurePing as discover protocol and TCP as transport protocol. I would guess you do the same.

But that leaves the issue that the TCP transport protocol can bind to one of two IP addresses (at least in my containers); 100.x.x.x or 169.x.x.x, but only 100.x.x.x is reachable by the other replicas (I’m using Azure Container Apps btw).

If you use dev-mode without SSL, I’m pretty sure it won’t respond to a non-localhost address

This may explain much of my issues.

You just had to get technical, didn’t you… :laughing: Fine
While JDBC is technically discovery protocol, it’s not a network-based one. The discovery is done via a table on the shared database. And yes, it technically needs transport to connect to a database, but in this protocol, that layer is implied because of the URL/connection string to the database. By setting the URL, the transport layer has only one possible route to reach it, therefore, one binded interface.
For any of the MPing protocols that utilise multicast, explicit binding is mandatory. That’s why you see it in most ping protocols.
See required settings of JDBCPing here.
From memory, Azure used to restrict IGMP so multicast wouldn’t work on their services (Service Fabric, VM, Webapps, etc) but they might allow it now on ContainerApps. If you get it to work, let me know. That’ll be very interesting!

@SimoTabtaoui did you ever find a sollution to this problem? No matter what I try, i keep getting your same error

upstream connect error or disconnect/reset before headers. retried and the latest reset reason: connection termination

My ingress settings are set the same as yours, but I still can’t connect. I know the container is running because the logs show it running.

Check my post here on how I configured Keycloak on Azure Container Apps with 2 instances clustered and behind a proxy (Azure Application Gateway) and Azure Ping for node discovery. Keycloak 19.0.3 quarkus - ha in azure - jgroup configuration azure_ping - Miscellanaeous - Keycloak

Hi,

I’m interested on your setup. Could you share some examples?

Regards

Emil