ROMANCE DAWN for the new world

Microsoft Azure を中心とした技術情報を書いています。

Azure App Service と SQL Database をプライベートネットワークで利用する

App Service から SQL Database へのアクセスを仮想ネットワーク内に制限したいという要件がある場合、Virtual Network Integration と Private Endpoint を利用することで、プライベートネットワーク経由で安全に接続することができます。
従来から提供されている機能ではありますが、本記事ではあらためて構築手順を整理してまとめました。

システム構成

App Service から SQL Database へプライベートネットワークで接続するシンプルな構成を例に、構成方法を説明します。


Virtual Network Integration

App Service から仮想ネットワーク内のリソースへのアクセスを制御する機能です。
learn.microsoft.com

Private Endpoint

SQL Database へのアクセスを仮想ネットワークの中からのみに限定する機能です。
learn.microsoft.com

前準備

ASP.NET Core を使用して、商品一覧を表示するアプリケーションを用意しました。Shop データベースの Product テーブルを参照し、MVC の View に一覧表示しています。

public class ProductsController : Controller
{
    private readonly ShopDbContext _context;

    public ProductsController(ShopDbContext context)
    {
        _context = context;
    }

    public async Task<IActionResult> Index()
    {
        return View(await _context.Product.ToListAsync());
    }
}

ShopDbContext を Entity Framework Core の DI コンテナに登録し、データプロバイダーとして SQL Server を使用する構成としています。

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<ShopDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("ShopDbContext") ?? throw new InvalidOperationException("Connection string 'ShopDbContext' not found.")));

appsettings.json では、環境変数の ShopDbContext というキーから接続文字列を取得するように構成しています。

{
  "ConnectionStrings": {
    "ShopDbContext": "Server=(localdb)\\mssqllocaldb;Database=Shop;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

パブリックネットワークアクセスを有効にした SQL Database に接続する構成で、App Service にデプロイしました。

SQL Database の接続文字列は、App Service の環境変数に登録しています。


Virtual Network を作成する

前置きが長くなりましたが、ここからが本題です。
まずは、仮想ネットワークを作成します。この際、Virtual Network Integration 用と Private Endpoint 用のサブネットもあわせて作成します。

Virtual Network Integration 用のサブネットは、他のリソース(Private Endpoint など)と共有できないことに注意してください。

SQL Database の Private Endpoint を作成する

次に、SQL Database の Security - Networking から Private Endpoint を作成します。
Private Endpoint は、仮想ネットワーク内のサブネットにプライベート IP アドレスを持つ Network Interface Card として実体化されます。この NIC が、SQL Database へのプライベートな接続口となります。

対象サブリソースは、sqlserver を選択します。

Private Endpoint 用に作成したサブネットを選択し、IP アドレスを動的に割り当てるようにします。

SQL Database の FQDN をプライベート IP アドレスに正しく名前解決させるため、Private DNS Zone を統合させます。

Private Endpoint を作成できたら、SQL Database の Security - Networking からパブリックネットワークアクセスを無効にします。

これにより、App Service から SQL Database へ接続できなくなりました。


App Service の Virtual Network Integration を構成する

最後に、App Service の Settings - Networking から Virtual Network Integration を構成します。これにより、App Service から仮想ネットワーク内のリソースへアウトバウンド通信が可能になります。

Virtual Network Integration 用に作成したサブネットを選択して接続します。

App Service から SQL Database へプライベートネットワークで接続できるようになりました。Virtual Network Integration はアウトバウンド通信の制御となりますので、インバウンド通信を制御したい場合には Private Endpoint を作成する必要があります。

App Service の Kudu から nslookup を実行すると、SQL Database の FQDN からプライベート IP アドレスが返されていることを確認できます。


まとめ

App Service の Virtual Network Integration と SQL Database の Private Endpoint を利用することで、プライベートネットワーク経由の接続を構成しました。
次回は、このシステム構成に Key Vault を追加してみたいと思います。

第8回 Azure Travelers 勉強会 仙台の旅に参加してきました

先週、第8回 Azure Travelers 勉強会 仙台の旅に参加してきました。
jat.connpass.com

勉強会

株式会社 ASAHI Accounting Robot 研究所(ロボ研)さんにご協力をいただき、Microsoft Base Sendai をお借りしました。仙台と同じく、お洒落で素敵な会場でした。

予想以上に沢山の方に参加していただけたので、メイン会場だけでは収まり切らず、サテライト会場も作りました。メイン会場の様子をガラス越しに見ながら、サテライト配信側の数秒遅れのリアクションが不思議な感じでした。


普段自分が関わることが少ない領域は学びになることが多いですし、技術的な内容だけでなくお仕事や立場の異なる方々の話を聞けるのは面白いです。勉強会の翌日に観光を楽しんでいるところも含めて、Azure Travelers の良さだと思います。X のまとめがあるので、そんな雰囲気を感じ取ってもらえたらと。

posfie.com

今回もロボ研さんにスポンサーしていただいてステッカーを作りました。

スターバックスにコーヒートラベラーというものがあって、酒見さんが買ってきてくれました。会場に出来立てのコーヒーの香りがしていい感じで、ネーミングもコミュニティに合っているので、また機会があれば利用したいです。

menu.starbucks.co.jp

飛び入りの LT で Azure Durable Functions で作った NL2SQL Agent の精度向上に取り組んだ話をしました。会場の有識者からのフィードバックで今回のアプローチが的外れでないことが分かりましたし、別のアプローチもあるという学びもありました。

speakerdeck.com

午前中のみ配信のアーカイブがあります。

www.youtube.com

懇親会は集合郎 はなれでせり鍋、前夜祭は蔵の庄でネギまぐろ鍋、仙台の美味しいものと日本酒を満喫しました。

Azure Travelers では、開催地をサイコロで決める水曜どうでしょう的なルールがあり、次々回は広島に決定しました。既に申し込みサイトがオープンしています。
jat.connpass.com

仙台観光

仙台は東京と比べて寒かったです。最高気温が0℃くらいで、薄っすらと積もる程度でしたが、雪が降ることもありました。
今回は仙台に木曜日入りして、秋保温泉で一泊してから勉強会に参加しました。


秋保温泉

秋保温泉は、仙台駅から車で30分くらいのところにあり、別所温泉、野沢温泉とともに日本三御湯と言われています。3年前に来たことがあるのですが、なかなか良い温泉だったので今回も来ました。

www.sentabi.jp

温泉街っぽい写真は撮っていないのですが、GREAT DANE BREWING というブルワリーのクラフトビールが美味しかったです。



ニッカウヰスキー宮城峡蒸溜所

秋保から仙台に戻る途中で、ニッカウヰスキー宮城峡蒸溜所に立ち寄りました。

何度か来ていますが、今回初めて無料のガイドツアーに参加しました。ウイスキーの製造工程やニッカウヰスキーの歴史を説明してくれて、最後に試飲もついている70分のコースでとても良かったです。




仙台

仙台では、孤独のグルメに登場した萃萃で牛タンを食べました。本当は井之頭五郎が食べたテール焼きを注文したかったのですが、店主が納得いくテールが仕入れられなかったため、この日は残念ながら品切れとのことでした。


一応、仙台っぽい観光地にも行きました。

仙台城跡
瑞鳳殿

少し時間があったので、定禅寺通りのイルミネーションも見に行きました。

松島

勉強会の翌日は、友人たちと車で松島を観光しました。京都の天橋立、広島の厳島と並ぶ日本三景のひとつです。湾内を一周する遊覧船に乗って島巡りしました。





まとめ

第8回 Azure Travelers 勉強会 仙台の旅は、今回も楽しいイベントでした。会場を提供してくださったロボ研さんと参加者の皆様、ありがとうございました。
次回は 4月に金沢開催を予定しています。会場と日程を鋭意調整中です。

GitHub Copilot App Modernization を使って Azure App Service のアプリを .NET10 にマイグレーションする

.NET 10 が GA しましたので、Azure App Service にデプロイされている ASP.NET Core のアプリケーションをマイグレーションしました。
github.com

これまでは手動によるマイグレーションでしたが、今回は GitHub Copilot App Modernization を使ってみました。

GitHub Copilot App Modernization

.NET 9 から 10 にマイグレーションする手順は、こちらのドキュメントの通りです。
learn.microsoft.com

GitHub Copilot App Modernization を使うと、チャットの @modernize コマンドで .NET アプリを新しいバージョンにアップグレードできます。
learn.microsoft.com

Application

Visual Studio 2026 の GitHub Copilot 画面から、@modernize コマンドでアップグレードを開始します。

何をするか聞かれるので、Start a .NET upgrade workflow と入力します。

対話を進めると、アップグレードプランを提示してくれます。
github.com

.NET と NuGet packages のバージョンを更新するだけで済みそうなので、approve plan と入力します。

その後も対話を進めると、upgrade-to-NET10 ブランチが作成されて計画通りにアップグレードが完了しましたので、finish と入力します。

アップグレードレポートを確認して、コードの変更をコミットします。
github.com

ソリューションに含まれないので仕方ありませんが、GitHub Actions の workflow は更新してくれません。こちらの dotnet-version も忘れずに更新しておく必要があります。

jobs:
  build:
    runs-on: windows-latest

    steps:
      - uses: actions/checkout@v4

      - name: Set up .NET Core
        uses: actions/setup-dotnet@v1
        with:
          dotnet-version: '10.0.x'
          include-prerelease: true

その他のマイグレーション

GitHub Copilot App Modernization がマイグレーションしてくれなかった NuGet packages のバージョンを更新します。バージョンを更新するほかに、追加で対応した内容が2つあります。

OpenAPI 3.1 対応

.NET 10 で OpenAPI 3.1 のサポートが追加されたので、対応しておきました。
learn.microsoft.com

app.UseSwagger(c =>
{
    c.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1;
});

AutoMapper

AutoMapper はバージョン 15.0 より商用ライセンスが適用されることになりました。しばらくは無料で使いたいので、14.0 を使うことにしました。
www.jimmybogard.com

Azure App Service

App Service 側は、.NET Version を変更するのみです。

以上で、無事に .NET 10 へのマイグレーションが完了しました。


まとめ

GitHub Copilot App Modernization を使って Azure App Service のアプリを .NET10 にマイグレーションしてみました。
今回は .NET と NuGet packages のバージョンを更新するだけで済みましたが、破壊的変更があった場合はどのくらい自動で対応してくれるのか気になりました。
とはいえ、GitHub Actions の更新漏れがあったように、AI が更新した結果をしっかりとレビューすることは必須です。