概要
Visual Studio2022で、Dockerサポート機能を使って、開発出来るようにする手順です。実行する環境は以下の通りです。
OS:Windows11
プロジェクト:.NET Core Razor Pages
DB:MSSQL2019
Dockerバージョン:4.9.0
設定ファイルなどに含まれる、プロジェクト名などは、適宜書き換えてください。
プロジェクトをDockerコンテナ上で実行する
手順1. Dockerをインストールする
まずは、Dockerを公式サイトからインストールします。
手順2. プロジェクトの作成
新規プロジェクトを作成します。
今回はRazor Pageを選択して、プロジェクト名は「RazorPageSample」で作成します。
画面を進めていくと、追加情報という画面が表示されます。
「Dockerを有効にする」という項目に、チェックを入れて、OSはLinuxを選択しておきます。
作成が完了すると、デバッグ開始ボタンがDockerになっています。
Dockerfileは自動で生成されるので、このまま実行すれば、Dockerコンテナ上で実行され、いつも通りデバッグ可能な状態になります。
Dockerに関する操作をすることなく、簡単に設定出来てしまうため、本当にDockerコンテナ上で動いているか、OSバージョンを表示させて確認してみます。
@page
@model IndexModel
@{
// OSの情報を取得する
System.OperatingSystem os = System.Environment.OSVersion;
ViewData["OS"] = os.ToString();
ViewData["Title"] = "Home page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p class="display-6">OS:@ViewData["OS"]</p>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
.net6.0のイメージに使われているOSが、Debainになるので、Unixと表示されます。
以上の設定で、DBを使わないWebアプリなどであれば、簡単にDocker上で動かすことが出来ます。
補足
Dockerfileに下記の設定を追加すると、DateTimeで取得できる日時を、JSTのYYYY/MM/DD形式に変更できます。.net6.0のイメージに使われているOSのタイムゾーンをJSTにして、言語を日本語にしています。
ENV TZ Asia/Tokyo
ENV DEBIAN_FRONTEND noninteractive
ENV LC_ALL ja_JP.UTF-8
RUN apt-get update
RUN apt-get install -y locales
RUN echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen ja_JP.UTF-8 && \
dpkg-reconfigure locales && \
/usr/sbin/update-locale LANG=ja_JP.UTF-8
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
# .net6.0のイメージに使われているOSがDebainで、以下の設定でタイムゾーンをJSTに変更して、日本語化している
ENV TZ Asia/Tokyo
ENV DEBIAN_FRONTEND noninteractive
ENV LC_ALL ja_JP.UTF-8
RUN apt-get update
RUN apt-get install -y locales
RUN echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen ja_JP.UTF-8 && \
dpkg-reconfigure locales && \
/usr/sbin/update-locale LANG=ja_JP.UTF-8
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["RazorPageSample/RazorPageSample.csproj", "RazorPageSample/"]
RUN dotnet restore "RazorPageSample/RazorPageSample.csproj"
COPY . .
WORKDIR "/src/RazorPageSample"
RUN dotnet build "RazorPageSample.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "RazorPageSample.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "RazorPageSample.dll"]
プロジェクトのコンテナとDBコンテナを同時に立ち上げる
次に、プロジェクトのコンテナとDBコンテナを、同時に立ち上げる設定方法です。大抵の場合は、DBが必要になってくると思うので、こちらの設定が必要になるかと思います。
手順1. コンテナーオーケストレーターサポートの追加
プロジェクトを右クリックして、追加からコンテナオーケストレーターサポートを追加をします。コンテナーオーケストレーターは「Docker Compose」、ターゲットOSは、「Linux」を選択します。
手順2. docker-compose.ymlにDBコンテナの設定を追加
ソリューションエクスプローラーにdocker-compose.ymlというファイルが追加されます。このファイルは、複数のコンテナを同時に立ち上げるのに使うファイルです。
デフォルトでは、プロジェクトのコンテナのみになっているので、DBコンテナも立ち上げるように設定を追加します。
version: '3.4'
services:
razorpagesample:
image: ${DOCKER_REGISTRY-}razorpagesample
build:
context: .
dockerfile: RazorPageSample/Dockerfile
depends_on:
- sqlexpress
sqlexpress:
image: mcr.microsoft.com/mssql/server:2019-latest
environment:
MSSQL_PID: "Express"
ACCEPT_EULA: "Y"
SA_PASSWORD: "P@ssw0rd"
MSSQL_LCID: "1041"
MSSQL_COLLATION: "Japanese_CI_AS"
volumes:
- "./db/mssqlserver/data:/var/opt/mssql/data"
- "./db/mssqlserver/log:/var/opt/mssql/log"
- "./db/mssqlserver/secrets:/var/opt/mssql/secrets"
- "./db/mssqlserver/backup:/var/opt/mssql/backup"
ports:
- "1401:1433"
depends_on: - sqlexpressで、先にDBコンテナを立ち上げてから、プロジェクトのコンテナを立ち上げるようにしています。
あとは、パスワードを設定したり、日本語化設定を行っています。
volumes:の設定はDBの永続化設定になります。
こうすることで、DBコンテナが終了しても、DBのデータが消えないようにしています。dbフォルダはプロジェクトの直下に生成されます。
手順3. SSMSからDBコンテナにアクセスする
開始ボタンが、「Docker」から「Docker Compose」に変わっていると思います。Dockerは、Dockerfileを元に実行されますが、Docker Composeの場合は、docker-compose.ymlを元にコンテナが実行されます。
一度、Docker Composeで実行します。
すると、プロジェクトのコンテナと、DBコンテナが立ち上がります。
コンテナの状況は、Docker DesktopのContainersから確認出来ます。
DBコンテナが起動していることを確認して、SSMSからDBコンテナにアクセスしてみます。
接続先情報は、先ほどdocker-compose.ymlで設定した通りです。
アクセス出来ました。
これで、Docker上で開発出来る環境が整ったので、試しに公式のチュートリアルを進めてみます。
手順4. ムービーモデルの作成
まずは、Razor Pagesの公式チュートリアルのムービー モデルのスキャフォールディングまで進めます。
手順5. DBコンテナに対して、EF の移行機能を使用して初期データベース スキーマを作成する
appsettings.jsonのDB接続先を、ローカルDBからDBコンテナに変更します。{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPageSampleContext": "Server=localhost,1401;Database=razor_sample_db;User ID=sa;Password=P@ssw0rd;initial catalog=razor_sample_db;MultipleActiveResultSets=True;App=EntityFramework;"
}
}
スタートアッププロジェクトを「docker-compose」から「RazorPageSample」に切り替えてから、パッケージマネージャーコンソールで下記コマンドを実行します。
スタートアッププロジェクトを切り替えておかないと、コマンドが実行出来ません。
Add-Migration InitialCreate
Update-Database
コマンドが実行され、DBコンテナに初期データベースが作成されました。
手順6. appsettings.jsonを書き換える設定を追加
appsettings.jsonの接続先情報で、Docker Composeで実行すると、コンテナ自身のlocalhostを参照してしまい、DB接続エラーになってしまいます。なので、ソリューションエクスプローラーから、docker-compose.ymlの下にある「docker-compose.override.yml」というファイルに、下記の通り設定して接続出来るようにします。
version: '3.4'
services:
razorpagesample:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
- ConnectionStrings__RazorPageSampleContext=Server=sqlexpress;Database=razor_sample_db;User ID=sa;Password=P@ssw0rd;initial catalog=razor_sample_db;MultipleActiveResultSets=True;App=EntityFramework;
ports:
- "80"
- "443"
volumes:
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
実行するときに、appsettings.jsonのConnectionStrings > RazorPageSampleContextの値が、docker-compose.override.ymlで設定した内容に書き換わるようになります。
これで、Dockerコンテナ上で、データの登録、編集、削除が出来るようになります。
DockerコンテナからホストのDBに接続する方法
最後に、Dockerコンテナから、ホストのローカルSQL Serverに接続する方法です。DBコンテナも一緒に立ち上げる方が簡単で、開発環境を統一しやすいメリットがあるので、あまり使わないかもしれません。
手順1. TCP/IPを有効にする
SQL Server構成マネージャーを開いて、TCP/IPを有効にします。そして、TCP/IPのプロパティのIPAllの「TCP 動的ポート」を後で使うので、メモしておきます。
手順2. SQL Serverの再起動
SQL Serverのサービスから、SQL Serverの再起動をします。
手順3. 接続先を変更
appsettings.jsonのDB接続先を変更します。{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPageSampleContext": "Server=host.docker.internal,50489; Database=razor_sample_db; User ID=sa; MultipleActiveResultSets=true;App=EntityFramework;"
}
}
localhost,1401;だった部分を、host.docker.internal,50489;に変更しています。
「host.docker.internal」はコンテナから、ホストのネットワークにアクセスするためのDNS名になります。ポート番号は、手順1. TCP/IPを有効にするで、メモしたポート番号を指定します。
あとは、ユーザーはsaのままで、パスワードは設定していないので、IDだけの指定になっています。
以上の設定で、ホストのローカルDBに繋がるようになるはずです。