Dockerize ASP.NET Core 8 App with SQL Server Using Docker Compose (2024)

Introduction

In this tutorial, we’ll walk through the process of Dockerizing an ASP.NET Core application and an SQL Server database using Docker Compose. By the end of this guide, you’ll have a clear understanding of how to containerize your ASP.NET Core application and its associated SQL Server database for easy deployment and scalability.

Brief about Docker Compose?

Docker Compose is a tool for defining and managing multi-container Docker applications. It allows you to define the services, networks, and volumes of your application in a single docker-compose.yml file, and then manage them with simple commands. This is particularly useful for applications that consist of multiple services that need to interact with each other, such as a web server, a database, and a cache.

Dockerize ASP.NET Core 8 App with SQL Server Using Docker Compose: A Step-by-Step Guide

Prerequisites:

Before we begin, ensure that you have the following prerequisites installed on your system:

  • Docker Desktop (or Docker Engine) – for running Docker containers.
  • ASP.NET Core 8.0 SDK – for building and running ASP.NET Core applications.
  • Visual Studio 2022 or newer
  • Basic knowledge of
  • Docker Commands
  • Basic knowledge of
  • ASP.NET Core Web API and Entity Framework Core.

Step 1: Set up your ASP.NET Core Web API Application

Start by creating a new ASP.NET Core Web API project or use an existing one or you can create using Visual Studio. For using Visual Studio make sure you enable the checkbox Enable Docker.

Dockerize ASP.NET Core 8 App with SQL Server Using Docker Compose (1)

Figure: Choose App Template

After creating the project Open your terminal or command prompt and navigate to your project directory. you‘ll get this project structure.

Dockerize ASP.NET Core 8 App with SQL Server Using Docker Compose (2)

Figure: Visualize project files in the console

Step 2: Create a Controller and Seed Data

Create a controller to expose endpoints for testing. Additionally, seed some initial data into your database.
Model Class: Create a model class for the Product entity.
public class Product

{ public int Id { get; set; } public required string Name { get; set; }}

Controller: Create a controller named ProductController to handle API requests.

[Route("api/[controller]")][ApiController]public class ProductController(ApplicationDbContext context) : ControllerBase{ private readonly ApplicationDbContext _context = context; [HttpGet] public ActionResult Greetings() =&gt; Ok("Hello, I'm alive!"); [HttpGet("{id}")] public async Task<actionresult>&gt; GetItem(int id) { _context.Database.EnsureCreated(); var item = await _context.Products.FindAsync(id); if (item == null) return NotFound(); return item; }}</actionresult>

Step 3: Install EF Core and add migration to the application

EF Core is an Object/Relational Mapping (O/RM) framework, an enhanced version of ADO.NET, which automates data storage and retrieval from the database. To Install EF Core in our app install the following 2 packages,

* Install EF Core DB Providers

Go to Tools > NuGet Package Manager > Manage NuGet Packages for Solution and search for Microsoft.EntityFrameworkCore.SqlServer. When it shows up, select it and install it to your app

Figure: Nuget package – Microsoft.EntityFrameworkCore.SqlServer

* Install EF Core Tools
Next, search for Microsoft.EntityFrameworkCore.Tools. Once you get the result, install it and add the migration

Now, Add some seed data into your DbContext to populate the database with initial records.

public class ApplicationDbContext(DbContextOptions<applicationdbcontext> options) : DbContext(options){ public DbSet<product> Products { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<product>().HasData( new Product { Id = 1, Name = "Product 1" }, new Product { Id = 2, Name = "Product 2" } ); }}</product></product></applicationdbcontext>

Step 4: Look into the docker file and get an explanation

If you go to your project directory you will see the docker file for the application that was generated by Visual Studio itself.

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS baseUSER appWORKDIR /appEXPOSE 8080FROM mcr.microsoft.com/dotnet/sdk:8.0 AS buildARG BUILD_CONFIGURATION=ReleaseWORKDIR /srcCOPY ["Product.API/Product.API.csproj", "Product.API/"]RUN dotnet restore "./Product.API/./Product.API.csproj"COPY . .WORKDIR "https://cdn.vivasoftltd.com/src/Product.API"RUN dotnet build "./Product.API.csproj" -c $BUILD_CONFIGURATION -o /app/buildFROM build AS publishARG BUILD_CONFIGURATION=ReleaseRUN dotnet publish "./Product.API.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=falseFROM base AS finalWORKDIR /appCOPY --from=publish /app/publish .ENTRYPOINT ["dotnet", "Product.API.dll"]

Here is the explanation of this Docker file:

Base Stage (base):

  • Base image: mcr.microsoft.com/dotnet/aspnet:8.0
  • Sets the user to the app and working directory to /app.
  • Exposes port 8080, indicating that the container will listen for incoming connections on this port.

Build Stage (build):

  • Base image: mcr.microsoft.com/dotnet/sdk:8.0
  • Defines an argument BUILD_CONFIGURATION with a default value of Release.
  • Sets the working directory to /src.
  • Copies the project file (Product.API.csproj) into the container’s /src/Product.API/ directory.
  • Runs dotnet restore to restore the dependencies specified in the project file.
  • Copies the entire application source code into the container.
  • Sets the working directory to /src/Product.API.
  • Runs dotnet build to build the application, specifying the build configuration (Release) and output directory (/app/build).

Publish Stage (publish):

  • Inherits from the build stage.
  • Defines an argument BUILD_CONFIGURATION with a default value of Release.
  • Runs dotnet publish to publish the application, specifying the build configuration (Release), output directory (/app/publish), and disabling the use of the app host (/p:UseAppHost=false).
  • This step prepares the application for deployment.

Final Stage (final):

  • Base image: base stage (mcr.microsoft.com/dotnet/aspnet:8.0).
  • Sets the working directory to /app.
  • Copies the published output from the publish stage into the container’s working directory.
  • Specifies the entry point for the container, which is the command to run when the container starts. In this case, it’s dotnet Product.API.dll, indicating that the application executable (Product.API.dll) will be run using the .NET runtime.

Now let’s write a docker file for our SQL server database.

# Use the official SQL Server imageFROM mcr.microsoft.com/mssql/server:latest AS sqlserverENV ACCEPT_EULA=Y ENV SA_PASSWORD=myPassword1!# Add optional environment variable for database nameENV MSSQL_DBNAME=product_db

Here is the explanation of this db.Docker file:

Base Image:

    • FROM mcr.microsoft.com/mssql/server:latest AS sqlserver: Specifies the base image to use for the SQL Server container. In this case, it uses the official Microsoft SQL Server image from the Microsoft Container Registry (mcr.microsoft.com/mssql/server), tagged as “latest”. The alias “sqlserver” is used for this stage.

Environment Variables:

    • ENV ACCEPT_EULA=Y: Sets the environment variable ACCEPT_EULA to “Y”, indicating acceptance of the End-User License Agreement (EULA) for the SQL Server image.
    • ENV SA_PASSWORD=myPassword1!: Sets the environment variable SA_PASSWORD to “myPassword1!”, which is the password for the sa (System Administrator) account. This is required by SQL Server to be able to start.
    • ENV MSSQL_DBNAME=product_db: (Optional) Sets the environment variable MSSQL_DBNAME to “product_db”, specifying the name of the default database to be created when the SQL Server container starts. This can be customized as needed.

These environment variables are essential for configuring the SQL Server container properly. ACCEPT_EULA acknowledges the license agreement, SA_PASSWORD sets the password for the sa account, and MSSQL_DBNAME allows you to specify the default database name.

Step 5: Create Docker Compose File

Next, create a docker-compose.yml file in your project directory using Visual Studio. This file will define the services required for running your ASP.NET Core application and SQL Server database.
Right-click the project file then goto add then ‘Container Orchestrator Support’

Figure: Add Container


Then Choose Docker Compose and Click OK.

Figure: Choose Docker Compose

Then Select Linux and click ok. Here we choose Linux as Linux is the preferred choice for container orchestration due to its native support, performance, compatibility, flexibility, and cost-effectiveness

Figure: Choose Targer OS

Then you’ll see the docker-compose.yml file in your solution folder

Figure: Solution of docker-compose

The default generated compose file will look like this

Now, let’s update the compose file as below

version: '3.4'name: product_servicesservices: product_api: container_name: product_api build: context: . dockerfile: Product.API/Dockerfile ports: - "5000:8080" depends_on: - docker_sqlserver docker_sqlserver: container_name: docker_sqlserver build: context: . dockerfile: Product.API/db.Dockerfile ports: - "1433:1433"

Here is the explanation of this Docker Compose file:

  • Version:
    • version: ‘3.4’: Specifies the version of the Docker Compose file format being used. In this case, it’s version 3.4.
  • Project Name:
    • name: product_services: Specifies the name of the Docker Compose project as “product_services”.
  • Services:
    • product_api:
      • container_name: product_api: Sets the name of the container for the product_api service to “product_api”.
      • build: Specifies how to build the Docker image for this service.
        • context: .: Specifies the build context as the current directory (where the Docker Compose file is located).
        • dockerfile: Product.API/Dockerfile: Specifies the Dockerfile to use for building the image. It’s expected to be located at Product.API/Dockerfile relative to the context directory.
      • ports: Maps ports between the host and container.
        • “5000:8080”: Maps port 8080 from the container to port 5000 on the host. This means that the service inside the container is expected to listen on port 8080, and external clients can access it through port 5000 on the host.
      • depends_on: Specifies the dependency of this service on another service.
        • – docker_sqlserver: Specifies that this service depends on the docker_sqlserver service, meaning that the product_api service will start only after the docker_sqlserver service is up and running.
    • docker_sqlserver:
      • container_name: docker_sqlserver: Sets the name of the container for the docker_sqlserver service to “docker_sqlserver”.
      • build: Specifies how to build the Docker image for this service.
        • context: .: Specifies the build context as the current directory (where the Docker Compose file is located).
        • dockerfile: Product.API/db.Dockerfile: Specifies the Dockerfile to use for building the image. It’s expected to be located at Product.API/db.Dockerfile relative to the context directory.
      • ports: Maps ports between the host and container.
        • “1433:1433”: Maps port 1433 from the container to port 1433 on the host. This is the default port used by SQL Server. External clients can access SQL Server through port 1433 on the host.

This Docker Compose file creates a development environment where an ASP.NET Core API (product_api) communicates with a SQL Server instance (docker_sqlserver) using Docker containers. It ensures that the SQL Server container starts before the API container to satisfy dependencies.

As our SQL server will run inside the docker container make sure you have updated connectionStrings from app.Settings.json, the server name will be your docker sqlserver container name and the database and password should be the same as that you provide in your db.DockerFile as environment variable.

"ConnectionStrings": { "DefaultConnection": "Server=docker_sqlserver, 1433; Database=product_db; User Id=sa; Password=myPassword1!; TrustServerCertificate=True;"}

Step 6: Build and Run Docker Containers

Before starting let’s check if any container is running in our docker by using the docker ps command. You can see in the image below that no container is running.

Figure: visualize running containers in console

Now, build and run your Docker containers using Docker Compose.
‘Docker-compose up –build’ This command will build the Docker images for your ASP.NET Core application and SQL Server database, create containers, and start them.
In the below image, our containers have started building.

Figure: visualize docker compose up

Finally, our build is complete, let’s check it by using the command ‘docker ps’

Figure: visualize docker ps

Yes, Our containers are running. If you open the docker desktop application there also you can see those containers running.

Figure: visualize docker containers in Docker desktop

Step 7: Test your Application:

Once the containers are up and running, you can test your ASP.NET Core Web API endpoints using Postman or any other API testing too, or even by the default Product.API.http that is generated by default from Visual Studio. Use the following endpoints:

  • GET http://localhost:5000/api/products – Retrieve an alive message
  • GET http://localhost:5000/api/products/{id} – Retrieve an item by its ID.

Let’s check our results from Product.API.http from Visual Studio.

Figure: Check results from Product.API.http (1)

Figure: Check results using curl (2)

Figure: Check results using curl (2)

Figure: Check results from Product.API.http (3)

Don’t get it because there isn’t any data by ID 5 in our database

Let’s check from the terminal using curl

Figure: Check results using curl (1)

Figure: Check results using curl (2)

Figure: Check results using curl (3)

Yes, Getting the expected result.

Conclusion

Congratulations! You’ve successfully Dockerized your ASP.NET Core application along with SQL Server using Docker Compose. By creating a controller for testing and seeding data into the database, you can easily verify the functionality of your application within Docker containers.

Containerization offers numerous benefits such as consistency, scalability, and portability, making it an ideal choice for modern application deployment.

At Vivasoft Limited, we are committed to helping developers streamline their development and deployment workflows with cutting-edge technologies like Docker and Docker Compose.

Feel free to experiment further with Docker and Docker Compose to optimize your development and deployment workflow. Here I am providing some reference links for studying more about this and also sharing my source code. if you need to check any code.

Source code: https://github.com/basharovi/Product.API

Reference :

Dockerize ASP.NET Core 8 App with SQL Server Using Docker Compose (2024)

References

Top Articles
Latest Posts
Recommended Articles
Article information

Author: Fr. Dewey Fisher

Last Updated:

Views: 6120

Rating: 4.1 / 5 (62 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Fr. Dewey Fisher

Birthday: 1993-03-26

Address: 917 Hyun Views, Rogahnmouth, KY 91013-8827

Phone: +5938540192553

Job: Administration Developer

Hobby: Embroidery, Horseback riding, Juggling, Urban exploration, Skiing, Cycling, Handball

Introduction: My name is Fr. Dewey Fisher, I am a powerful, open, faithful, combative, spotless, faithful, fair person who loves writing and wants to share my knowledge and understanding with you.