Windows Containers Multi-Container Applications
Multi-Container Applications
This tutorial will walk you through using the sample Music Store application with Windows containers. The Music Store application is a standard .NET sample application, available in the aspnet GitHub repository. We’ve forked it to use Windows Containers.
Using docker-compose on Windows
Docker Compose is a great way develop complex multi-container consisting of databases, queues and web frontends.
To develop with Docker Compose on a Windows Server 2016 system, install compose too (this is not required on Windows 10 with Docker for Windows installed):
Invoke-WebRequest https://github.com/docker/compose/releases/download/1.11.1/docker-compose-Windows-x86_64.exe -UseBasicParsing -OutFile $env:ProgramFiles\docker\docker-compose.exe
To try out Compose on Windows, clone a variant of the ASP.NET Core MVC MusicStore app, backed by a SQL Server Express 2016 database.
git clone https://github.com/dockersamples/dotnet-musicstore.git
...
cd dotnet-musicstore
docker-compose -f .\docker-compose.windows.yml build
...
docker-compose -f .\docker-compose.windows.yml up
...
To access the running app from the host running the containers (for example when running on Windows 10 or if opening browser on Windows Server 2016 system running Docker engine) use the container IP and port 5000. localhost
will not work:
docker inspect -f {{ .NetworkSettings.IPAddress }} dotnet-musicstore_web_1
172.21.124.54
If using Windows Server 2016 and accessing from outside the VM or host, simply use the VM or host IP and port 5000.
What’s happening here?
Take a closer look at the docker-compose.windows.yml
file.
version: '2.1'
services:
db:
image: microsoft/mssql-server-windows-express
environment:
sa_password: "Password1"
ports:
- "1433:1433" # for debug. Remove this for production
web:
build:
context: .
dockerfile: Dockerfile.windows
environment:
- "Data:DefaultConnection:ConnectionString=Server=db,1433;Database=MusicStore;User Id=sa;Password=Password1;MultipleActiveResultSets=True"
depends_on:
- "db"
ports:
- "5000:5000"
networks:
default:
external:
name: nat
You can find more details in the Docker Compose documentation, but basically here’s what is happening.
- Two services are defined,
db
andweb
. db
is a Microsoft SQL Express image official image from Microsoft.- The password for
db
is set toPassword1
(obviously only for a developer environment). - Port 1433 on the host is mapped to the exposed port 1433 in the container which is used for debugging.
- The password for
web
is built fromDockerfile.windows
. - Compose passes along an environment variable which defines where the database is and how to connect to it. Notice that we can just refer to the database asdb
and Compose will allowweb
to discover the service there. - The port 5000 is mapped to the exposed port 5000 in the container.- The two services are added to an existing Docker network, named
nat
.
Let’s look at Dockerfile.windows
to understand it a bit better.
FROM microsoft/dotnet:1.1-sdk-msbuild-nanoserver
This pulls in the official microsoft .NET Core image based on Nano Server
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
This sets the shell to powershell.
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord
This disables the Windows DNS cache. The cache is too aggressive, and turning it off ensures the web container always queries the DNS server running in Docker to get the address of the database container.
RUN New-Item -Path \MusicStore\samples\MusicStore.Standalone -Type Directory
WORKDIR MusicStore
This creates a new directory in the container and makes it the working directory. Everything else that happens after this point will use MusicStore as the base directory.
COPY samples/MusicStore.Standalone/project.json samples/MusicStore.Standalone/project.json
COPY NuGet.config .
The command adds the project file (detailing NuGet package dependencies) and the NuGet config file.
RUN dotnet restore --no-cache .\samples\MusicStore.Standalone
This pulls in the right dependencies to the project.
COPY samples samples
RUN dotnet build .\samples\MusicStore.Standalone
This adds the rest of the app source code to the container, and compiles the project.
EXPOSE 5000
ENV ASPNETCORE_URLS http://0.0.0.0:5000
CMD dotnet run -p .\samples\MusicStore.Standalone
These last three commands expose correct ports and set the default run command for the container to run the MusicStore app.