Windows Server 2019 – Working with containers

Docker Compose Tutorial for Beginners

There are a lot of moving pieces that work together to make containers a reality in your environment, but it’s really not too difficult to get started. Let’s walk through the initial setup of turning Windows Server 2019 into a container-running mega machine.

Installing the role and feature

The amount of work that you need to accomplish here depends on whether you want to run Windows Server Containers, Hyper-V Containers, or both. The primary feature that you need to make sure that you install is Containers, which can be installed by using either the Add roles and features link from inside Server Manager, or by issuing the following PowerShell command:

Add-WindowsFeature Containers

Additionally, if you intend to run Hyper-V Containers, you need to ensure that the underlying Hyper-V components are also installed onto your container host server. To do that, install the Hyper-V role and accompanying management tools onto this same server.

As indicated following the role and feature installation, make sure to restart your server after these changes.

At this point, you may be wondering, “If my container host server needs to have the Hyper-V role installed, doesn’t that mean it must be a physical server? You can’t install the Hyper-V role onto a virtual machine, right?” Wrong. Windows Server 2019 supports something called nested virtualization, which was added for the purpose of containers. You see, requiring physical hardware is becoming a limiting factor for IT departments these days, as almost everything is done from virtual machines. It makes sense that companies would want to deploy containers, but they may also want their container host servers to be VMs, with multiple containers being run within that VM. Therefore, nested virtualization was required to make this possible. If you are running a Windows Server 2019 physical hypervisor server, and a Windows Server 2019 virtual machine inside that server, you will now find that you are able to successfully install the Hyper-V role right onto that VM. I told you virtual machines were popular, so much so that they are now being used to run other virtual machines!

Remember that we can also host and run containers on our Windows 10 machines! In order to prep a Win10 client for this purpose, simply add the Windows feature called Containers, just like on the server operating system.

Installing Docker for Windows

Now that our container host server is prepped with the necessary Windows components, we need to grab Docker for Windows from the internet. The Docker interface is going to provide us with all of the commands that are needed in order to start building and interacting with our containers.

This is the point where that Docker Hub login becomes important. If you are working through this in order to test containers on your own workstation and need to install Docker Desktop for Windows on your Win10 client, the easiest way is to visit Docker Hub, log in, and search for the Docker client software. Here is a link to that software (this is the tool you need to use if you are installing on Windows 10):

However, since I am sitting on a Windows Server 2019, my license for the server also includes licensing for Docker Enterprise, which can be pulled down without having to visit Docker Hub. If I open up an elevated PowerShell prompt and run the following two commands, my server will reach out and grab Docker Enterprise, and install it onto my server:

Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
Install-Package -Name docker -ProviderName DockerMsftProvider -Force -RequiredVersion 18.03

After package installation has finished, Docker is now configured on your server as a service, but that service needs to be started with the following command:

Start-Service docker

Docker commands

Once Docker is installed on your system, whether you are working with a Windows Server 2019 or a Windows 10 machine, you now have the Docker Engine running on your machine and it is ready to accept some commands in order to begin working with containers. If there is a single word to remember when it comes to working with containers, it is Docker. That is because every command that you issue to interact with containers will begin with the word docker. Let’s have a look are some of the common commands that you will be working with.

docker –help

This is sort of like issuing docker /?, if that were a real command. The help function for Docker will generate a list of the possible docker commands that are available to run. This is a good reference point as you get started.

docker images

After downloading some container images from a repository (we will do this for ourselves in the next section of this chapter), you can use the docker images command to view all of the images that are available on your local system.

docker search

Utilizing the search function allows you to search the container repositories (such as Docker Hub) for base container images that you might want to utilize in your environment. For example, in order to search and find images provided from inside Microsoft’s Docker Hub repository, issue the following:

docker search microsoft
docker pull

We can use docker pull to pull down container images from online repositories. There are multiple repositories from which you can get container images. Most often, you will be working with images from Docker Hub, which is where we will pull a container image from shortly. However, there are other online repositories from which you can get container images, such as Microsoft’s public container registry, known as MCR.

Here are some sample docker pull commands showing how to pull container images from Docker Hub, as well as MCR:

docker pull Microsoft\nanoserver
docker pull Microsoft\windowsservercore
docker image pull
docker image pull
docker run

This is the command for starting a new container from a base image. You will find that you can retain multiple container images in your local repository that are all based off the same container image. For example, as you add new things into your containers or update the application inside your containers, you may be building new container images that are now a subset of an existing container image. You may have numerous container images that are all named windowsservercore, for example. In this case, container tags become very important, as tags help you to distinguish between different versions of those container images. As an example, here is a command that would start a container based on a windowsservercore image for which I had associated the ltsc2019 tag:

docker run -it --rm Microsoft\windowsservercore:ltsc2019

In the preceding command, the -it switch creates a shell from which we can interact with a container, which is useful for building and testing containers, but you generally wouldn’t need that switch for launching production containers that were 100% ready to serve up applications. --rm is a cleanup switch, meaning that once this particular container exits, the container and its filesystem will be automatically deleted.

docker ps -a

You utilize docker ps when you want to view the containers that are currently running on your system.

docker info

This will summarize your Docker environment, including the number of containers that you have running and additional information about the host platform itself.

Downloading a container image

The first command we will run on our newly-created container host is docker images, which shows us all of the container images that currently reside on our system; there are none:

Of course there are no container images yet, as we haven’t downloaded any. Let’s grab a couple so that we can test this out. There is a sample container image file provided by the .NET team that showcases running a .NET application inside a Nano Server container—that one sounds like a fun way to get started with verifying that I can successfully run containers on this new host server. First, we can use docker search to check the current container images that reside inside Microsoft’s Docker Hub repository. Once we find the image that we want to download, we use docker pull to download it onto our server:

docker search microsoft
docker image pull microsoft/nanoserver

The preceding command downloaded a copy of the standard Nano Server base image, but we want to make our container do something in the end, so here is a command that will download that .NET sample image as well:

docker image pull microsoft/dotnet-samples:dotnetapp-nanoserver-1809

After the downloads are finished, running docker images once again now shows us the newly-available Nano Server container image, as well as the .NET sample image:

From these base images we are now able to launch and run a real container.

Running a container

We are so close to having a container running on our host! Now that we have installed the service, implemented Docker, imported the Docker module into our PowerShell prompt, and downloaded a base container image, we can finally issue a command to launch a container from that image. Let’s run the .NET container that we downloaded before:

docker run microsoft/dotnet-samples:dotnetapp-nanoserver-1809

The container starts and runs through its included code, and we see some fun output:

This container showcases that all components necessary for this .NET application to run are included inside the container. This container is based on Nano Server, which means it has an incredibly small footprint. In fact, looking back a few pages at the last Docker images command that we ran, I can see that this container image is only 417 MB! What a resource saving, when compared with running this application on a traditional IIS web server.

The main resource for Microsoft documentation on containers is The tools used to interact with containers are constantly changing, including changes to Docker and Kubernetes. Make sure to check over the Microsoft Docs site in order to find the latest best practices and approved installation path for preparing your container host servers.

Comments are closed.