host.docker.internal for Sitecore Rendering Host

Anton Tishchenko
Anton Tishchenko
Cover Image for host.docker.internal for Sitecore Rendering Host

We talked about accessing your local machine from the container's network using ngrok in the previous article. But is there a way to achieve the same without using any 3rd party services like ngrok? Yes, there is a "native" Docker way. By default, Docker exposes your localhost as host.docker.internal and gateway.docker.internal inside each container. These addresses should correspond to your local IP address that is accessible from containers.

But unfortunately, this Docker functionality is buggy. They worked on improvements, but break something. And if you ping host.docker.internal inside your Sitecore containers, it will work only in the part of cases. It will work for Identity container. But unfortunately, it will fail for CM, the container that we are most interested in. I expected that it should be fixed in 4.19:

Reverted to fully patching etc/hosts on Windows (includes host.docker.internal and gateway.docker.internal again). For WSL, this behavior is controlled by a new setting in the General tab. Fixes docker/for-win#13388 and docker/for-win#13398.

But after testing it on Docker 4.19, I still can't connect to host.docker.internal from CM, something still is broken.

Ok, we can fix it by ourselves. It is just a DNS record insider your container hosts file. You will need to run the command that will update hosts file for your container:

$containerId = docker ps --filter ancestor=jss_sample-xm1-cm --format "{{.ID}}"
$ip = Get-NetIPAddress | Where-Object -FilterScript {$_.IPAddress.StartsWith("192")}
$ipAddress = $ip.IPAddress
Write-Host "Adding DNS record to container $containerId. Host: host.docker.internal. IP: $ipAddress"
$command = "'$ipAddress host.docker.internal' | Out-File -Append -Encoding ASCII -FilePath '$($Env:windir)\\system32\\drivers\\etc\\hosts'"
docker exec -it $containerId powershell $command

We take CM container by image name filtering. Then we get the local IP address. Usually, your machine can have a few IP addresses. And filtering by starting with 192 allows us to the proper one. If you have some custom local network configuration, probably you will need to change this filter. Now we have the container and the IP address, and all that we need is to append $ipAddress host.docker.internal to your hosts file inside the container.

But that is not all. There is a high probability that this connection will be closed by Windows Defender Firewall. In my case, I needed to allow node.exe process to accept inbound connections from public networks.

Windows Defender Firewall

After all these changes, I can successfully point Server side rendering engine endpoint URL to http://host.docker.internal:3000/api/editing/render and Sitecore Experience Editor will work as expected. CM will be running in the container, but the rendering host will be running on my local machine outside of the container.