Windows Hosts Writer (WHW) is a service designed to map the IP address from running containers (typically Docker) to a friendly canonical name written to the hosts file on Microsoft Windows.
Begin by opening docker-compose.yml
and add the following service:
whw:
image: ${WHW_IMAGE}
volumes:
- C:\windows\system32\drivers\etc:C:\driversetc
- source: \\.\pipe\docker_engine\
target: \\.\pipe\docker_engine\
type: npipe
The token ${WHW_IMAGE}
can be configured in the environment file .env like the following:
WHW_IMAGE=rahnemann/windows-hosts-writer:2.0-nanoserver-1809
With just this you are ready to get started. Spin up your compose file with docker compose up -d whw
.
Open up your hosts file in notepad to check out the the changes.
172.20.233.154 e14e090ee310 #by whw
172.20.233.154 demo-whw-1 #by whw
172.20.233.154 whw #by whw
The IPs are automatically generated by the container software so we won't worry about those for now. Notice that for the same IP whw has recorded three entries: the container ID, container name, and service name.
This is in part made possible by the volume we configured from the local machine to the container. Don't worry, when the whw container shuts down these entries are cleaned up.
If you are working with additional load balancing software such as Traefik you'll want some or all of the services to map back to the IP of the load balancer.
Add Traefik to your docker-compose.yml
followed by adding a new environment variable to our whw service.
The TERMINATION_MAP
environment variable begins with a comma delimitated list of service names followed by :traefik
.
environment:
TERMINATION_MAP: whoami:traefik
Additionally, you may wish to add aliases to each of the services. These are great when you want multiple hostname bindings mapped to the service. This can be accomplished by adding network aliases to your configuration.
networks:
default:
aliases: [ "${WHOAMI_HOST}" ]
Let's add a more complete example to our docker-compose.yml
.
services:
traefik:
isolation: ${TRAEFIK_ISOLATION}
image: ${TRAEFIK_IMAGE}
command:
- "--ping"
- "--api.insecure=true"
- "--providers.docker.endpoint=npipe:////./pipe/docker_engine"
- "--providers.docker.exposedByDefault=false"
- "--providers.file.directory=C:/etc/traefik/config/dynamic"
- "--entryPoints.websecure.address=:443"
- "--entryPoints.websecure.forwardedHeaders.insecure"
ports:
- "443:443"
- "8079:8080"
healthcheck:
test: ["CMD", "traefik", "healthcheck", "--ping"]
volumes:
- source: \\.\pipe\docker_engine\
target: \\.\pipe\docker_engine\
type: npipe
- ./docker/traefik:C:/etc/traefik
whoami:
image: stefanscherer/whoami:2.0.1
environment:
- ASPNETCORE_URLS=http://+:80
networks:
default:
aliases: [ "${WHOAMI_HOST}" ]
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami-secure.entrypoints=websecure"
- "traefik.http.routers.whoami-secure.rule=Host(`${WHOAMI_HOST}`)"
- "traefik.http.routers.whoami-secure.tls=true"
whw:
isolation: ${ISOLATION}
image: ${WHW_IMAGE}
volumes:
- C:\windows\system32\drivers\etc:C:\driversetc
- source: \\.\pipe\docker_engine\
target: \\.\pipe\docker_engine\
type: npipe
environment:
TERMINATION_MAP: whoami:traefik
Then to our .env
.
COMPOSE_PROJECT_NAME=demo
TRAEFIK_IMAGE=traefik:v2.6.3-windowsservercore-1809
TRAEFIK_ISOLATION=hyperv
ISOLATION=default
WHW_IMAGE=rahnemann/windows-hosts-writer:2.0-nanoserver-1809
WHOAMI_HOST=whoami.whw.localhost test.whw.localhost
Starting up with additional services mapped to traefik will result in the following:
172.20.231.209 415e2f33d6e0 #by whw
172.20.231.209 demo-traefik-1 #by whw
172.20.231.209 traefik #by whw
172.20.231.209 106e79e2f132 #by whw
172.20.231.209 demo-whoami-1 #by whw
172.20.231.209 whoami #by whw
172.20.231.209 whoami.whw.localhost #by whw
172.20.231.209 test.whw.localhost #by whw
172.20.233.154 e14e090ee310 #by whw
172.20.233.154 demo-whw-1 #by whw
172.20.233.154 whw #by whw
We've also added logging to the output visible through Docker so you can quickly see what whw is doing.