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デスクトップがシステムにインストールされていることがわかります。
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
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 つのサービスは、名前
db
とweb
属性によって定義されます。 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_d
b するためのユーザー名/パスワードとして 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 作成ファイルで記述できるマイクロサービス アプリケーション。 チュートリアルの同じプロセスは、はるかに複雑なアプリケーションに適用できます。