Reputation: 14479
I want to provision a Spring Boot app into a Windows Docker Container which is hosted on a Windows Docker Host (which is virtualized on a Mac, but this is another story ;) ) with Ansible. I already successfully used Ansible Windows Modules to provision a Spring Boot app to Windows.
I´am in the final chapter and just wanted to add a health-check at the very end. As outlined in the blogpost without Docker this is easy:
- name: Wait until our Spring Boot app is up & running
win_uri:
url: "http://localhost:8080/health"
method: GET
register: result
until: result.status_code == 200
retries: 5
delay: 5
Now with Docker Windows Containers there´s a known limitation so that you can´t use localhost
for now. We have to use the Windows Docker Containers internal Hyper-V IP address (you can see the IP after you ran a docker inspect <yourContainerIdHere>
inside the JSON output in NetworkSettings.Networks.nat.IPAddress
).
My question is: How can I obtain the Windows Docker Container´s Hyper-V internal IP address, output it inside a debug statement and do a health-check similar to the one I outlined?
Upvotes: 2
Views: 2142
Reputation: 14479
After a far to long journey to just do a simple health-check I found a solution.
At first we have to obtain the Docker Container´s IP address, which could be easily done on a Powershell with this command:
docker inspect --format '{{ .NetworkSettings.Networks.nat.IPAddress }}' <yourInstanceIdHere>
We just have to use the win_shell module.
But because this uses a Docker templating mechanism, Jinja2 templating doesn´t know, it shouldn´t interpret these command this time. We have to escape the curly braces properly, which is outlined in this so q&a already. You could use one of the suggested solutions:
"{%raw%}"{{ .NetworkSettings.Networks.nat.IPAddress }}"{%endraw%}"
or
"{{'{{'}} .NetworkSettings.Networks.nat.IPAddress {{'}}'}}"
- both will work for us here.
Now obtaining the IP address from this output, I tried to just register a result and make the health-check. Sadly this doesn´t work, because the returned stdout
and stdout_lines
do contain your IP, but also the Docker template again - but this time without the escaping sequence, which will in turn let the task fail (as a comment from Davide Guerri in this so answer already reported).
The following comment from lanwen gave an advice to the rescue: We could pipe the first win_shell output into a temporary textfile container_ip.txt
and then - in a second win_shell task - we just read the contents of that file and register an output-variable.
This seems to be easy, again we use win_shell:
win_shell: cat container_ip.txt
register: win_shell_txt_return
But hey, that´s not the whole story -> because on Windows, there are nice carriage return line feeds :), which will pollute our IP address with \r\n
at the end and will let our health-check fail again.
But again, there´s help: Ansible has a nice splitlines feature (which is slightly un-documented...) We just have to do it with a trailing [0]
to obtain the IP:
"{{ win_shell_txt_return.stdout.splitlines()[0] }}"
Now we are able to do our health-check as we wanted in the first place. Here´s the complete solution:
- name: Obtain the Docker Container´s internal IP address (because localhost doesn´t work for now https://github.com/docker/for-win/issues/458)
win_shell: "docker inspect -f {% raw %}'{{ .NetworkSettings.Networks.nat.IPAddress }}' {% endraw %} {{spring_boot_app_name}} {{ '>' }} container_ip.txt"
- name: Get the Docker Container´s internal IP address from the temporary txt-file (we have to do this because of templating problems, see https://stackoverflow.com/a/32279729/4964553)
win_shell: cat container_ip.txt
register: win_shell_txt_return
- name: Define the IP as variable
set_fact:
docker_container_ip: "{{ win_shell_txt_return.stdout.splitlines()[0] }}"
- debug:
msg: "Your Docker Container has the internal IP {{ docker_container_ip }} --> Let´s do a health-check against this URI: 'http://{{ docker_container_ip }}:{{spring_boot_app.port}}/{{spring_boot_app.health_url_ending}}'"
- name: Wait until our Spring Boot app is up & running
win_uri:
url: "http://{{ docker_container_ip }}:8080/health"
method: GET
register: health_result
until: health_result.status_code == 200
retries: 5
delay: 5
Upvotes: 3