Collect diagnostics in containers
The same diagnostics tools that are useful for diagnosing .NET issues in other scenarios also work in Docker containers. However, some of the tools require special steps to work in a container. This article covers how tools for gathering performance traces and collecting dumps can be used in Docker containers.
Use .NET CLI tools in a container
These tools apply to: ✔️ .NET Core 3.1 SDK and later versions
The .NET global CLI diagnostic tools (dotnet-counters, dotnet-dump, dotnet-gcdump, dotnet-monitor, and dotnet-trace) are designed to work in a wide variety of environments and should all work directly in Docker containers. Because of this, these tools are the preferred method of collecting diagnostic information for .NET scenarios targeting .NET Core 3.1 or later in containers.
You can also install these tools without the .NET SDK by downloading the single-file variants from the links in the previous paragraph. These installs require a global install of the .NET runtime version 3.1 or later, which you can acquire following any of the prescribed methods in the .NET installation documentation or by consuming any of the official runtime containers.
Use .NET global CLI tools in a sidecar container
If you would like to use .NET global CLI diagnostic tools to diagnose processes in a different container, bear the following additional requirements in mind:
- The containers must share a process namespace (so that tools in the sidecar container can access processes in the target container).
- The .NET global CLI diagnostic tools need access to files the .NET runtime writes to the /tmp directory, so the /tmp directory must be shared between the target and sidecar container via a volume mount. This could be done, for example, by having the containers share a common volume or a Kubernetes emptyDir volume. If you attempt to use the diagnostic tools from a sidecar container without sharing the /tmp directory, you will get an error about the process "not running compatible .NET runtime."
Use PerfCollect
in a container
This tool applies to: ✔️ .NET Core 2.1 and later versions
The PerfCollect
script is useful for collecting performance traces and is the recommended tool for collecting traces prior to .NET Core 3.0. If using PerfCollect
in a container, keep the following requirements in mind:
PerfCollect
requires additional capabilities to run theperf
tool. The minimal set of capabilities required isPERFMON
andSYS_PTRACE
. Some environments requireSYS_ADMIN
. Be sure to start the container with the necessary capabilities. If the minimal set doesn't work, then try with the full set.PerfCollect
requires some environment variables to be set prior to the app it is profiling starting. These can be set either in a Dockerfile or when you start the container. Because these variables shouldn't be set in normal production environments, it's common to just add them when starting a container that will be profiled. The two variables that PerfCollect requires are:DOTNET_PerfMapEnabled=1
DOTNET_EnableEventLog=1
Note
When executing the app with .NET 7, you must also set DOTNET_EnableWriteXorExecute=0
in addition to the preceding environment variables.
Note
.NET 6 standardizes on the prefix DOTNET_
instead of COMPlus_
for environment variables that configure .NET run-time behavior. However, the COMPlus_
prefix will continue to work. If you're using a previous version of the .NET runtime, you should still use the COMPlus_
prefix for environment variables.
Use PerfCollect
in a sidecar container
If you want to run PerfCollect
in one container to profile a .NET process in a different container, the experience is almost the same. The differences are:
- The environment variables mentioned previously (
DOTNET_PerfMapEnabled
andDOTNET_EnableEventLog
) must be set for the target container (not the one runningPerfCollect
). - The container running
PerfCollect
must have theSYS_ADMIN
capability (not the target container). - The two containers must share a process namespace.