Private DNS for Native Windows Docker Container

Docker Windows containers have a number of shortcomings, particularly around networking. One showstopper is that it doesn’t use the DNS of its host server. The expected behaviour in (Linux) Docker containers is that the Docker engine creates a virtual DNS for containers. The Docker DNS resolves containers by name (for Docker Swarm / Docker Compose) or delegates to the host DNS configuration. There are options to override this behaviour if necessary.

Native Windows containers don’t do this. Docker for Windows will resolve container names from the Swarm and will then use the default external DNS (Google DNS on 8.8.8.8) to resolve external addresses. It will not use the host machine DNS settings nor can its behaviour be overridden with the --dns flag. This is a serious problem if your container depends on services within a private / corporate network.

This appears to be an issue with the Docker Windows images (nanoserver / windowservercore) rather than with the engine. Microsoft might get round to fixing it but given its half-hearted support for Docker, it might not.

Workaround

A workaround is to initialize the container with an ENTRYPOINT script. The script uses the Set-DnsClientServerAddress Powershell command to add any required DNS servers to the one provided by Docker:

$cmd = $args

# Add the local DNS to the container's DNS Server list
$LocalDns = '1.1.1.1' # Your DNS server
$InterfaceIndex = (Get-NetAdapter).IfIndex
$DnsServerList = [array]$LocalDns + (Get-DnsClientServerAddress -InterfaceIndex $InterfaceIndex).ServerAddresses
Write-Host "DNS server list: $($DnsServerList)"
Set-DnsClientServerAddress -InterfaceIndex $InterfaceIndex -ServerAddresses $DnsServerList

# Run the Docker COMMAND
Write-Host "Running command: $($cmd)"
cmd.exe /c "$cmd"

This can be invoked on startup in a container running in Docker Swarm with the following configuration:

version: '3.8'
services:
  windowsservercore:
    image: mcr.microsoft.com/windows/servercore:ltsc2019
    volumes:
    - ./scripts:c:/scripts
    entrypoint: "powershell -File C:\\\\scripts\\\\DnsFix.ps1"
    command: powershell -Command 'Start-Sleep -s 3600; return 0'
    networks:
    - customnet
    
networks:
  customnet:
    driver: overlay

This assumes that you’ve put the fix in a file called DnsFix.ps1 in the .\scripts\ directory, relative to the Swarm configuration file.

Note that we need the full Windows servercore image. Windows nanoserver won’t do as it doesn’t have Powershell.

Leave a Reply

Your email address will not be published. Required fields are marked *