
Last Update: November 12, 2025
BY
eric
Keywords
Microsoft's transformation from a proprietary software giant to an open-source advocate has been remarkable. The release of .NET Core for Linux marked a pivotal moment in cross-platform development. However, despite this progress, developers working with .NET on Linux have encountered persistent challenges that can significantly impact productivity.
The Promise and Reality of .NET on Linux
When Microsoft announced .NET Core's availability on Linux, it opened doors for developers who had been yearning to use their favorite .NET technologies outside the Windows ecosystem. The framework itself is remarkably solid – applications run smoothly, performance is excellent, and the development experience is largely seamless.
But there's a catch that many developers have discovered the hard way: the build process.
The Persistent Build Hang Problem
The dotnet build command on Linux has a notorious reputation for hanging unexpectedly. This isn't a minor inconvenience – it's a productivity killer that affects development workflows across teams and projects.
Characteristics of the Problem
The hanging behavior exhibits several frustrating patterns:
- Unpredictable occurrence: It works perfectly on one machine but fails consistently on another with seemingly identical configurations
- Intermittent failures: The build might succeed several times, then suddenly hang without any code changes
- Repository dependency: Sometimes checking out a fresh clone of the same repository resolves the issue temporarily
- No clear error messages: The process simply stops responding, providing no actionable feedback
The Library Dependency Nightmare
The build process is only half the battle. A common scenario unfolds like this: you successfully build your .NET application on your development machine (e.g., running the latest Ubuntu), and everything looks great. You then deploy the compiled artifacts to a production server, which might be running an older but more stable distribution like Debian or CentOS.
When you try to run the application on the target machine, it crashes with errors like these:
Nov 12 10:47:53 workstation run.sh[290219]: ./[YOUR_APP]: /lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.32' not found (required by ./[YOUR_APP])
Nov 12 10:47:53 workstation run.sh[290219]: ./[YOUR_APP]: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found (required by ./[YOUR_APP])
These errors indicate version mismatches between the system's installed libraries and what the .NET runtime expects – a classic Linux dependency hell scenario.
Why These Issues Persist
A simple Google search for "dotnet build linux hung" reveals the scope of this problem. Results span back at least four years, with countless developers reporting similar experiences across different Linux distributions, .NET versions, and hardware configurations.
The persistence of these issues a couple of underlying factors. The .NET build system performs numerous operations under the hood – package restoration, compilation, linking, and asset generation. Any step in this pipeline can encounter environment-specific issues that cause hanging. Also Linux systems handle process scheduling and resource allocation differently than Windows. The .NET build process might encounter unexpected contention or deadlock scenarios specific to Linux environments. The exact root cause remains elusive. Despite numerous bug reports and community discussions, a definitive, universal solution from the Microsoft .NET team has not materialized. The problem's intermittent and environment-specific nature makes it incredibly difficult to diagnose. Rather than getting stuck trying to solve a mystery that has stumped even the core development team, this guide focuses on a pragmatic and reliable workaround that bypasses the problem entirely.
Docker as the Solution
While the root causes remain complex, Docker provides a practical workaround that many development teams have adopted successfully.
Why Docker Works
Docker containers offer several advantages for .NET builds on Linux:
Consistent Environment: Every build runs in an identical, controlled environment regardless of the host system's configuration.
Isolated Dependencies: Container images include all necessary runtime dependencies at known versions, eliminating library mismatch issues.
Reproducible Builds: The same container image produces identical results across different machines and CI/CD environments.
Setting Up Dockerized .NET Builds
Here's a practical implementation for containerizing your .NET builds:
Basic Dockerfile
# Simple single-stage Dockerfile for building [YOUR_APP] on Ubuntu 22.04
FROM ubuntu:22.04
# Prevent interactive prompts
ENV DEBIAN_FRONTEND=noninteractive
# Install .NET SDK 8.0 for Ubuntu 22.04
RUN apt-get update && apt-get install -y wget ca-certificates \
&& wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \
&& dpkg -i packages-microsoft-prod.deb \
&& rm packages-microsoft-prod.deb \
&& apt-get update \
&& apt-get install -y dotnet-sdk-8.0 \
&& rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /app
# Configure environment
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 \
DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 \
MSBUILDDISABLENODEREUSE=1
# Copy all project files
COPY . .
# Fix NuGet.Config
RUN printf '%s\n' \
'<?xml version="1.0" encoding="utf-8"?>' \
'<configuration>' \
' <packageSources>' \
' <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />' \
' </packageSources>' \
'</configuration>' > NuGet.Config
# Remove global.json to allow any .NET 8 SDK
RUN rm -f global.json
# Restore, build, and publish with runtime identifier
RUN echo "=== RESTORE (with RID) ===" \
&& dotnet restore [YOUR_APP].csproj -r linux-x64 2>&1 | tee restore.log \
&& echo "=== BUILD ===" \
&& dotnet build [YOUR_APP].csproj -c Release --no-restore -r linux-x64 2>&1 | tee build.log \
&& echo "=== PUBLISH ===" \
&& dotnet publish [YOUR_APP].csproj -c Release --no-restore --no-build \
-o /app/publish \
-r linux-x64 \
--self-contained false \
2>&1 | tee publish.log \
&& echo "=== BUILD COMPLETE ===" \
&& ls -lh /app/publish/
# Set entrypoint
WORKDIR /app/publish
CMD ["/bin/bash"]
Remember to replace [YOUR_APP] in the above Dockerfile to your actual project name.
Build Script
Create a shell script to streamline the Docker build process:
#!/bin/bash
#
# Simple Docker build script with better error handling
#
set -e
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$PROJECT_DIR"
echo "=========================================="
echo "Building [YOUR_APP] in Docker "
echo "Target: Ubuntu 22.04"
echo "=========================================="
echo
# Configuration
IMAGE_NAME="[YOUR_APP]-docker"
CONTAINER_NAME="[YOUR_APP]-extract"
OUTPUT_DIR="./bin/Release/net8.0/publish"
# Clean up
echo "Cleaning up previous containers..."
docker rm -f "$CONTAINER_NAME" 2>/dev/null || true
# Build the Docker image
echo
echo "Building Docker image..."
if ! docker build -f Dockerfile -t "$IMAGE_NAME:latest" . 2>&1 | tee docker-build.log; then
echo
echo "=========================================="
echo "BUILD FAILED!"
echo "Check docker-build.log for details"
echo "=========================================="
exit 1
fi
echo
echo "Creating container to extract build..."
docker create --name "$CONTAINER_NAME" "$IMAGE_NAME:latest"
# Create output directory
mkdir -p "$OUTPUT_DIR"
# Copy published files
echo "Extracting build artifacts..."
if docker cp "$CONTAINER_NAME:/app/publish/." "$OUTPUT_DIR/"; then
echo "Build artifacts extracted successfully"
else
echo "Warning: Could not extract all artifacts, checking what\'s available..."
docker run --rm "$IMAGE_NAME:latest" ls -la /app/publish/ || true
fi
# Clean up container
docker rm "$CONTAINER_NAME"
echo
echo "=========================================="
echo "Build process completed!"
echo "=========================================="
echo
if [ -d "$OUTPUT_DIR" ] && [ "$(ls -A $OUTPUT_DIR)" ]; then
echo "Output directory: $OUTPUT_DIR"
echo "Files:"
ls -lh "$OUTPUT_DIR" | head -20
echo
echo "Binary file check:"
file "$OUTPUT_DIR/[YOUR_APP]" 2>/dev/null || echo "[YOUR_APP] binary not found"
echo
echo "To test on target workstation:"
echo " scp -r $OUTPUT_DIR/* workstation:/apps/[YOUR_APP]/current/"
else
echo "ERROR: No files in output directory!"
echo "Check docker-build.log for errors"
exit 1
fi
Again, remember to replace [YOUR_APP] in the above Dockerfile to your actual app name.
Looking Forward
The .NET build hanging issue on Linux remains an active concern in the .NET community. Microsoft continues working on improvements, but the complexity of supporting diverse Linux environments means progress is incremental.
Docker provides a pragmatic solution that works today. While it adds complexity to your development workflow, the trade-off between operational overhead and build reliability often favors containerization.
As the .NET ecosystem matures on Linux, we can expect better native support and fewer environment-specific issues. Until then, Docker remains a reliable path forward for teams serious about .NET development on Linux.
Conclusion
Microsoft's embrace of open source and cross-platform development has created exciting opportunities for .NET developers. However, the reality of cross-platform development includes challenges that require practical solutions.
The persistent build hanging issues on Linux demonstrate that even mature frameworks can struggle with platform-specific complexities. Docker offers a proven workaround that many teams have adopted successfully, trading some additional complexity for significantly improved reliability.
Whether this Docker-based approach will remain necessary long-term remains to be seen. For now, it provides a stable foundation for .NET development on Linux, allowing teams to focus on building great applications rather than fighting build system issues.
If you're experiencing similar challenges with .NET builds on Linux, consider implementing a Docker-based workflow. While it may seem like overkill initially, the improved consistency and reliability often justify the additional setup complexity.
Do you have similar experience? Share your comments below.
Previous Article
Nov 13, 2025
This Chrome Extension for CommSec Was Coded Entirely by AI
How AI tools created a Chrome extension that solves CommSec session timeouts with zero human coding.
Next Article
Nov 06, 2025
Fix the 'Could Harm Your Computer' File Preview Error
Resolve Windows File Explorer preview errors for PDF files from network shares and internet downloads.





Comments (0)
Leave a Comment