Visual Studio – Docker https://www.docker.com Wed, 15 Feb 2023 01:53:00 +0000 en-US hourly 1 https://wordpress.org/?v=6.2.2 https://www.docker.com/wp-content/uploads/2023/04/cropped-Docker-favicon-32x32.png Visual Studio – Docker https://www.docker.com 32 32 Getting Started with Visual Studio Code and IntelliJ IDEA Docker Plugins https://www.docker.com/blog/getting-started-with-visual-studio-code-and-intellij-idea-docker-plugins/ Wed, 15 Jun 2022 14:55:57 +0000 https://www.docker.com/?p=34025 Today’s developers swear by IDEs that best support their workflows. Jumping repeatedly between windows and apps is highly inconvenient, which makes these programs so valuable. By remaining within your IDE, it’s possible to get more done in less time.

Today, we’ll take a look at two leading IDEs — VS Code and IntelliJ IDEA — and how they can mesh with your favorite Docker tools. We’ll borrow a sample ASP.NET application and interact with it throughout this guide. We’ll show you why Docker integrations are so useful during this process.

The Case for Integration

When working with Docker images, you’ll often need to perform repetitive tasks like building, tagging, and pushing each image — after creating unique Dockerfiles and Compose files.

In a typical workflow, you’d create a Dockerfile and then build your image using the docker build CLI command. Then, you’d tag the image using the docker tag command and upload it to your remote registry with docker push. This process is required each time you update your application. Additionally, you’ll frequently need to inspect your running containers, volumes, and networks.

Before the Docker, Docker Explorer, and “Remote – Containers” plugins debuted, (to name a few), you’d have to switch between your IDE and Docker Desktop to perform tasks. Now, Docker Desktop IDE integration unlocks Desktop’s functionality without compromising productivity. The user experience is seamless.

Integrating your favorite IDE with Docker Desktop enables you to be more productive without leaving either app. These extensions let you create Dockerfiles and Compose files based on your entered source code — letting you view and manage containers directly from within your IDE.

Now, let’s explore how to install and leverage various Docker plugins within each of these IDEs.

Prerequisites

You’ll need to download and install the following before getting started:

 

Before beginning either part of the tutorial, you’ll first need to download and install Docker Desktop. This grabs all Docker dependencies and places them onto your machine — for both the CLI and GUI. After installing Desktop, launch it before proceeding.

Next, pull the Docker image from the ASP.NET Core app using the Docker CLI command:

docker pull mcr.microsoft.com/dotnet/samples:aspnetapp

 

However, our example is applicable to any image. You can find a simple image on Docker Hub and grab it using the appropriate docker pull command.

Integrations with VS Code

Depending on which version you’re running (since you might’ve installed it prior), VS Code’s welcome screen will automatically prompt you to install recommended Docker plugins. This is very convenient for quickly getting up and running:

 

VS Intro Screen

VS Code displays an overlay in the bottom right, asking to install Docker-related extensions.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

If you want to install everything at once, simply click the Install button. However, it’s likely that you’ll want to know what VS Code is adding to your workspace. Click the Show Recommendations button. This summons a list of Docker and Docker-adjacent extensions — while displaying Microsoft’s native “Remote – Containers” extension front and center:

 

Plugins Screen

 

 

 

 

 

 

 

 

 

 

 

 

 

 

You can click any of these items in the sidebar and install them using the green Install button. Selecting the dropdown arrow attached to this button lets you install a release version or pre-release version depending on your preferences. Additionally, each extension may also install its own dependencies that let it work properly. You can click the Dependencies tab, if applicable, to view these sidekick programs.

However, you may have to manually open the Extensions pane if this prompt doesn’t appear. From the column of icons in the sidebar, click the Extensions icon that resembles a window pane, search for “Docker” in the search bar.

 

Search Results

 

 

 

 

 

 

 

 

 

 

 

 

You’ll also see a wide variety of other Docker-related extensions, sorted by popularity and relevance. These are developed by community members and verified publishers.

Once your installation finishes, a “Getting Started with Docker” screen will greet you in the main window, letting you open a workspace Folder, run a container, and more:

 

Getting Started Options

 

 

 

 

 

 

 

 

 

 

 

The Docker whale icon will also appear in the left-hand pane. Clicking it shows a view similar to that shown below:

 

Expandable Sections

 

 

 

 

 

 

 

 

 

 

 

Each section expands to reveal more information. You can then check your running containers and images, stop or start them, connect to registries, plus inspect networks, volumes, and contexts.

Remember that ASP.NET image we pulled earlier? You can now expand the Images group and spin up a container using the ASP.NET Core image. Locate mcr.microsoft.com/dotnet/samples in the list, right click the aspnetapp tag, and choose “Run”:

 

image6 1

 

 

 

 

 

 

 

 

 

 

You’ll then see your running container under the Containers group:

 

image14

 

 

 

 

 

 

 

 

 

 

This method lets you easily preview container files right within VS Code.

Expand the Files group under the running container and select any file from the list. Our example below previews the site.css file from the app/wwwroot/css directory:

 

image12

 

 

 

 

 

 

 

 

 

 

 

Finally, you may need to tag your local image before pushing it to the remote registry. You can do this by opening the Registries group and clicking “Connect Registry.”

VSCode will display a wizard that lets you choose your registry service — like Azure, Docker Hub, the Docker Registry, or GitLab. Let’s use Docker Hub by selecting it from the options list:

 

image19

 

 

 

 

 

Now, Visual Studio will prompt you to enter credentials. Enter these to sign in. Once you’ve successfully logged in, your registry will appear within the group:

 

image16

 

 

 

 

 

 

After connecting to Hub, you can tag local images using your remote repository name. For example:

YOUR_REPOSITORY_NAME/samples:aspnetapp

 

To do this, return to the Images group and right-click on the aspnetapp Docker image. Then, select the “Tag” option from the context menu. VS will display the wizard, where you can enter your desired tag.

Finally, right-click again on aspnetapp and select “Push” from the context menu:

 

image4 1

 

 

 

 

 

 

 

 

 

 

This method is much faster than manually entering your code into the terminal.

However, this showcases just some of what you can achieve with the Docker extension for VS Code. For example, you can automatically generate Dockerfiles from within VS Code.

To create these, open the Command Palette (View > Command Palette…), and type “Docker” to view all available commands:

 

Commands List

 

 

 

 

 

 

 

 

Next, click “Add Docker Files to Workspace…” You can now create your Dockerfiles from within VS Code.

Additionally, note the variety of Docker functions available from the Command Palette. The Docker extension integrates seamlessly with your development processes.

IntelliJ IDEA

In the IntelliJ IDEA Ultimate Edition, the Docker plugin is enabled by default. However, if you’re using the Community Edition, you’ll need to install the plugin manually.

You can either do this when the IDE starts (as shown below), or by clicking the Preferences window in the Plugins section.

 

image5 1

 

 

 

 

 

 

 

 

 

 

 

 

 

Once you’ve installed the Docker plugin, you’ll need to connect it to Docker Desktop. Follow these steps:

  1. Navigate to IntelliJ IDEA > Preferences.
  2. Expand the Build, Execution, Deployment group. Click Docker, and then click the small  “+” icon to the right.
  3. Choose the correct Docker daemon for your platform (for example, Docker for Mac).

 

The installation may take a few minutes. Once it’s complete, you’ll see the “Connection successful” message toward the middle-bottom of the Preferences pane:

 

image2 1

 

 

 

 

 

 

 

 

 

 

 

 

 

Next, click “Apply” and then expand the Docker group from the left sidebar.

Select “Docker Registry” and add your preferred registry from there. Like our VS Code example, this demo also uses Docker Hub.

IntelliJ will prompt you to enter your credentials. You should again see the “Connection successful” message under the Test connection pane if you’re successful:

 

image21

 

 

 

 

 

 

 

 

 

Now, click OK. Your Docker daemon and the Docker Registry connections will appear in the bottom portion of your IDE, in the Services pane:

 

image10

 

 

 

 

 

 

This should closely resemble what happens within VS Code. Now, you can spin up another container!

To do this, click to expand the Images group. Locate your container image and select it to open the menu. Click the “Create Container” button from there.

 

image1 1

 

 

 

 

 

This launches the “Create Docker Configuration” window, where you can configure port binding, entrypoints, command variables, and more.

You can otherwise interact with these options via the “Modify options” drop-down list — written in blue near the upper-right corner of the window:

 

image3 1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

After configuring your options, click “Run” to start the container. Now, the running container (test-container) will appear in the Services pane:

 

image8

 

 

 

 

 

 

You can also inspect the running container just like you would in VS Code.

First, navigate back to the Dashboard tab. You’ll see additional buttons that let you quickly “Restart” or “Stop” the container:

 

image13

 

 

 

 

 

Additionally, you can access the container command prompt by clicking “Terminal.” You’ll then use this CLI to inspect your container files.

 

image9

 

 

 

 

 

Finally, you can now easily tag and push the image. Here’s how:

  1. Expand the Images group, and click on your image. You’ll see the Tags list in the right-hand panel.
  2. Click on “Add…” to create a new tag. This prompts the Tag image window to appear. Use this window to provide your repository name.
  3. Click “Tag” to view your new tag in the list.

 

image15

 

 

 

 

 

Click on your tag. Then use the “Push Image” button to send your image to the remote registry.

Wrapping Up

By following this tutorial, you’ve learned how easy it is to perform common, crucial Docker tasks within your IDE. The process of managing containers and images is much smoother. Accordingly, you no longer need to juggle multiple windows or programs while getting things done. Docker Desktop’s functionality is baked seamlessly into VS Code and IntelliJ IDEA.

To enjoy streamlined workflows yourself, remember to download Docker Desktop and add Docker plugins and extensions to your favorite IDE.

Want to harness these Docker integrations? Read VS Code’s docs to learn how to use a Docker container as a fully-featured dev environment, or customize the official VS Code Docker extension. You can learn more about how Docker and IntelliJ team up here.

]]>
Building a Multi-Container .NET App Using Docker Desktop https://www.docker.com/blog/building-multi-container-net-app-using-docker-desktop/ Wed, 13 Apr 2022 02:24:57 +0000 https://www.docker.com/?p=33086 whalepurpleguy

.NET is a free, open-source development platform for building numerous apps, such as web apps, web APIs, serverless functions in the cloud, mobile apps and much more. .NET is a general purpose development platform maintained by Microsoft and the .NET community on GitHub. It is cross-platform, supporting Windows, macOS and Linux, and can be used in device, cloud, and embedded/IoT scenarios.

Docker is quite popular among the .NET community. .NET Core can easily run in a Docker container. .NET has several capabilities that make development easier, including automatic memory management, (runtime) generic types, reflection, asynchrony, concurrency, and native interop. Millions of developers take advantage of these capabilities to efficiently build high-quality applications.

Building the Application

In this tutorial, you will see how to containerize a .NET application using Docker Compose. The application used in this blog is a Webapp communicating with a Postgresql database. When the page is loaded, it will query the Student table for the record with ID and display the name of student on the page.

What will you need?

Getting Started

Visit https://www.docker.com/get-started/ to download Docker Desktop for Mac and install it in your system.

getting started with docker

Once the installation gets completed, click “About Docker Desktop” to verify the version of Docker running on your system.

about docker desktop pull down menu

If you follow the above steps, you will always find the latest version of Docker desktop installed on your system.

Docker Desktop Version 4.7 welcome

1. In your terminal, type the following command

dotnet new webApp -o myWebApp --no-https

The `dotnet new` command creates a .NET project or other artifacts based on a template.

You should see the output in terminal

The template ASP.NET Core Web App was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/aspnetcore/6.0-third-party-notices for details.

This will bootstrap a new web application from a template shipped with dotnet sdk. The -o parameter creates a directory named myWebApp where your app is stored.

2. Navigate to the application directory

cd myWebApp

you will have a list of files –

tree -L 2
.
├── Pages
│ ├── Error.cshtml
│ ├── Error.cshtml.cs
│ ├── Index.cshtml
│ ├── Index.cshtml.cs
│ ├── Privacy.cshtml
│ ├── Privacy.cshtml.cs
│ ├── Shared
│ ├── _ViewImports.cshtml
│ └── _ViewStart.cshtml
├── Program.cs
├── Properties
│ └── launchSettings.json
├── appsettings.Development.json
├── appsettings.json
├── myWebApp.csproj
├── obj
│ ├── myWebApp.csproj.nuget.dgspec.json
│ ├── myWebApp.csproj.nuget.g.props
│ ├── myWebApp.csproj.nuget.g.targets
│ ├── project.assets.json
│ └── project.nuget.cache
└── wwwroot
├── css
├── favicon.ico
├── js
└── lib

8 directories, 19 files

3. In your terminal, type the following command to run your application

The dotnet run command provides a convenient option to run your application from the source code.

dotnet run –urls http://localhost:5000

The application will start to listen on port 5000 for requests

# dotnet run
Building...
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when the container is destroyed.
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Cannot assign requested address'.
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /src

4. Test the application

Run the curl command to test the connection of the web application.

# curl http://localhost:5000

welcome 1 mywebapp

5. Put the application in the container

In order to run the same application in a Docker container, let us create a Dockerfile with the following content:

FROM mcr.microsoft.com/dotnet/sdk as build
COPY . ./src
WORKDIR /src
RUN dotnet build -o /app
RUN dotnet publish -o /publish

FROM mcr.microsoft.com/dotnet/aspnet as base
COPY --from=build  /publish /app
WORKDIR /app
EXPOSE 80
CMD ["./myWebApp"]

This is a Multistage Dockerfile. The build stage uses SDK images to build the application and create final artifacts in the publish folder. Then in the final stage copy artifacts from the build stage to the app folder, expose port 80 to incoming requests and specify the command to run the application myWebApp.

Now that we have defined everything we need to run in our Dockerfile, we can now build an image using this file. In order to do that, we’ll need to run the following command:

$ docker build -t mywebapp .

We can now verify that our image exists on our machine by using docker images command:

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mywebapp latest 6acc7ebf3a1d 25 seconds ago 210MB

In order to run this newly created image, we can use the docker run command and specify the ports that we want to map to and the image we wish to run.

$ docker run --rm - p 5000:80 mywebapp

  • - p 5000:80– This exposes our application which is running on port 80 within our container on http://localhost:5000 on our local machine.
  • --rm – This flag will clean the container after it runs
  • mywebapp – This is the name of the image that we want to run in a container.

Now we start the browser and put http://localhost:5000 to address bar

Welcome MyWebApp

Update application

The myWebApp and Postgresql will be running in two separate containers, and thus making this a multi-container application.

1.  Add package to allow app talk to database

Change directory to myWebapp and run the following command:
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL

2. Create student model

  • Create a Models folder in the project folder
  • Create Models/Student.cs with the following code:
using System;
using System.Collections.Generic;
namespace myWebApp.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
}
}

3. Create the `SchoolContext` with the following code:

using Microsoft.EntityFrameworkCore;
namespace myWebApp.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options) { }
public DbSet<Models.Student>? Students { get; set; }
}
}

4. Register SchoolContext to DI in Startup.cs

// You will need to add these using statements as well
using Microsoft.EntityFrameworkCore;
using myWebApp.Models;
using myWebApp.Data;
var builder = WebApplication.CreateBuilder(args);
// Add the SchoolContext here, before calling AddRazorPages()
builder.Services.AddDbContext<SchoolContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("SchoolContext")));
// Add services to the container.
builder.Services.AddRazorPages();

5. Adding database connection string to `appsettings.json`

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"SchoolContext":
"Host=db;Database=my_db;Username=postgres;Password=example"
}
}

6. Bootstrap the table if it does not exist in Program.cs

using Microsoft.EntityFrameworkCore;
using myWebApp.Data;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContext<SchoolContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("SchoolContext")));
var app = builder.Build();

using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
// add 10 seconds delay to ensure the db server is up to accept connections
// this won't be needed in real world application
System.Threading.Thread.Sleep(10000);
var context = services.GetRequiredService<SchoolContext>();
var created = context.Database.EnsureCreated();

}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the DB.");
}
}

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

 

Update the UI

Add the following to `Pages/Index.cshtml`

<div class="row mb-auto">
<p>Student Name is @Model.StudentName</p>
</div>

and update `Pages/Index.cshtml.cs` as shown below:

public class IndexModel : PageModel
{
public string StudentName { get; private set; } = "PageModel in C#";
private readonly ILogger<IndexModel> _logger;
private readonly myWebApp.Data.SchoolContext _context;

public IndexModel(ILogger<IndexModel> logger, myWebApp.Data.SchoolContext context)
{
_logger = logger;
_context= context;
}

public void OnGet()
{
var s =_context.Students?.Where(d=>d.ID==1).FirstOrDefault();
this.StudentName =
quot;{s?.FirstMidName} {s?.LastName}";
}
}

Configuration file

The entry point to Docker Compose is a Compose file, usually called docker-compose.yml

In the project directory, create a new file docker-compose.yml in it. Add the following contents:

services:
db:
image: postgres
restart: always
environment:
POSTGRES_PASSWORD: example
volumes:
- postgres-data:/var/lib/postgresql/data
adminer:
image: adminer
restart: always
ports:
- 8080:8080
app:
build:
context: .
dockerfile: ./Dockerfile
ports:
- 5000:80
depends_on:
- db
volumes:
postgres-data:

In this Compose file:

  • Two services in this Compose are defined by the name db and web attributes; the adminer service is a helper for us to access db
  • Image name for each service defined using image attribute
  • The postgres image starts the Postgres server.
  • environment attribute defines environment variables to initialize postgres server.
    • POSTGRES_PASSWORD is used to set the default user’s, postgres, password. This user will be granted superuser permissions for the database my_db in the connectionstring.
  • app application uses the  db service as specified in the connection string
  • The app image is built using the Dockerfile in the project directory
  • Port forwarding is achieved using ports attribute.
  • depends_on attribute allows to express dependency between services. In this case, Postgres will be started before the app. Application-level health checks are still the user’s responsibility.

Start the application

All services in the application can be started, in detached mode, by giving the command:

docker-compose up -d

An alternate Compose file name can be specified using -foption.

An alternate directory where the compose file exists can be specified using -p option.

This shows the output as:

ocker compose up -d
[+] Running 4/4
⠿ Network mywebapp_default      Created                                             0.1s
⠿ Container mywebapp-db-1       Started                                             1.4s
⠿ Container mywebapp-adminer-1  Started                                             1.3s
⠿ Container mywebapp-app-1      Started                                             1.8s

0

The output may differ slightly if the images are downloaded as well.

Started services can be verified using the command docker-compose ps:

ocker compose ps
NAME                 COMMAND                  SERVICE             STATUS              PORTS
mywebapp-adminer-1   "entrypoint.sh docke…"   adminer             running             0.0.0.0:8080->8080/tcp
mywebapp-app-1       "./mywebapp"             app                 running             0.0.0.0:5000->80/tcp
mywebapp-db-1        "docker-entrypoint.s…"   db                  running             5432/tcp

This provides a consolidated view of all the services, and containers within each of them.

Alternatively, the containers in this application, and any additional containers running on this Docker host can be verified by using the usual docker container ls command

docker container ls
CONTAINER ID   IMAGE               COMMAND                  CREATED              STATUS                   PORTS                              NAMES
f38fd86eb54f   mywebapp_app        "./mywebapp"             About a minute ago   Up About a minute        0.0.0.0:5000->80/tcp               mywebapp-app-1
7b6b555585b9   adminer             "entrypoint.sh docke…"   About a minute ago   Up About a minute        0.0.0.0:8080->8080/tcp             mywebapp-adminer-1
5ea39a742206   postgres            "docker-entrypoint.s…"   About a minute ago   Up About a minute        5432/tcp                           mywebapp-db-1

Service logs can be seen using docker-compose logs command, and looks like:

docker compose logs
mywebapp-adminer-1  | [Fri Apr 15 12:38:31 2022] PHP 7.4.16 Development Server (http://[::]:8080) started
mywebapp-db-1       |
mywebapp-db-1       | PostgreSQL Database directory appears to contain a database; Skipping initialization
mywebapp-db-1       |
mywebapp-db-1       | 2022-04-15 12:38:32.033 UTC [1] LOG:  starting PostgreSQL 13.2 (Debian 13.2-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
mywebapp-db-1       | 2022-04-15 12:38:32.034 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
mywebapp-db-1       | 2022-04-15 12:38:32.034 UTC [1] LOG:  listening on IPv6 address "::", port 5432
mywebapp-db-1       | 2022-04-15 12:38:32.056 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
mywebapp-db-1       | 2022-04-15 12:38:32.084 UTC [27] LOG:  database system was shut down at 2021-11-13 22:52:29 UTC
mywebapp-db-1       | 2022-04-15 12:38:32.171 UTC [1] LOG:  database system is ready to accept connections
mywebapp-app-1      | warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
mywebapp-app-1      |       Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
mywebapp-app-1      | warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
mywebapp-app-1      |       No XML encryptor configured. Key {e94371f0-08d1-43a0-b286-255e0005605c} may be persisted to storage in unencrypted form.
mywebapp-app-1      | info: Microsoft.Hosting.Lifetime[0]
mywebapp-app-1      |       Now listening on: http://[::]:80
mywebapp-app-1      | info: Microsoft.Hosting.Lifetime[0]
mywebapp-app-1      |       Application started. Press Ctrl+C to shut down.
mywebapp-app-1      | info: Microsoft.Hosting.Lifetime[0]
mywebapp-app-1      |       Hosting environment: Production
mywebapp-app-1      | info: Microsoft.Hosting.Lifetime[0]
mywebapp-app-1      |       Content root path: /app

Verify application

Let’s access the application. In your browser address bar type http://localhost:5000

you will see the page show no student name since the database is empty.

student name myweb app

Open a new tab with address http://localhost:8080 and you will be asked to login:

adminer login

Use postgres and example as username/password to login  my_db. Once you are logged in, you can create a new student record as shown:

creating a student record

Next, refresh the app page at http://localhost:5000, the new added student name will be displayed:

awesome james

Shutdown application

Shutdown the application using docker-compose down:

docker compose down
[+] Running 4/4
⠿ Container mywebapp-app-1      Removed                                             0.4s
⠿ Container mywebapp-adminer-1  Removed                                             0.3s
⠿ Container mywebapp-db-1       Removed                                             0.4s
⠿ Network mywebapp_default      Removed                                             0.1s

This stops the container in each service and removes all the services. It also deletes any networks that were created as part of this application.

Conclusion

We demonstrated the containerization of .NET application and the usage of docker compose to construct a two layers simple web application with dotnet. The real world business application can be composed of multiple similar applications, ie. microservice application, that can be described by docker compose file. The same process in the tutorial can be applied to much more complicated applications.

]]>