Skip to main content
Redhat Developers  Logo
  • AI

    Get started with AI

    • Red Hat AI
      Accelerate the development and deployment of enterprise AI solutions.
    • AI learning hub
      Explore learning materials and tools, organized by task.
    • AI interactive demos
      Click through scenarios with Red Hat AI, including training LLMs and more.
    • AI/ML learning paths
      Expand your OpenShift AI knowledge using these learning resources.
    • AI quickstarts
      Focused AI use cases designed for fast deployment on Red Hat AI platforms.
    • No-cost AI training
      Foundational Red Hat AI training.

    Featured resources

    • OpenShift AI learning
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

    Red Hat AI Factory with NVIDIA

    • Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.
    • Explore the solution
  • Learn

    Self-guided

    • Documentation
      Find answers, get step-by-step guidance, and learn how to use Red Hat products.
    • Learning paths
      Explore curated walkthroughs for common development tasks.
    • Guided learning
      Receive custom learning paths powered by our AI assistant.
    • See all learning

    Hands-on

    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.
    • Interactive labs
      Learn by doing in these hands-on, browser-based experiences.
    • Interactive demos
      Click through product features in these guided tours.

    Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics

    Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
  • Build

    Get started

    • Red Hat build of Podman Desktop
      A downloadable, local development hub to experiment with our products and builds.
    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.

    Download products

    • Access product downloads to start building and testing right away.
    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset

    References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
  • Community

    Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions

    Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github

    Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

    Join the Red Hat Developer program

    • Download Red Hat products and project builds, access support documentation, learning content, and more.
    • Explore the benefits

.NET container troubleshooting in OpenShift 4

August 4, 2025
Francisco De Melo Junior
Related topics:
.NETRuntimes
Related products:
Red Hat OpenShiftRed Hat OpenShift Container Platform

    The .NET framework is extremely useful for the deployment of applications given its large amount of libraries and resources associated with the .NET Foundation. That said, Red Hat provides the containerized version of .NET for Red Hat OpenShift. One of its main features is a cross-platform application for web and console applications for Windows, Linux, and macOS, as well as its long-term support and scalable performance.

    Microsoft's .NET fundamentals is an excellent reference providing excellent, compiled information about its core usage with extensive examples. 

    It provides automatic memory management via a garbage collector (GC), and it can be objective to tuning and investigations. I will list the steps for collecting and analyzing data, including a few troubleshooting suggestions and recommendations that can be useful for some issues.

    Deployment example

    There are several options to create a .NET container image, as author Tom Deseyn explains in his article. Let's start with an example build for .NET in local development:

    s2i --loglevel 5 build https://github.com/redhat-developer/s2i-dotnetcore --context-dir=6.0/build/test/asp-net-hello-world registry.access.redhat.com/ubi8/dotnet-60:6.0-51.20240627154839 dotnet-sample-app
    I0704 20:36:41.117474 1172557 build.go:52] Running S2I version "unknown"
    I0704 20:36:41.117634 1172557 util.go:70] Getting docker credentials for registry.access.redhat.com/ubi8/dotnet-60:6.0-51.20240627154839
    ...
    I0704 20:37:06.173553 1172557 cleanup.go:33] Removing temporary directory /tmp/s2i3632451278
    I0704 20:37:06.173561 1172557 fs.go:307] Removing directory '/tmp/s2i3632451278'
    I0704 20:37:06.173723 1172557 build.go:182] Build completed successfully
    ...
    ...
    $ docker image list
    REPOSITORY                                                       TAG                     IMAGE ID       CREATED          SIZE
    dotnet-sample-app                                                latest                  dda3eaacd694   31 seconds ago   856MB
    ...
    ###Run it:
    $ docker run  dotnet-sample-app:latest
    ---> Running application ...
    Hosting environment: Production
    Content root path: /opt/app-root/app
    Now listening on: http://0.0.0.0:8080
    Application started. Press Ctrl+C to shut down.

    Otherwise, another alternative is to build an image with the application as follows:

    FROM registry.access.redhat.com/ubi8/dotnet-80
    WORKDIR /opt/app-root/src 
    RUN dotnet new web  && dotnet publish -c Release -o /opt/app-root/publish
    WORKDIR /opt/app-root/publish
    CMD ["dotnet", "src.dll" ]

    From this image, there are two alternative approaches:

    1. Send the image to Quay.
    2. Load the image directly into Red Hat OpenShift Container Platform.

    Push to Quay (or internal registry) as follows:

    podman push localhost/image:tag quay.io/user/image <-- default should go as latest
    ...
    Writing manifest to image destination

    Deploy the image straight from the local build as follows: 

    1. Build image and tag it: $ sudo podman build --authfile=${HOME}/.docker/config.json -f Dockerfile . --tag springboot.
    2. Expose registry:
      1. $ oc patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge.
      2. $ HOST=$(oc get route default-route -n openshift-image-registry --template='{{ .spec.host }}').
    3. Log in via Podman: $ podman login -u kubeadmin -p $(oc whoami -t) --tls-verify=false $HOST.
    4. Create an empty image stream: $ oc apply -f is.yaml.
    5. Get the image stream: oc get is .
    6. Get the local IMAGE ID: $ sudo podman image list.
    7. Send the image $ sudo podman push IMAGE_ID $HOST/NAMESPACE/IS_NAME --tls-verify=false.
    8. Start the deployment using the IS: $ oc new-app --image-stream=imagestream-name.

    Finally, there is another method, using the built-in SDK feature container support for the .NET SDK. Here is an example: 

    # install the build-image
    $ dotnet tool install -g dotnet-build-image
    # build image as below
    $ dotnet build-image -t example-app:latest -b ubi

    In terms of OpenShift 4, it is possible to use a BuildConfig as an argument the .NET image and the GitHub (and branch) for the build as follows:

    $ cat github-buildconfig.yaml
    kind: BuildConfig
    apiVersion: build.openshift.io/v1
    metadata:
      name: quarkus-test-build
      namespace: quarkus
    spec:
      nodeSelector: null
      output:
        to:
          kind: ImageStreamTag
          name: 'output-dotnet:latest'
      resources: {}
      successfulBuildsHistoryLimit: 5
      failedBuildsHistoryLimit: 5
      strategy:
        type: Source
        sourceStrategy:
          from:
            kind: ImageStreamTag
            namespace: openshift
            name: 'dotnet-60:6.0-51.20240627154839'
      postCommit: {}
      source:
        type: Git
        git:
          uri: 'https://github.com/redhat-developer/s2i-dotnetcore.git'
          ref: main
        contextDir: 6.0/build/test/asp-net-hello-world
      runPolicy: Serial
    ...
    ...
    $ cat is.yaml 
    apiVersion: image.openshift.io/v1
    kind: ImageStream
    metadata:
      annotations:
        openshift.io/generated-by: OpenShiftNewApp  
      generation: 1
      labels:
        app: dotnet
      name: output-dotnet
      namespace: dotnet
    spec:
      lookupPolicy:
        local: false

    Then apply the BuildConfig and ImageStream YAMLs so the image can be built and outputted for an ImageStream:

    $ oc apply -f is.yaml
    imagestream.image.openshift.io/output-dotnet created
    ...
    ...
    $ oc apply -f github-buildconfig.yaml
    buildconfig.build.openshift.io/dotnet-build created
    ...
    ...
    $ oc get bc
    oc NAME           TYPE     FROM       LATEST
    dotnet-build   Source   Git@main   1
    $ oc get build
    NAME             TYPE     FROM          STATUS                       STARTED              DURATION
    dotnet-build-2   Source   Git@a0c7ee1   Complete                     About a minute ago   38s
    $ oc get pod
    NAME                   READY   STATUS       RESTARTS   AGE
    dotnet-build-1-build   0/1     Completed    0          93s

    Issues and methods

    From the previous deployment, in case of memory issues, see the following steps. Note, this will be an explanation of the main solution .NET Core image troubleshooting.

    Given a scenario where there is a memory issue, collect the data and for them to be analyzed. Let's break down two steps in the analysis as follows:

    • First, the collection of the data inside the container.
    • Second, the analysis of this data.

    Data collection

    For the data collection part, one can use the createdump tool using the .NET application process ID (PID) as the argument. For .NET images built using the OpenShift s2i flow, the PID is 1 (as used in the previous example). If the .NET application does not run as PID 1, you can find it using tools like ps and pidof:

    $ oc exec -ti $POD /bin/sh
    sh-4.4$ dotnet --list-runtimes
    Microsoft.AspNetCore.App 6.0.12
    [/usr/lib64/dotnet/shared/Microsoft.AspNetCore.App]
    Microsoft.NETCore.App 6.0.12 
    [/usr/lib64/dotnet/shared/Microsoft.NETCore.App]
    sh-4.4$ /usr/lib64/dotnet/shared/Microsoft.NETCore.App/6.0.12/createdump
    -f /tmp/dump --full 1
    [createdump] Gathering state for process 1 dotnet
    [createdump] Writing full dump to file /tmp/dump
    [createdump] Written 871575552 bytes (212787 pages) to core file
    [createdump] Target process is alive
    [createdump] Dump successfully written
    sh-4.4$ exit
    exit
    $ oc cp $POD:/tmp/dump /tmp/dump

    Data analysis

    With the core dump in hand, opening a debug container, you can analyze the core dump file using the dotnet-dump global tool.

    Install the global tool:

    $ dotnet tool install -g dotnet-dump

    Add the core dump and load it on the dotnet-dump diagnostic tool:

    $ dotnet dump analyze /tmp/dump
    Loading core dump: /tmp/dump ...
        Ready to process analysis commands. Type 'help' to list available commands or 'help [command]' to get detailed help on a command.
        Type 'quit' or 'exit' to exit the session.
        >

    To expand the original article to include analysis examples:

    1. Get the image:
    $ podman pull registry.access.redhat.com/ubi8/dotnet-60:6.0-39

        2. Create a dotnet container with the dump—passing it as an argument:

    $ podman run -u 0 --entrypoint /bin/sh -ti -v /path_host/dump.dmp:/tmp/dump.dmp:Z registry.access.redhat.com/ubi8/dotnet-60:6.0-39 
    1. Install dotnet tools: $ dotnet tool install -g dotnet-dump
    2. Load the dump: $ dotnet-dump analyze /tmp/dump.dmp
    3. Select the command (e.g., print stack):
    > clrstack                                                                                                           
    OS Thread Id: 0x12 (0)
            Child SP               IP Call Site
    00007FFF710C1670 00007f68c70de45c [HelperMethodFrame_1OBJ: 00007fff710c1670] System.Threading.Monitor.ObjWait(Int32, System.Object)
    00007FFF710C17A0 00007F68523A6BAE System.Threading.Monitor.Wait(System.Object, Int32)
    00007FFF710C17F0 00007F68523A588B System.Threading.ManualResetEventSlim.Wait(Int32, System.Threading.CancellationToken)
    1. For native investigations, lldb can be useful: $ dnf install lldb; $ lldb -c ./path/to/file+ bt:
    sh-4.4# lldb -c ./dump.dmp 
    (lldb) target create --core "./dump.dmp"
    Core file '/tmp/dump.dmp' (x86_64) was loaded.
    (lldb) bt
    * thread #1, name = 'dotnet', stop reason = signal SIGSTOP
      * frame #0: 0x00007f68c70de45c libpthread.so.0`pthread_cond_wait@@GLIBC_2.3.2 + 508
        frame #1: 0x00007f68c58feaa3 libcoreclr.so`CorUnix::CPalSynchronizationManager::ThreadNativeWait(CorUnix::_ThreadNativeWaitData*, unsigned int, CorUnix::ThreadWakeupReason*, unsigned int*) + 355    

    As Omair Majid explained a few times for me on our troubleshooting sessions:

    The dotnet dump is essentially a dump of the .NET memory, which means it has all the internal data structures placed as they are in memory in a running program. The DAC component knows how to map the raw memory into the CoreCLR internal data structures. That allows the dotnet dump analyze command to understand the internal state of the runtime.

    For the microsoft-built runtimes, the dotnet dump can automatically find/download the matching dac. Red Hat's runtime has no such option and you need to manually install the matching .NET runtime for the dotnet dump tool to find the appropriate DAC.

    As I previously listed, you can find information regarding the commands in the documentation at Microsoft's dotnet-dump#dotnet-dump-analyze. Note that for .NET to debug things natively, it needs matching application and native debug symbols. Microsoft publishes their DAC and debug symbols for every release they build to their symbol server. Unfortunately, there's no way for Red Hat to do that. Also, you can use dotnet-dump on RHEL, and once you've installed the matching .NET runtime and the native (unmanaged) debuginfo, you will be able to debug things on RHEL.

    Final thoughts

    In summary, .NET in OpenShift allows for an easy deployment of .NET applications in OpenShift Container Platform. The steps showed a straightforward approach for memory analysis inside a container. This article provided example analyses and steps to collect the data. The process to collect the data is streamlined via Microsoft's tool dotnet dump, including the analyze option. 

    Although Red Hat can help generate and collect data in the .NET container, the memory usage won't be covered by the support investigation given the memory is either from the .NET platform or from the application itself; therefore, very unlikely a container issue.

    To learn more about .NET, refer to the Microsoft's  Learn platform. In the matter of C#, Tom Deseyn has done a great series about it in the C#11 series, Some more C# 11.

    Special thanks to Omair and Tom Deseyn for their collaboration throughout the years on issues with .NET. For any other specific inquiries, please open a case with Red Hat support. Our global team of experts can help you with any issues.

    Related Posts

    • Containerize .NET for Red Hat OpenShift: Linux containers and .NET Core

    • Three ways to containerize .NET applications on Red Hat OpenShift

    • Monitoring .NET Core applications on Kubernetes

    • Reduce application image build times with .NET Core incremental builds

    • Interacting with native libraries in .NET Core 3.0

    Recent Posts

    • Every layer counts: Defense in depth for AI agents with Red Hat AI

    • Fun in the RUN instruction: Why container builds with distroless images can surprise you

    • Trusted software factory: Building trust in the agentic AI era

    • Build a zero trust AI pipeline with OpenShift and RHEL CVMs

    • Red Hat Hardened Images: Top 5 benefits for software developers

    What’s up next?

    OpenShift for .NET Developers is a practical guide that explains techniques for building, testing, and debugging .NET applications within the Red Hat OpenShift environment.

    Get the e-book
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer tools
    • Interactive tutorials
    • API catalog

    Quicklinks

    • Learning resources
    • E-books
    • Cheat sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site status dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2026 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Chat Support

    Please log in with your Red Hat account to access chat support.