Windows Containers with Go: HCS Shim

This package contains the Golang interface for using the Windows Host Compute Service (HCS) to launch and manage Windows Containers. It also contains other helpers and functions for managing Windows Containers such as the Golang interface for the Host Network Service (HNS), as well as code for the guest agent (commonly referred to as the GCS or Guest Compute Service in the codebase) used to support running Linux Hyper-V containers.

It is primarily used in the Moby and Containerd projects, but it can be freely used by other projects as well.


While this repository can be used as a library of sorts to call the HCS apis, there are a couple binaries built out of the repository as well. The main ones being the Linux guest agent, and an implementation of the runtime v2 containerd shim api.

Linux Hyper-V Container Guest Agent

To build the Linux guest agent itself all that's needed is to set your GOOS to "Linux" and build out of ./cmd/gcs.

C:\> $env:GOOS="linux"
C:\> go build .\cmd\gcs\

or on a Linux machine

> go build ./cmd/gcs

If you want it to be packaged inside of a rootfs to boot with alongside all of the other tools then you'll need to provide a rootfs that it can be packaged inside of. An easy way is to export the rootfs of a container.

docker pull busybox
docker run --name base_image_container busybox
docker export base_image_container | gzip > base.tar.gz
make all

If the build is successful, in the ./out folder you should see:

> ls ./out/
delta.tar.gz  initrd.img  rootfs.tar.gz

Containerd Shim

For info on the Runtime V2 API.

Contrary to the typical Linux architecture of shim -> runc, the runhcs shim is used both to launch and manage the lifetime of containers.

C:\> $env:GOOS="windows"
C:\> go build .\cmd\containerd-shim-runhcs-v1

Then place the binary in the same directory that Containerd is located at in your environment. A default Containerd configuration file can be generated by running:

.\containerd.exe config default | Out-File "C:\Program Files\containerd\config.toml" -Encoding ascii

This config file will already have the shim set as the default runtime for cri interactions.

To trial using the shim out with ctr.exe:

C:\> ctr.exe run --runtime io.containerd.runhcs.v1 --rm windows-test cmd /c "echo Hello World!"


This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit Microsoft CLA.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

We require that contributors sign their commits to certify they either authored the work themselves or otherwise have permission to use it in this project.

We also require that contributors sign their commits using using git commit --signoff to certify they either authored the work themselves or otherwise have permission to use it in this project. A range of commits can be signed off using git rebase --signoff.

Please see the developer certificate for more info, as well as to make sure that you can attest to the rules listed. Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off.


Code must pass a linting stage, which uses golangci-lint. Since ./test is a separate Go module, the linter is run from both the root and the test directories. Additionally, the linter is run with GOOS set to both windows and linux.

The linting settings are stored in .golangci.yaml, and can be run automatically with VSCode by adding the following to your workspace or folder settings:

    "go.lintTool": "golangci-lint",
    "go.lintOnSave": "package",

Additional editor integrations options are also available.

Alternatively, golangci-lint can be installed and run locally:

# use . or specify a path to only lint a package
# to show all lint errors, use flags "--max-issues-per-linter=0 --max-same-issues=0"
> golangci-lint run

To run across the entire repo for both GOOS=windows and linux:

> foreach ( $goos in ('windows', 'linux') ) {
    foreach ( $repo in ('.', 'test') ) {
        pwsh -Command "cd $repo && go env -w GOOS=$goos && golangci-lint.exe run --verbose"

Go Generate

The pipeline checks that auto-generated code, via go generate, are up to date. Similar to the linting stage, go generate is run in both the root and test Go modules.

This can be done via:

> go generate ./...
> cd test && go generate ./...

Download Details:

Author: microsoft

Official Github: 

License: MIT


Windows Containers with Go: HCS Shim
1.10 GEEK