Experimental Windows Containers Support for BuildKit Released in v0.13.0 | Docker
We are excited to announce that the latest BuildKit release, v0.13.0, contains experimental Windows Containers support. BuildKit has been around for many years and has been the default build engine on Linux since Docker Engine 23.0.0.
BuildKit is a toolkit for converting source code to build artifacts (like container images) in an efficient, expressive, and repeatable manner. BuildKit introduced the following benefits as compared with the previous Docker Builder:
- Parallelize building independent build stages and skip any unused stages.
- Incrementally transfer only the changed files in your build context between builds, also skip the transfer of unused files in your build context.
- Use Dockerfile frontend implementations with many new features.
- Avoid side effects with the rest of the API (intermediate images and containers).
- Prioritize your build cache for automatic pruning.
Since 2018, Windows Container customers have been asking for Windows support for BuildKit, as seen in the BuildKit repo and Windows Containers repo, with hundreds of reactions and comments. We have listened to our users and focused resources in the past year to light up Windows Containers support on BuildKit.
Until now, we only shipped the Buildx client on Windows for building Linux images and some very limited Windows images using cross-compilation. Today, we are introducing experimental support for Windows Containers in BuildKit, with the aim of making this available soon in your standard Docker Build.
What’s next?
In the upcoming months, we will work toward further improvements, including:
- General Availability (GA) ready: Improving release materials, including guides and documentation.
- Integration with Docker Engine: So you can just run
docker build
. - OCI worker support: On Linux, there is an option to run BuildKit with only runc using the OCI worker. Currently, only the containerd worker is supported for Windows.
- Container driver: Add support for running in the container driver.
- Image outputs: Some image outputs supported by Linux may not work on Windows and need to be tested and assessed. These include exporting an image to multiple registries, checking if keys for image output are supported, and testing multi-platform image-building support.
- Building other artifacts: BuildKit can be used to build other artifacts beyond container images. Work needs to be done in this area to cross-check whether other artifacts, such as binaries, libraries, and documentation, are also supported on Windows as it is on Linux.
- Running buildkitd doesn’t require Admin: Currently, running buildkitd on Windows requires admin privileges. We will be looking into running buildkitd on low privileges, aka “rootless”.
- Export cache: Investigations need to be done to confirm whether specific cache exporters (inline, registry, local, gha [GitHub Actions], 3, azblob) are also supported on Windows.
- Linux parity: Identifying, accessing, and closing the feature parity gap between Windows and Linux.
Walkthrough — Build a basic “Hello World” image with BuildKit and Windows Containers
Let’s walk through the process of setting up BuildKit, including the necessary dependencies, and show how to build a basic Windows image. For feedback and issues, file a ticket at Issues · moby/buildkit (github.com) tagged with area/windows.
The platform requirements are listed below. In our scenario, we will be running a nanoserver:ltsc2022
base image with AMD64.
- Architecture: AMD64, Arm64 (binaries available but not officially tested yet).
- Supported operating systems: Windows Server 2019, Windows Server 2022, Windows 11.
- Base images:
servercore:ltsc2019
,servercore:ltsc2022
,nanoserver:ltsc2022
. See the compatibility map.
The workflow will cover the following steps:
- Enable Windows Containers.
- Install containerd.
- Install BuildKit.
- Build a simple “Hello World” image.
1. Enable Windows Containers
Start a PowerShell terminal in admin privilege mode. Run the following command to ensure the Containers feature is enabled:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V, Containers -All
If you see RestartNeeded as True on your setup, restart your machine and reopen an Administrator PowerShell terminal (Figure 1). Otherwise, continue to the next step.
2. Install containerd
Next, we need to install containerd, which is used as the container runtime for managing containers and images.
Note: We currently only support the containerd worker. In the future, we plan to add support for the OCI worker, which uses runc and will therefore remove this dependency
Run the following script to install the latest containerd release. If you have containerd already installed, skip the script below and run Start-Service containerd
to start the containerd service.
Note: containerd v1.7.7+ is required.
# If containerd previously installed run:
Stop-Service containerd
# Download and extract desired containerd Windows binaries
$Version="1.7.13" # update to your preferred version
curl.exe -L https://github.com/containerd/containerd/releases/download/v$Version/containerd-$Version-windows-amd64.tar.gz -o containerd-windows-amd64.tar.gz
tar.exe xvf .containerd-windows-amd64.tar.gz
# Copy and configure
Copy-Item -Path ".bin" -Destination "$Env:ProgramFilescontainerd" -Recurse -Container:$false -Force
cd $Env:ProgramFilescontainerd
.containerd.exe config default | Out-File config.toml -Encoding ascii
# Copy
Copy-Item -Path .bin* -Destination (New-Item -Type Directory $Env:ProgramFilescontainerd -Force) -Recurse -Force
# add the binaries (containerd.exe, ctr.exe) in $env:Path
$Path = [Environment]::GetEnvironmentVariable("PATH", "Machine") + [IO.Path]::PathSeparator + "$Env:ProgramFilescontainerd"
[Environment]::SetEnvironmentVariable( "Path", $Path, "Machine")
# reload path, so you don't have to open a new PS terminal later if needed
$Env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
# configure
containerd.exe config default | Out-File $Env:ProgramFilescontainerdconfig.toml -Encoding ascii
# Review the configuration. Depending on setup you may want to adjust:
# - the sandbox_image (Kubernetes pause image)
# - cni bin_dir and conf_dir locations
Get-Content $Env:ProgramFilescontainerdconfig.toml
# Register and start service
containerd.exe --register-service
Start-Service containerd
3. Install BuildKit
Note: Ensure you have updated to the latest version of Docker Desktop.
Run the following script to download and extract the latest BuildKit release.
$version = "v0.13.0" # specify the release version, v0.13+
$arch = "amd64" # arm64 binary available too
curl.exe -LO https://github.com/moby/buildkit/releases/download/$version/buildkit-$version.windows-$arch.tar.gz
# there could be another `.bin` directory from containerd instructions
# you can move those
mv bin bin2
tar.exe xvf .buildkit-$version.windows-$arch.tar.gz
## x bin/
## x bin/buildctl.exe
## x bin/buildkitd.exe
Next, run the following commands to add the BuildKit binaries to your Program Files
directory, then add them to the PATH
so they can be called directly.
# after the binaries are extracted in the bin directory
# move them to an appropriate path in your $Env:PATH directories or:
Copy-Item -Path ".bin" -Destination "$Env:ProgramFilesbuildkit" -Recurse -Force
# add `buildkitd.exe` and `buildctl.exe` binaries in the $Env:PATH
$Path = [Environment]::GetEnvironmentVariable("PATH", "Machine") + `
[IO.Path]::PathSeparator + "$Env:ProgramFilesbuildkit"
[Environment]::SetEnvironmentVariable( "Path", $Path, "Machine")
$Env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + `
[System.Environment]::GetEnvironmentVariable("Path","User")
Run buildkitd.exe
. You should expect to see something as shown in Figure 2:
Now we can set up buildx (the BuildKit client) to use our BuildKit instance. Here we will create a Builder item that points to our Buildkit instance we just started, by running:
docker buildx create --name buildkit-exp --use --driver=remote npipe:////./pipe/buildkitd
Here we are creating a new instance of a builder and pointing it to our BuildKit instance. BuildKit will listen on npipe:////./pipe/buildkitd
.
Notice that we also name the builder, here, we call it buildkit-exp
, but you can name it whatever you want. Just remember to add --use
to set this as the current builder.
Let’s test our connection by running docker buildx inspect
(Figure 3):
All good!
You can also list and manage your builders. Run docker buildx ls
(Figure 4).
4. Build “Hello World” image
We will be building a simple “hello world” image as shown in the following the Dockerfile.
FROM mcr.microsoft.com/windows/nanoserver:ltsc2022
COPY hello.txt C:
CMD ["cmd", "/C", "type C:\hello.txt"]
Run the following commands to create a directory and change directory to sample_dockerfile
.
mkdir sample_dockerfile
cd sample_dockerfile
Run the following script to add the Dockerfile shown above and hello.txt
to the sample_dockerfile
directory.
Set-Content Dockerfile @"
FROM mcr.microsoft.com/windows/nanoserver:ltsc2022
USER ContainerAdministrator
COPY hello.txt C:/
RUN echo "Goodbye!" >> hello.txt
CMD ["cmd", "/C", "type C:\hello.txt"]
"@
Set-Content hello.txt @"
Hello from buildkit!
This message shows that your installation appears to be working correctly.
"@
Now we can use buildx
to build our image and push it to the registry (see Figure 5):
docker buildx build --builder buildkit-exp --push -t /hello-buildkit .
If you are utilizing Docker Hub as your registry, run docker login
before running buildx build
(Figure 6).
Congratulations! You can now run containers with standard docker run
:
docker run /hello-buildkit
Get started with BuildKit
We encourage you to test out the released experimental Windows BuildKit support v0.13.0. To start out, feel free to follow the documentation or blog, which will walk you through building a simple Windows image with BuildKit. File feedback and issues at Issues · moby/buildkit (github.com) tagged with area/windows.
Learn more
Thank you
A big thanks to @gabriel-samfira, @TBBle, @tonistiigi, @AkihiroSuda, @crazy-max, @jedevc, @thaJeztah, @profnandaa, @iankingori[LX11] , and many other key community members who have contributed to enabling Windows Containers support on BuildKit. We also thank Windows Container developers who continue to provide valuable feedback and insights.