Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: December 7, 2024
Docker is a container platform for developing, distributing, and running containerized applications natively on the Linux kernel. While designed for Linux, we can run Docker on Windows via the Windows Subsystem for Linux (WSL). However, setting up Docker on Windows 10 or 11 has different requirements than setting it up on Windows Server. Albeit different, we can run Docker Windows containers on Windows Server with a supported container runtime environment. Further, Windows Server is the only option for running Docker on Windows in a cloud environment (AWS, Azure, etc.).
In this tutorial, we’ll learn to set up Docker on Windows Server. The only prerequisite we need is a machine running Windows Server (2022, 2019, or 2016) as the operating system.
We can choose from three supported container runtimes: Docker CE/Moby, containerd, and Mirantis Container Runtime. Let’s use the Docker CE (Community Edition), which is managed by the open-source Moby project. Microsoft provides a Powershell script that can be run to install the Docker runtime and configure the environment for container-related operating system features on Windows Server.
Let’s start a Powershell session and run the command to install the Docker CE:
PS C:\Windows\system32>Invoke-WebRequest
-UseBasicParsing "https://raw.githubusercontent.com/microsoft/Windows-Containers/Main/helpful_tools/Install-DockerCE/install-docker-ce.ps1"
-o install-docker-ce.ps1
.\install-docker-ce.ps1
When we run this script for the first time, it performs the prerequisite setup:
The system performs an automatic restart during the installation process. When we aren’t the first user or the script installer, we can always run the script again to verify that the system is set for Docker:
Querying status of Windows feature: Containers...
Feature Containers is already enabled.
DOCKER default
Installing Docker... C:\Users\Administrator\DockerDownloads\docker-27.3.1\docker\docker.exe
Installing Docker daemon... C:\Users\Administrator\DockerDownloads\docker-27.3.1\docker\dockerd.exe
Configuring the docker service...
Waiting for Docker daemon...
Successfully connected to Docker Daemon.
The following images are present on this machine:
REPOSITORY TAG IMAGE ID CREATED SIZE
Script complete!
Let’s run the docker commands docker version and docker info to get details about the new installation:
$ docker version
Client:
Version: 27.3.1
OS/Arch: windows/amd64
Server: Docker Engine - Community
Engine:
Version: 27.3.1
OS/Arch: windows/amd64
$ docker info
Client:
Version: 27.3.1
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 27.3.1
Storage Driver: windowsfilter
Windows:
Kernel Version: 10.0 20348 (20348.1.amd64fre.fe_release.210507-1500)
Operating System: Microsoft Windows Server Version 21H2 (OS Build 20348.2849)
OSType: windows
Architecture: x86_64
Docker Root Dir: C:\ProgramData\docker
Product License: Community Engine
We’ve completed the Docker setup on Windows Server and can start using it.
Let’s pull or download a Windows Server base image from the Microsoft Container Registry. The Nano Server is an ultralight base image for Windows Server containers:
$ docker pull mcr.microsoft.com/windows/nanoserver:ltsc2022
ltsc2022: Pulling from windows/nanoserver
f66768ec6d65: Pull complete
Digest: sha256:be37c9e8bf388c4e3ef27b4a2592b94adab551e231644ce3c9d4d3dc0a50af41
Status: Downloaded newer image for mcr.microsoft.com/windows/nanoserver:ltsc2022
mcr.microsoft.com/windows/nanoserver:ltsc2022
Notably, the tag of the base image should match the OS version; ltsc2022 for WindowsServer 2022, ltsc2019 for Windows Server 2019, and so on. These base images are themselves based on the Windows 10 OS. Therefore, we can run only Windows containers from these images by default.
Let’s list images:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mcr.microsoft.com/windows/nanoserver ltsc2022 890e4cf2e171 3 weeks ago 293MB
It should list the downloaded image.
Let’s run a Windows container from the pulled image:
$ docker run -it mcr.microsoft.com/windows/nanoserver:ltsc2022 cmd.exe
Microsoft Windows [Version 10.0.20348.2849]
(c) Microsoft Corporation. All rights reserved.
C:\>
It starts a command prompt within the Windows container. Notably, it lists the Windows version as 10.0 because we’re within a container. We can exit the container with the exit command:
C:\>exit
When a container exits, it switches context to the host Windows Server. We can list the container we exited:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
79976e7b1972 mcr.microsoft.com/windows/nanoserver:ltsc2022 "cmd.exe" 4 minutes ago Exited (0) About a minute ago hopeful_tharp
It generates a container name automatically when we don’t specify one at launch time.
Let’s build a new container image from the container we just ran:
$ docker commit 79976e7b1972 helloworld
sha256:4c6db347d185012ac56555e9d31dcbe0601e739985c477a1e23b88e349d6b252
We called the new image helloworld, and can list it along with other images:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld latest 4c6db347d185 34 seconds ago 294MB
mcr.microsoft.com/windows/nanoserver ltsc2022 890e4cf2e171 3 weeks ago 293MB
Although we didn’t modify the base image we pulled, base images are typically modified and used to develop new, custom images.
Let’s launch a new Windows container using the helloworld image we just built and start an instance of Cmd.exe within the container to run an echo command in the container:
$ docker run --rm helloworld cmd.exe /s /c echo 'Hello Docker on Windows Server'
"Hello Docker on Windows Server"
It outputs the result to the shell itself from where we run the docker run command, and removes the container because we included the –rm option.
We can log in to a Docker repository using the docker login command:
docker login [OPTIONS] [SERVER]
The [SERVER] is the repository address or the Server URL; the default is https://index.docker.io/v1 for the Docker Hub. We specify username and password for options.
Let’s log in to the Docker Hub:
$ docker login -u username -p password
Login Succeeded
We need to prefix/tag an image to correspond to the Docker Hub repository we want to upload to. For example, to upload to the baeldung repository we prefix it as baeldung. Let’s tag the helloworld image we created:
$ docker image tag helloworld baeldung/helloworld
Let’s list the images:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld latest 4c6db347d185 2 hours ago 294MB
baeldung/helloworld latest 4c6db347d185 2 hours ago 294MB
mcr.microsoft.com/windows/nanoserver ltsc2022 890e4cf2e171 3 weeks ago 293MB
Indeed, the tagged image is listed.
While we’re logged in to the Docker Hub, let’s push or upload the tagged image to the repository:
$ docker push baeldung/helloworld
Using default tag: latest
The push refers to repository [docker.io/baeldung/helloworld]
8290390d708d: Pushed
afe057336777: Pushed
latest: digest: sha256:30880b447432edc2f6abf67140e477334d70b130dbc34a94e486224585897b06 size: 740
We can verify the image is uploaded by logging in to the Docker repository uploaded to.
When we don’t need an image, we can remove the image:
$ docker rmi baeldung/helloworld
Untagged: baeldung/helloworld:latest
Untagged: baeldung/helloworld@sha256:30880b447432edc2f6abf67140e477334d70b130dbc34a94e486224585897b06
Removing unneeded images is a method usually used to free up disk space.
Let’s pull the container image we just uploaded to Docker Hub:
$ docker pull baeldung/helloworld
Using default tag: latest
latest: Pulling from baeldung/helloworld
Digest: sha256:30880b447432edc2f6abf67140e477334d70b130dbc34a94e486224585897b06
Status: Downloaded newer image for baeldung/helloworld:latest
docker.io/baeldung/helloworld:latest
After that let’s run a command in a Container launched from the pulled image:
$ docker run --rm baeldung/helloworld cmd.exe /s /c echo "Hello!"
Hello!
Again, a Windows container launches, prints the output from the command, and exits.
In this article, we learned how to set up Docker on a Windows Server 2022. We can use the same procedure with any of the Docker-supported versions of Windows Server. We discussed pulling a Windows Server base image, running a Windows container from it, creating a new image from a container, and running a command in a container. Furthermore, we discussed logging in to a Docker repository (Docker Hub) to upload and download a tagged Docker image.
As always, the Docker commands’ scripts used in this article are available over on GitHub.