We are going to deploy Keycloak using Docker Swarm.
We will install Docker Swarm on CentOS 7 and create a stack for Keycloak. Note that Keycloak realm configuration is not covered in this article.
Pre-requisites
- Three CentOS 7 VMs with root access.
- Private IP address for the master node (e.g. 10.11.1.80)
- MySQL database and user credentials to store Keycloak configuration.
Install Docker Engine
Run the following commands on all nodes.
Install packages:
# yum install -y yum-utils
Add Docker repository:
# yum-config-manager --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
Install Docker:
# yum install docker-ce docker-ce-cli containerd.io
Enable and start the service:
# systemctl enable docker && systemctl start docker
Configure Firewall
Open the following ports between all nodes:
- TCP port 2377 for cluster management communications.
- TCP and UDP port 7946 for communication among nodes.
- UDP port 4789 for overlay network traffic.
Iptables config snippet:
-A INPUT -s 10.11.1.0/24 -p tcp -m multiport --dports 2377,7946 -j ACCEPT -A INPUT -s 10.11.1.0/24 -p udp -m multiport --dports 4789,7946 -j ACCEPT
Create a Swarm
On the master node, initialise the swarm:
# docker swarm init --advertise-addr 10.11.1.80
Swarm initialized: current node (uglx1edsgztziitrlg2uwuls2) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN...juf 10.11.1.80:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Add Workers to Swarm
Add the other two servers as worker nodes:
# docker swarm join --token SWMTKN...juf 10.11.1.80:2377
Verify Swarm
# docker info # docker node ls
Deploy Portainer Agent (Optional)
This part is optional. I find Portainer somewhat useful.
Content of the file compose.yml can be seen below.
services:
agent:
image: portainer/agent:latest
ports:
- "9001:9001/tcp"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /var/lib/docker/volumes:/var/lib/docker/volumes
version: '3.8'
Deploy a new stack:
# docker stack deploy --compose-file compose.yml portainer
Deploy Keycloak
Note that creating a dedicated network is useful but not required. Create a new network:
# docker network create --attachable --driver overlay --gateway 10.55.254.1 --subnet 10.55.254.0/24 --scope swarm --label keycloak_net --internal keycloak_net
Content of the file kc-compose.yml can be seen below.
version: '3.8'
services:
keycloak:
image: jboss/keycloak:11.0.0
environment:
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: changeme
KEYCLOAK_HTTP_PORT: 8080
KEYCLOAK_HTTPS_PORT: 8443
KEYCLOAK_LOGLEVEL: INFO
DB_VENDOR: mysql
DB_ADDR: database.hl.local
DB_PORT: 3306
DB_DATABASE: keycloak_swarm
DB_USER: keycloak_swarm
DB_PASSWORD: changeme
networks:
- keycloak_net
ports:
- "8080:8080/tcp"
- "8443:8443/tcp"
restart: unless-stopped
volumes:
- "/etc/hosts:/etc/hosts" ## poor man's DNS
- "/opt/keycloak/certs/:/etc/x509/https" ## map certificates to container
deploy:
mode: replicated
replicas: 1
placement:
max_replicas_per_node: 1
constraints:
- node.role==worker
resources:
limits:
cpus: '1.50'
memory: 1024M
reservations:
cpus: '0.05'
memory: 128M
networks:
keycloak_net:
external: true
Start with a single replica.
Keycloak image allows us to specify both a private key and a certificate for serving HTTPS. Directory /opt/keycloak/certs/ contains two files: tls.crt and tls.key. As per documentation, those files need to be mounted on /etc/x509/https directory. If you don’t use/require HTTPS, comment the lines out.
Deploy a new stack:
# docker stack deploy --compose-file kc-compose.yml keycloak
Check service logs:
# docker service logs -f keycloak_keycloak
List services:
# docker service ls ID NAME MODE REPLICAS IMAGE PORTS pwu4krhlcqkq keycloak_keycloak replicated 1/1 (max 1 per node) jboss/keycloak:11.0.0 *:8080->8080/tcp, *:8443->8443/tcp qoywxieiy53h portainer_agent replicated 1/1 portainer/agent:latest *:9001->9001/tcp
References
https://docs-stage.docker.com/engine/swarm/stack-deploy
https://registry.hub.docker.com/r/jboss/keycloak
