Docker & Containerization

16 questions found

What is a container health check (HEALTHCHECK instruction), and how does it differ from a Kubernetes liveness/readiness probe?

Advanced
A Dockerfile's HEALTHCHECK instruction defines a command Docker itself periodically runs inside the container to determine if it's healthy, useful for basic container orchestrators or Docker Swarm, marking the container status as 'unhealthy' in `docker ps` output if it fails repeatedly. Kubernetes largely supersedes this with its own liveness/readiness probes configured at the Pod spec level (HTTP, TCP, or exec-based checks) rather than relying on the Dockerfile's HEALTHCHECK, since Kubernetes needs its own control over probe behavior for its scheduling and self-healing decisions -- when deploying to Kubernetes, the Dockerfile HEALTHCHECK is typically redundant or omitted in favor of Kubernetes-native probes.
# Dockerfile HEALTHCHECK (used by plain Docker/Swarm, often redundant in Kubernetes)
HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:8080/health || exit 1

# Kubernetes equivalent, configured in the Pod spec instead:
livenessProbe:
  httpGet: { path: /health/live, port: 8080 }
  periodSeconds: 10
Real-world example A team removes the Dockerfile HEALTHCHECK instruction from their images once fully migrating to Kubernetes, since it provided no value there and Kubernetes's own liveness/readiness probes already handle health monitoring more appropriately for that orchestration layer.

Common follow-ups: Why can't Kubernetes just use the Dockerfile HEALTHCHECK directly?;What's the difference between liveness and readiness probes in terms of orchestrator behavior?

Health Checks & Readiness/Liveness Probes;.NET CLI SDK & Project Structure (csproj)

How does .dockerignore improve Docker build performance and image cleanliness for .NET projects?

Intermediate
A .dockerignore file excludes specified files and directories (like bin/, obj/, .git/, and local development artifacts) from being sent to the Docker build context, reducing the amount of data transferred to the Docker daemon (speeding up builds) and preventing stale local build artifacts from accidentally being copied into the image, which could otherwise cause confusing build issues or bloat the image with unnecessary files.
# .dockerignore
bin/
obj/
.git/
.vs/
*.user
**/node_modules

# Without this, COPY . . would include local bin/obj folders,
# potentially conflicting with the container's own build output
Real-world example A team's Docker build times drop noticeably after adding a proper .dockerignore excluding local bin/obj folders, which had previously been silently transferred into the build context on every single build despite being irrelevant to the containerized build process.

Common follow-ups: What happens specifically if local bin/obj artifacts leak into the image via COPY?;How does .dockerignore syntax compare to .gitignore syntax?

.NET CLI SDK & Project Structure (csproj);CI/CD Publishing & Deployment

How would you optimize a Docker image build for a solution with multiple .NET projects sharing common dependencies, to maximize layer cache reuse?

Advanced
Restructure the Dockerfile to copy all .csproj/.sln files first (preserving the directory structure needed for project references) and run a single `dotnet restore` against the solution before copying any actual source code, so the expensive restore step (resolving potentially dozens of shared NuGet dependencies across all projects) is cached and reused as long as none of the project files change, even if application source code changes frequently.
# Copy project files first, preserving directory structure for references
COPY *.sln .
COPY src/MyApi/*.csproj src/MyApi/
COPY src/MyLib/*.csproj src/MyLib/
RUN dotnet restore

# THEN copy all source code (invalidates cache more often, but restore stays cached)
COPY . .
RUN dotnet publish -c Release -o /app/publish
Real-world example A monorepo with 15 interdependent projects restructures its Dockerfile using this pattern, cutting typical CI build time significantly since the shared dependency restore step (previously re-run on every build) is now cached across builds that only touch application code.

Common follow-ups: How does this pattern scale as the number of projects grows very large?;What's the trade-off of this more complex Dockerfile versus simplicity?

.NET CLI SDK & Project Structure (csproj);CI/CD Publishing & Deployment

What is the difference between an image and a container in Docker terminology, applied to a .NET application?

Beginner
An image is an immutable, built artifact (the result of a `docker build`) containing the application, its dependencies, and everything needed to run it, analogous to a class definition. A container is a running (or stopped) instance of an image, analogous to an object instantiated from that class -- you can run multiple independent containers from the same single image simultaneously, each with its own isolated filesystem and process space.
docker build -t myapp:1.0 .          # builds an image
docker run -d --name instance1 myapp:1.0  # runs a container from that image
docker run -d --name instance2 myapp:1.0  # runs ANOTHER independent container from the SAME image
Real-world example A load-tested API runs five separate containers from the same built image behind a load balancer, scaling horizontally by simply starting more container instances rather than building anything new for each one.

Common follow-ups: What happens to data written inside a container when it stops or is removed?;How do you persist data across container restarts using volumes?

Docker & Containerization;CI/CD Publishing & Deployment

How do you configure a .NET application inside a container to listen on the correct port, and what does ASPNETCORE_URLS control?

Intermediate
The ASPNETCORE_URLS environment variable (or the newer ASPNETCORE_HTTP_PORTS) tells Kestrel which URL(s)/port(s) to bind to inside the container; this must be explicitly set (or match the Dockerfile's EXPOSE and the container run command's port mapping) since a container's internal networking is isolated from the host by default, requiring explicit port publishing to make the application reachable from outside the container.
# In the Dockerfile or docker run command
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080

# Running with port mapping: host port 5000 -> container port 8080
docker run -p 5000:8080 myapp:latest
Real-world example A team debugging why their containerized API was unreachable from the host discovers ASPNETCORE_URLS was left at its default (often localhost-only in some configurations), requiring an explicit override to bind to all interfaces (+) inside the container.

Common follow-ups: What's the difference between EXPOSE in a Dockerfile and the -p flag at runtime?;Why must a containerized app bind to 0.0.0.0 or + rather than localhost?

ASP.NET Core Middleware & Request Pipeline;.NET CLI SDK & Project Structure (csproj)

What are microservices, and what specific tools does the .NET ecosystem provide to build and run them?

Advanced
Microservices structure an application as a collection of small, independently deployable services, each owning a specific capability (payments, orders, auth), communicating over the network rather than in-process -- this improves scalability and fault isolation compared to a single monolith, at the cost of added networking, deployment, and observability complexity. .NET supports this architecture through ASP.NET Core for building lightweight service APIs, Docker for packaging each service consistently, Kubernetes for orchestration (scaling, service discovery, self-healing), gRPC for efficient inter-service communication, message brokers (RabbitMQ, Azure Service Bus, Kafka) for event-driven communication, and .NET Aspire for higher-level tooling around service discovery, configuration, and observability across the whole distributed system.
[ApiController]
[Route("api/products")]
public class ProductsController : ControllerBase {
    [HttpGet]
    public IEnumerable<string> Get() => new[] { "Product1", "Product2" };
}
// Each microservice like this is packaged into its own Docker image and
// deployed/scaled independently behind Kubernetes
Real-world example An e-commerce platform splits its monolithic order-processing system into separate orders, inventory, and payments microservices, each containerized with Docker and deployed to Kubernetes, communicating asynchronously via Azure Service Bus so a slow payments provider never blocks order intake.

Common follow-ups: What specific new failure modes (network partitions, partial failures) does a microservices architecture introduce that a monolith doesn't have?;How does .NET Aspire reduce the setup overhead traditionally associated with running microservices locally during development?

System Design;gRPC Services

Showing 11–16 of 16