Add Docker To Existing Net Core Project

Add Docker To Existing Net Core Project

Reading time1 min
#Docker#DevOps#Cloud#DotNet#Containerization#Microservices

Seamlessly Integrate Docker into Your Existing .NET Core Project Without Disruption

Most developers start new projects with Docker, but retrofitting Docker into a mature .NET Core app feels like a minefield. Suddenly, that neat, functioning codebase is bogged down with questions around environment parity, build processes, and deployment configurations. This guide cuts through the noise to show you how to add Docker to your existing .NET Core project cleanly, preserving your project integrity while unlocking container benefits—like consistent environments, faster deployments, and easier scalability.


Why Containerize an Existing .NET Core App?

Before diving into the how, let's touch quickly on the why. Containerizing an existing .NET Core app can:

  • Ensure consistency across development, testing, and production — no more "it works on my machine".
  • Accelerate deployment cycles by packaging all dependencies together.
  • Simplify horizontal scalability with container orchestration platforms like Kubernetes or Docker Swarm.
  • Improve resource utilization by running isolated containers on shared infrastructure.

Even if your app is stable now, adopting Docker adds agility and reliability that scales as your project and team grow.


Step 1: Prepare Your Project

Dockerizing an existing project requires some housekeeping first.

  • Make sure your project builds cleanly with dotnet build.
  • Confirm you can run it locally via dotnet run or from your IDE.
  • Verify that any environment variables or configuration files can be overridden at runtime, as these will be managed differently inside containers.

Step 2: Create a Dockerfile

At the root of your .NET Core project folder, add a file named Dockerfile. Here’s a straightforward example for an ASP.NET Core web app:

# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY *.csproj .
RUN dotnet restore

# Copy everything else and build
COPY . .
RUN dotnet publish -c Release -o out

# Stage 2: Runtime
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS runtime
WORKDIR /app
COPY --from=build /app/out .

# Expose port (change if needed)
EXPOSE 80

ENTRYPOINT ["dotnet", "YourProjectName.dll"]

Replace YourProjectName.dll with the actual DLL output of your project (usually matches the project name).

This two-stage build does the following:

  • Uses the SDK image to restore dependencies and compile.
  • Publishes the output into /out.
  • Creates a smaller runtime-only image with just what’s needed.

By splitting this way, final images are compact and production-ready.


Step 3: Add .dockerignore File

Add a .dockerignore file next to your Dockerfile to avoid copying unnecessary files (like local config, logs, or binaries) which bloat the context:

bin/
obj/
*.user
*.vs/
.dockerignore
.git/
.vscode/

This speeds up builds and ensures no secrets slip in accidentally.


Step 4: Build Your Docker Image Locally

Run this from the root where your Dockerfile sits:

docker build -t myapp:latest .

This command builds an image tagged myapp:latest.

You should see output tracing:

  • Base image downloads (if not cached).
  • Restore of NuGet packages.
  • Compilation.
  • Final stage container assembly.

Step 5: Run Your App in a Container

After building:

docker run -d -p 8080:80 --name myrunningapp myapp:latest

Here:

  • -d runs detached.
  • -p 8080:80 maps port 80 in container to localhost 8080.
  • --name gives your container an easy name.

Visit http://localhost:8080 (or whichever port you mapped) to verify it runs exactly like before—but isolated inside its own container.


Step 6: Refine Configuration for Production Readiness

Once you have basic dockerization working, consider:

Environment Variables

Use Docker's support for environment variables instead of hardcoded settings or local config files. For example:

docker run -d -p 8080:80 -e "ConnectionStrings__DefaultConnection=Server=myserver;Database=mydb;..." myapp:latest

In your .NET Core project’s appsettings.json, use placeholders or enable environment overrides via ASP.NET Core’s configuration system (AddEnvironmentVariables()).

Volumes for Persistent Data

If your app writes files or logs locally inside the container folder system, remember these disappear when containers stop/destroy. Use volumes:

docker run -d -p 8080:80 -v /host/logs:/app/logs myapp:latest

This maps host machine logging folder to container's internal path for persisting outputs safely.


Optional Step 7: Use Docker Compose for Multi-Service Apps

If your .NET Core app depends on other services—SQL Server, Redis, etc.—use Docker Compose for simple orchestration without extra complexity right away.

Create a docker-compose.yml file like this one using official images alongside yours:

version: '3.8'

services:
  webapp:
    build: .
    ports:
      - "8080:80"
    environment:
      ConnectionStrings__DefaultConnection: Server=db;Database=MyDb;User=sa;Password=Your_password123;
    depends_on:
      - db
  
  db:
    image: mcr.microsoft.com/mssql/server:2022-latest
    environment:
      SA_PASSWORD: "Your_password123"
      ACCEPT_EULA: "Y"
    ports:
      - "1433"

Run all services together via:

docker-compose up --build

Wrap-Up & Best Practices

Adding Docker into an existing .NET Core project doesn’t have to disrupt workflow—it can actually make deployment and scaling easier down the line. To recap:

  • Start small with a straightforward multi-stage Dockerfile.
  • Use .dockerignore.
  • Test locally before moving toward orchestrated environments.
  • Integrate environment-based configuration early.
  • Iterate gradually as team specs evolve.

Once containerized, explore integrating CI/CD pipelines that automatically build/test/push images on commit — further unlocking velocity gains without sacrificing stability hours lost troubleshooting “works on dev but not prod” scenarios anymore.


Further Reading & Tools

Implementing these tips can help you retrofit Docker into legacy apps smoothly—and modernize your entire development lifecycle without rebuilding from scratch!


If you found this post helpful or want sample GitHub repos for reference projects retrofitted step-by-step with Docker in real time—drop a comment below! Happy docking! 🚢🐳