Docker デスクトップを使用したマルチコンテナ .NET アプリの構築

クジラパープルガイ

NET は、Webアプリ、Web API、クラウドのサーバーレス機能、モバイルアプリなど、多数のアプリを構築するための無料のオープンソース開発プラットフォームです。 .NET は、マイクロソフトと GitHub 上の .NET コミュニティによって管理されている汎用開発プラットフォームです。 クロスプラットフォームであり、Windows、macOS、Linux をサポートしており、デバイス、クラウド、埋め込み/IoT のシナリオで使用できます。

Docker は .NET コミュニティの間で非常に人気があります。 .NET Core は 、Docker コンテナーで簡単に実行できます。 .NET には、 自動メモリ管理、(ランタイム) ジェネリック型、 リフレクション非同期同時実行ネイティブ相互運用など、開発を容易にするいくつかの機能があります。 何百万人もの開発者がこれらの機能を利用して、高品質のアプリケーションを効率的に構築しています。

アプリケーションのビルド

このチュートリアルでは、 Docker Compose を使用して .NET アプリケーションをコンテナー化する方法について説明します。 このブログで使用するアプリケーションは、 Postgresql データベースと通信するウェブアプリです。 ページが読み込まれると、Student テーブルに対して ID を持つレコードが照会され、ページに学生の名前が表示されます。

何が必要ですか?

始める

https://www.docker.com/get-started/ にアクセスして、Mac用のDockerデスクトップをダウンロードし、システムにインストールします。

ドッカーの使用を開始する

インストールが完了したら、「Dockerデスクトップについて」をクリックして、システムで実行されているDockerのバージョンを確認します。

Dockerデスクトッププルダウンメニューについて

上記の手順に従うと、常に最新バージョンのDockerデスクトップがシステムにインストールされていることがわかります。

ドッカーデスクトップバージョン4。7 ようこそ

1. ターミナルで、次のコマンドを入力します

dotnet new webApp -o myWebApp --no-https

'dotnet new' コマンドは、テンプレートに基づいて .NET プロジェクトまたはその他の成果物を作成します。

ターミナルに出力が表示されます

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.

これにより、dotnet sdk に付属するテンプレートから新しい Web アプリケーションがブートストラップされます。 -o パラメーターは、アプリが格納される myWebApp という名前のディレクトリを作成します。

2. アプリケーションディレクトリに移動します

cd マイウェブアプリ

ファイルのリストがあります–

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. ターミナルで、次のコマンドを入力してアプリケーションを実行します

このコマンドは dotnet run 、ソース コードからアプリケーションを実行するための便利なオプションを提供します。

dotnet run –urls http://localhost:5000

アプリケーションは要求のリッスン port 5000 を開始します

# 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. アプリケーションをテストする

curl コマンドを実行して、Web アプリケーションの接続をテストします。

# カール http://localhost:5000

ようこそ1マイウェブアプリ

5. アプリケーションをコンテナーに入れる

Dockerコンテナで同じアプリケーションを実行するために、次のコンテンツでDockerfileを作成しましょう。

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"]

これは マルチステージ ドッカーファイルです。 ビルド・ステージでは、SDK イメージを使用してアプリケーションをビルドし、パブリッシュ・フォルダーに最終的な成果物を作成します。 次に、最終段階で、ビルド ステージからアプリ フォルダーに成果物をコピーし、ポート 80 を受信要求に公開し、アプリケーション myWebAppを実行するコマンドを指定します。

Dockerfile で実行するために必要なすべてのものを定義したので、このファイルを使用してイメージをビルドできます。 これを行うには、次のコマンドを実行する必要があります。

$ docker build -t mywebapp .

これで、docker imagesコマンドを使用して、イメージがマシンに存在することを確認できます。

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

この新しく作成されたイメージを実行するには、docker runコマンドを使用して、マップ先のポートと実行するイメージを指定できます。

$ドッカー実行--rm - p5000:80 mywebapp

  • - p 5000:80–これにより、ローカルマシンの http://localhost:5000 コンテナ内のポート80で実行されているアプリケーションが公開されます。
  • --rm –このフラグは、実行後にコンテナをクリーンアップします
  • mywebapp –これは、コンテナで実行するイメージの名前です。

次に、ブラウザを起動し、http://localhost:5000 アドレスをアドレスバーに配置します

ようこそ私のウェブアプリ

アプリケーションの更新

myWebApp と Postgresql は 2 つの別々のコンテナーで実行されるため、これはマルチコンテナー アプリケーションになります。

1.アプリがデータベースと通信できるようにするパッケージを追加します

ディレクトリを myWebapp に変更し、次のコマンドを実行します。
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL

2. 学生モデルの作成

  • プロジェクト フォルダーに Models フォルダーを作成する
  • 次のコードを使用して.csモデル/学生を作成します。
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.次のコードを使用して「スクールコンテキスト」を作成します。

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. スタートアップで DI に登録 SchoolContext します.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. データベース接続文字列を '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. テーブルに存在しない場合はブートストラップします。 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();

 

UI を更新する

'Pages/Index.cshtml' に以下を追加します。

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

'Pages/Index.cshtml.cs' を更新します。 以下に示すように:

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}";
}
}

構成ファイル

Docker Compose へのエントリ ポイントは、通常は docker-compose.yml

プロジェクトディレクトリで、その中に新しいファイル docker-compose.yml を作成します。 次の内容を追加します。

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:

この作成ファイルの内容:

  • この Compose の 2 つのサービスは、名前 dbweb 属性によって定義されます。 adminer サービスは、db にアクセスするためのヘルパーです
  • 属性を使用して image 定義された各サービスのイメージ名
  • イメージによって postgres Postgres サーバーが起動します。
  • environment 属性は、PostGresサーバを初期化するための環境変数を定義します。
    • POSTGRES_PASSWORD は、デフォルトのユーザー、 postgres、 パスワードを設定するために使用されます。 このユーザーには、接続文字列で my_db データベースに対するスーパーユーザー権限が付与されます。
  • アプリ アプリケーションは、  db 接続文字列で指定されたサービスを使用します
  • アプリ イメージは、プロジェクト ディレクトリ内の Dockerfile を使用してビルドされます
  • ポート転送は、属性を使用して ports 実現されます。
  • depends_on 属性を使用すると、サービス間の依存関係を表現できます。 この場合、Postgres はアプリの前に起動されます。 アプリケーションレベルのヘルスチェックは、引き続きユーザーの責任です。

アプリケーションを起動する

アプリケーション内のすべてのサービスは、次のコマンドを指定することで、デタッチモードで開始できます。

docker-compose up -d

代替の作成ファイル名は、オプションを使用して -f指定できます。

作成ファイルが存在する代替ディレクトリは、オプションを使用して -p 指定できます。

これにより、出力が次のように表示されます。

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

画像もダウンロードすると、出力が若干異なる場合があります。

開始されたサービスは、次のコマンドを使用して確認できます 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

これにより、すべてのサービスと各サービス内のコンテナーの統合ビューが提供されます。

または、このアプリケーション内のコンテナーと、この Docker ホストで実行されている追加のコンテナーは、通常の docker container ls コマンドを使用して検証できます

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

サービスログはコマンドを使用して表示 docker-compose logs でき、次のようになります。

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

アプリケーションの検証

アプリケーションにアクセスしてみましょう。 ブラウザーのアドレス バーに次のように入力します http://localhost:5000

データベースが空であるため、ページに学生名が表示されません。

学生名 マイウェブアプリ

アドレス http://localhost:8080 で新しいタブを開くと、ログインするように求められます。

管理者ログイン

ログイ ン my_db するためのユーザー名/パスワードとして postgres 例 を使用します。ログインすると、次のように新しい学生レコードを作成できます。

学生レコードの作成

次に、http://localhost:5000 でアプリページを更新すると、新しく追加された学生の名前が表示されます。

素晴らしいジェームズ

アプリケーションのシャットダウン

を使用してアプリケーションをシャットダウンします 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

これにより、各サービスのコンテナーが停止し、すべてのサービスが削除されます。 また、このアプリケーションの一部として作成されたネットワークもすべて削除されます。

結論

NETアプリケーションのコンテナ化と、dotnetを使用して2層のシンプルなWebアプリケーションを構築するためのdocker composeの使用を示しました。 現実世界のビジネスアプリケーションは、複数の類似したアプリケーション、すなわちで構成することができる。 Docker 作成ファイルで記述できるマイクロサービス アプリケーション。 チュートリアルの同じプロセスは、はるかに複雑なアプリケーションに適用できます。

フィードバック

「Dockerデスクトップを使用したマルチコンテナ.NETアプリケーションの構築」に関する0の考え