How to Set Up Windows Server 2016 Container Registry
A Container Registry is a centralized repository for storing, managing, and distributing container images. Rather than pulling images from the public Docker Hub or Microsoft Container Registry on every deployment, organizations can host a private registry to store proprietary images, control access, reduce external bandwidth consumption, and maintain compliance with data governance policies. Windows Server 2016 supports running a private container registry either using the open-source Docker Registry (also known as Distribution) or using Azure Container Registry for cloud-connected scenarios.
Setting up a local private registry on Windows Server 2016 allows development and operations teams to push custom-built Windows container images to the registry and pull them across multiple container hosts within the organization. This is essential for CI/CD pipelines where container images are built, tested, and deployed at scale without reliance on external internet services.
Prerequisites
To set up a container registry on Windows Server 2016, you need: Windows Server 2016 with the Containers feature installed and Docker Engine running, a dedicated server or VM for hosting the registry with sufficient storage, a valid TLS certificate (strongly recommended for production use), DNS resolution for the registry hostname, and administrative access to both the registry host and container hosts that will use it.
Step 1: Install the Containers Feature and Docker
On the server designated as the registry host, install the Containers feature and Docker if not already present:
Install-WindowsFeature -Name Containers
Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
Install-Package -Name Docker -ProviderName DockerMsftProvider -Force
Restart-Computer
Step 2: Prepare Storage for the Registry
The registry requires dedicated storage for container image layers. Create a directory on the host to serve as the registry data volume:
New-Item -ItemType Directory -Path C:registry-data
For production environments, consider placing this on a dedicated disk or storage volume with sufficient capacity for your image repository.
Step 3: Generate or Obtain a TLS Certificate
A production registry should use HTTPS with a valid TLS certificate. You can obtain a certificate from an internal CA or a public CA. For testing, generate a self-signed certificate using PowerShell:
$cert = New-SelfSignedCertificate -DnsName "registry.domain.local" -CertStoreLocation "cert:LocalMachineMy" -NotAfter (Get-Date).AddYears(5)
Export the certificate to PFX format for use by the registry container:
$pwd = ConvertTo-SecureString -String "CertPassword123!" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath C:registry-certsregistry.pfx -Password $pwd
Extract the certificate and key files in PEM format for the Docker registry:
openssl pkcs12 -in C:registry-certsregistry.pfx -clcerts -nokeys -out C:registry-certsdomain.crt -passin pass:CertPassword123!
openssl pkcs12 -in C:registry-certsregistry.pfx -nocerts -nodes -out C:registry-certsdomain.key -passin pass:CertPassword123!
Step 4: Pull and Run the Registry Container
The Docker Registry is available as a Linux container image. For a Windows Server 2016 host, you can run it using Docker for Windows or Hyper-V Containers. Alternatively, Microsoft provides guidance for running a registry using Windows-compatible images. Pull the registry image:
docker pull registry:2
Run the registry container with TLS configured and data persistence via the volume mount:
docker run -d -p 443:443 --name registry --restart always -v C:registry-data:C:varlibregistry -v C:registry-certs:C:certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=C:certsdomain.crt -e REGISTRY_HTTP_TLS_KEY=C:certsdomain.key registry:2
Step 5: Configure Docker Clients to Trust the Registry
On each container host that will use the private registry, configure Docker to trust the registry’s TLS certificate. For a self-signed certificate, copy the certificate to the Docker cert store on each client host:
New-Item -ItemType Directory -Path C:ProgramDatadockercerts.dregistry.domain.local
Copy the certificate file to this directory and rename it ca.crt:
Copy-Item C:registry-certsdomain.crt C:ProgramDatadockercerts.dregistry.domain.localca.crt
Restart the Docker service on the client:
Restart-Service Docker
Step 6: Push an Image to the Private Registry
To push a container image to the private registry, first tag the image with the registry’s hostname and port:
docker tag mcr.microsoft.com/windows/servercore:ltsc2016 registry.domain.local/windowsservercore:ltsc2016
Push the tagged image to the registry:
docker push registry.domain.local/windowsservercore:ltsc2016
Push a custom application image:
docker tag my-iis-app:v1 registry.domain.local/my-iis-app:v1
docker push registry.domain.local/my-iis-app:v1
Step 7: Pull an Image from the Private Registry
On any configured container host, pull an image from the private registry:
docker pull registry.domain.local/my-iis-app:v1
List images stored in the registry by querying the Registry API:
Invoke-RestMethod -Uri "https://registry.domain.local/v2/_catalog" -UseBasicParsing
Step 8: Configure Registry Authentication
For production use, enable basic authentication on the registry to prevent unauthorized access. Create a htpasswd credentials file and mount it into the registry container. Use the htpasswd tool or create a compatible credentials entry:
docker run --entrypoint htpasswd registry:2 -Bbn admin StrongPassword123! > C:registry-authhtpasswd
Add authentication to the registry container configuration by setting environment variables:
-e REGISTRY_AUTH=htpasswd -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=C:authhtpasswd
Step 9: Add a Firewall Rule
Allow inbound traffic to the registry port through Windows Firewall:
New-NetFirewallRule -DisplayName "Docker Registry HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
A private container registry on Windows Server 2016 is an essential component of enterprise container infrastructure, enabling controlled distribution of Windows container images, faster deployments through local caching, and compliance with data residency and security requirements.