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.
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.