たびとの旅路 ~電脳砂漠の冒険譚~

フロッピー頼りに歩き、クラウドの地平を見つめる今日まで。見つけたオアシス、迷い込んだ砂の迷宮、全てこの羊皮紙に。

第三章:異次元の箱庭に、魂を宿せ ~Dockerで創る、gRPCのゴーレム~

旅の途中、興味深いオアシスを見つけた。忘れないうちに、この羊皮紙に記しておくとしよう。

Windows、そしてLinux。二つの広大な大地を旅した後、私はついに、gRPC(高性能RPC通信)のゴーレムを召喚する、究極の祭壇に辿り着いた。その名は「Docker」(コンテナ仮想化技術)。あらゆる環境の差異を吸収し、どこにでも持ち運べる、異次元の箱庭だ。

今回は、これまでの旅で得た知見を元に、このDocker(コンテナ仮想化技術)という箱庭の中で、gRPCサーバというゴーレムを錬成する。自己署名証明書(開発用SSL証明書)という結界を自ら創り出し、コンテナ(隔離実行環境)の中で魂を安全に稼働させる、その儀式の全てを、未来の錬金術師たちのために記そう。

この羊皮紙のあらまし

この羊皮紙が導く者

  • gRPCという名のゴーレムを、Dockerというポータブルな器に封じ込めたいと願う者
  • HTTP/2という光の道を、コンテナを越えて繋げたい探求者
  • マイクロサービスアーキテクチャに興味がある実務家
  • 開発環境をコンテナ化したい開発者

砂漠の道標

  • gRPC - Google開発の高性能RPC(Remote Procedure Call)フレームワーク。HTTP/2ベース。
  • Docker - コンテナ仮想化技術。アプリケーションを隔離された環境で実行できる。
  • docker-compose - 複数のDockerコンテナを一括管理するツール。YAML形式で定義。
  • 自己署名証明書 - 認証局を介さず自身で発行したSSL/TLS証明書。開発・テスト環境で使用。
  • Dockerfile - Dockerイメージをビルドするための設定ファイル。
  • ASP.NET Core - Microsoftのオープンソースなクロスプラットフォームフレームワーク。
  • Kestrel - ASP.NET Core標準のWebサーバ。高性能で軽量。
  • マルチステージビルド - Dockerfileで複数の段階を経てイメージを作成する手法。最終イメージを軽量化できる。

第一の儀式:結界の創造(自己署名証明書)

HTTPS(暗号化HTTP通信)という聖なる光でゴーレムを護るには、まず「証明書」(SSL/TLS証明書)という名の結界が必要だ。openssl(SSL/TLS暗号化ツール)の古の呪文を三度唱え、我々は自らの手で、この儀式に不可欠な結界を創り出す。

# 秘密鍵という、結界の核を創る(2048ビットRSA鍵)
$ openssl genrsa 2048 > ssl_greeter.key
# 証明書発行要求(CSR)という、神々への願いを記す
$ openssl req -new -key ssl_greeter.key -out ssl_greeter.csr
# 自らの力で、願いを成就させ、証明書を創り出す(10年間有効)
$ openssl x509 -days 3650 -in ssl_greeter.csr -req -signkey ssl_greeter.key -out ssl_greeter.crt

第二の儀式:魂の設計図(ソースコード)

次に、ゴーレムの魂の設計図を、現代の言葉で記していく。

世界の契約書:docker-compose.yml(Docker Compose設定ファイル)

この箱庭の世界全体の理を定義する。ゴーレムにgreeterという名を与え、外界との魂の通り道(ポート番号)を定め、先ほど創り出した結界(証明書)を、コンテナ(隔離実行環境)内の聖域へと共有する。

version: '3.8'
services:
  #gRPC (ASP.NET Core)
  app:
    container_name: 'greeter'
    build:
      context: ./src        # ビルドコンテキスト
      dockerfile: Dockerfile
    ports:
      - "5094:80"   # HTTP通信ポート(ホスト:コンテナ)
      - "7094:443"  # HTTPS通信ポート(ホスト:コンテナ)
    environment:
      TZ: Asia/Tokyo  # タイムゾーン設定
    volumes:
      - ./ssl_greeter.crt:/etc/ssl/certs/ssl_greeter.crt      # SSL証明書をマウント
      - ./ssl_greeter.key:/etc/ssl/private/ssl_greeter.key    # SSL秘密鍵をマウント
    tty: true
    restart: always
    stdin_open: true

魂の錬成工程:Dockerfile(イメージビルド定義)

ゴーレムの魂を、どのように錬成するかを記した、最も重要な羊皮紙だ。sdk(.NET SDK:開発キット)という名の広大な工房で魂を鍛え上げ、完成した魂を、aspnet(ASP.NET Coreランタイム)という名の、より軽量で戦闘に特化した器へと移し替える。

# 本番用の器(.NET6 runtime:実行環境のみ)
FROM mcr.microsoft.com/dotnet/aspnet:6.0-focal AS runtime
ENV ASPNETCORE_URLS=http://+:80;https://+:443  # 待ち受けURLを環境変数で設定
EXPOSE 80   # HTTPポート公開
EXPOSE 443  # HTTPSポート公開

# 魂を鍛える工房(sdk:開発キット)
FROM mcr.microsoft.com/dotnet/sdk:6.0-focal AS build
ARG DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0
WORKDIR /src
COPY ["./GrpcGreeter/GrpcGreeter.csproj", "GrpcGreeter/"]
RUN dotnet restore "./GrpcGreeter/GrpcGreeter.csproj"  # 依存関係の復元
COPY . .
WORKDIR "/src/GrpcGreeter"
RUN dotnet build "GrpcGreeter.csproj" -c Release -o /app/build  # Releaseビルド

# 鍛え上げた魂を工房から取り出す
FROM build AS publish
RUN dotnet publish "GrpcGreeter.csproj" -c Release -o /app/publish  # 発行

# 魂を、本番用の器へと移し替える(マルチステージビルドで軽量化)
FROM runtime AS final
WORKDIR /app
COPY --from=publish /app/publish .  # publishステージから成果物をコピー
ENTRYPOINT ["dotnet", "GrpcGreeter.dll"]  # 起動コマンド

(注:上記Dockerfileは、./src/GrpcGreeter/配下にcsprojファイルがある前提の記述です)

魂の契約:appsettings.json(ASP.NET Core設定ファイル)

ゴーレムに、自らが護られるべき結界(証明書)の場所を教える。

{
  "Kestrel": {  // ASP.NET Core標準Webサーバの設定
    "Certificates": {
      "Default": {
        "Path": "/etc/ssl/certs/ssl_greeter.crt",      // 証明書のパス
        "KeyPath": "/etc/ssl/private/ssl_greeter.key"  // 秘密鍵のパス
      }
    }
  }
}

最終儀式:魂の召喚と対話

全ての設計図が揃ったら、docker-compose build(イメージビルド)で魂を錬成し、docker-compose up -d(コンテナ起動)で箱庭に魂を召喚する。 docker-compose logs(ログ表示)コマンドで、ゴーレムが正常に起動し、力強く鼓動しているのがわかるだろう。

$ docker-compose logs
grpc  | INFO : Now listening on: http://[::]:80
grpc  | INFO : Now listening on: https://[::]:443
grpc  | INFO : Application started. Press Ctrl+C to shut down.
...

二つの光の道(ポート80と443)で、来訪者を待ち構えている。これこそが、魂が正常に宿った証だ。

Windowsの世界から、gRPCクライアント(gRPC通信を行うアプリケーション)という名の魔法で、箱庭の中のゴーレムと対話する。 172.18.126.178:7094という、異次元への座標(WSL2のIPアドレス:ポート番号)を指定し、HttpClientHandler(HTTP通信制御クラス)で結界への信頼を宣言すれば、二つの世界は光の道で結ばれる。

// 異次元の座標(WSL2のIPアドレスとHTTPSポート)
var server = "https://172.18.126.178:7094";

var option = new GrpcChannelOptions()
{
    HttpClient = new HttpClient(new HttpClientHandler
    {
        // 自己署名証明書という結界を、信頼する(開発環境専用)
        ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
    })
};
var channel = GrpcChannel.ForAddress(server, option);
// ...
gRPC クライアントの正常終了

二つの世界が繋がり、対話が成功した証

羊皮紙を巻く前に

Windows、Linux、そしてDocker。三つの大地を旅し、我々はついに、どこにでも持ち運べる、堅牢なgRPC(高性能RPC通信)ゴーレムを錬成する術を手に入れた。自己署名証明書(開発用SSL証明書)という結界を自ら創り出し、docker-compose(Docker統合管理ツール)とDockerfile(イメージビルド定義)という二つの設計図で、異次元の箱庭に魂を宿す儀式は、想像以上に明快なものだった。

Docker版gRPCの優れた点

  1. 環境の完全な一貫性 - 開発・検証・本番環境で同一の動作を保証。「俺の環境では動くのに」という呪いからの解放
  2. 真のポータビリティ - コンテナイメージをどこでも実行可能。クラウドでもオンプレミスでも同じ動作を実現
  3. マルチステージビルドによる軽量化 - sdk(開発キット)で魂を鍛え、aspnet(実行環境)という軽量な器に移し替えることで、最終イメージを最小化
  4. 環境変数による普遍的制御 - ASPNETCORE_URLS環境変数でポート設定を制御。launchSettings.json(Visual Studio専用設定)というローカルな呪文に依存しない

この儀式で学んだこと

Docker版では、環境変数ASPNETCORE_URLS=http://+:80;https://+:443という普遍的な方法で、Kestrel(ASP.NET Coreの標準Webサーバ)の待ち受けポートを制御できる。これは、launchSettings.jsonというVisual Studio専用の設定ファイルに依存せず、あらゆる環境で一貫して動作する、真に移植可能な設定方法だ。

まとめ

この後、我々の旅は、この城塞の前にNginx(高性能Webサーバ・リバースプロキシ)という鉄壁の門番を配置する、さらなる冒険へと続いていく。Dockerという異次元の箱庭は、単なる実行環境ではなく、マイクロサービスアーキテクチャ(サービス分散型設計)という、より壮大な世界を構築するための、確かな礎となるのだ。

この羊皮紙が、同じように異次元の箱庭で魂を錬成しようと挑む、未来の冒険者の助けとなることを願う。

おっと、相棒が「もう日が暮れる」と急かしている。今宵はここまでとしよう。

砂漠で見つけた魔法のランプ

ラクダの独り言

ご主人が「どっかー」とかいう、透明な箱の中にゴーレムを創り出して、悦に入っている。なんでも、この箱ごとどこへでも持っていけるらしい。俺に言わせりゃ、そんな面倒なことしなくても、俺の背中に乗せりゃどこへでも運んでやるのによ。それに、箱の中に箱を入れて、その中にまた何か入れて…って、まるで入れ子細工だ。まったく、人間ってのは、シンプルなものを複雑にするのが大好きだな。やれやれだぜ。