WCF サービスを Windows コンテナのプロセス分離モードで動かす実験

はじめに

先日、ASP.NET Core アプリを Windows コンテナのプロセス分離モードで動かす実験を行った。

tnakamura.hatenablog.com

本業で抱える .NET Framework の資産は、ASP.NET Core よりも WCF の方が大多数なので、 次は WCF サービスをコンテナ化する実験を行ってみる。

WCF サービス

今回の実験で使用した WCF サービスは下記の通り。

using System;
using System.Threading;
using System.ServiceModel;

namespace WcfWCOW
{
    class Program
    {
        static void Main(string[] args)
        {
            var host = new ServiceHost(typeof(GreetingService));
            try
            {
                var binding = new NetTcpBinding();
                binding.Security.Mode = SecurityMode.None;

                host.AddServiceEndpoint(
                    typeof(IGreetingService),
                    binding,
                    "net.tcp://localhost:808/GreetingService");
                host.Open();

                foreach (var endpoint in host.Description.Endpoints)
                {
                    Console.WriteLine(endpoint.ListenUri);
                }

                Thread.Sleep(-1);

            }
            catch
            {
                host.Close();
            }
        }
    }

    [ServiceContract]
    public interface IGreetingService
    {
        [OperationContract]
        string Hello(string name);
    }

    public class GreetingService : IGreetingService
    {
        public string Hello(string name)
        {
            return $"Hello {name}!";
        }
    }
}

NetTcpBinding を使う超単純な WCF サービス。

Dockerfile

WCF サービスはあらかじめリリースビルドしておき、 それをもとにコンテナイメージを作る Dockerfile を記述した。

FROM mcr.microsoft.com/dotnet/framework/wcf:4.8
WORKDIR /app
EXPOSE 808
COPY ./WcfWCOW/bin/Release/ .
ENTRYPOINT ["WcfWCOW.exe"]

ベースとなるコンテナイメージは WCF 用のものを利用。

コンテナイメージ作成

> docker build -t tnakamura/wcfwcow:1.0 .

f:id:griefworker:20190626150939p:plain

コンテナ起動

プロセス分離モードでコンテナを起動。 今回は -d オプションを指定して、コンテナをバックグラウンドで実行している。

> docker run -d --isolation process --name wcfwcow tnakamura/wcfwcow:1.0

f:id:griefworker:20190626150953p:plain

WCF クライアント

コンテナ内で動いている WCF サービスにアクセスするためのクライアントを作成。 WCF サービスのエンドポイントはコンテナを起動するたびに変わるので、 エンドポイントアドレスをコマンドライン引数で渡せるようにしておいた。

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using WcfWCOW;

namespace ConsoleClient
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("ホスト名または IP アドレスを指定してください。");
                return;
            }
            var host = args[0];
            var factory = new ChannelFactory<IGreetingService>(
                new NetTcpBinding(SecurityMode.None),
                $"net.tcp://{host}:808/GreetingService");
            var channel = factory.CreateChannel();

            var result = channel.Hello("Kubo");
            Console.WriteLine(result);

            Console.WriteLine("Enter で終了");
            Console.ReadLine();

            ((IChannel)channel).Close();
        }
    }
}

namespace WcfWCOW
{
    [ServiceContract]
    public interface IGreetingService
    {
        [OperationContract]
        string Hello(string name);
    }
}

接続テスト

WCF サービスが動いているコンテナの IP アドレスを調べる。

> docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" wcfwcow

f:id:griefworker:20190626151019p:plain

調べた IP アドレスを引数に、WCF クライアントを起動。

> ConsoleClient.exe 172.26.156.148

f:id:griefworker:20190626151029p:plain

結果が表示されたので、WCF サービスを呼び出しに成功したようだ。

おわりに

Windows コンテナのプロセス分離モードで、WCF サービスを動かすことに成功した。 実際にコンテナ化を考えている WCF サービスは SQL Server に接続するので、 次はコンテナ内のアプリからコンテナ外の SQL Server にアクセスする実験でもやってみようか。