Quantcast
Channel: ASP.NET Blog
Viewing all articles
Browse latest Browse all 7144

Let’s Try WCF Self-Hosted Services in a Container

$
0
0

Microservices are a hot architecture concept right now, and we hear a lot of interest in the architecture concepts.  Many of the ideas and capabilities behind microservices are already possible with the WCF frameworks for client and server creation.  There is one tenet about microservices that you can not do with WCF: run inside of a container.  Until now…   In this article, we’re going to take a look at running a simple WCF self-hosted service inside of a Docker container.

The architecture that we are going to assemble in this article is quite simple:  our self-hosted HTTP service will run inside of a Docker container on our workstation and we will be able to use a client on the same machine to connect through the container and interact with the service.  The following diagram illustrates the desired configuration:

Architecture of our sample

Architecture of our sample

WCF Services Run on Windows

WCF runs on the .NET framework, which means that it only runs on Windows.  Fortunately, we have Windows Server Core images available to us.  If we install Docker for Windows on Windows 10 or Windows Server 2016 with container support enabled, we can configure Docker to use Windows containers.  Right click on the Docker whale icon in the system tray and you can choose to “Switch to Windows Containers” to get started:

Switch to Windows Containers

Switch to Windows Containers

Lets open a command prompt and grab a copy of the Windows Server Core docker image to get started:

docker pull microsoft/windowsservercore

We will build our minimal set of WCF requirements on top of this image.

Our WCF Sample Code

Let’s build a simple service to add to a container and then a client to consume the service from the container.  I will start with a service library project that is almost identical to the default project template for a WCF Service Library.  I will simply change the GetDataUsingContract method to interpret the StringValue with a slightly different string:

We can then add a simple Windows Console application to the solution that will serve as the host of our service.  The Program class is simple and references the Service1 type from our ServiceLibrary project:

The app.config for this project needs to contain some information about the address, endpoint, and behaviors of our service.  Lets fill that out with some simple MetadataExchange and BasicHttpBinding:

Finally, we need a client that will connect to the service and interact with the IService1 service contract.  This is another Windows Console application.  This time we add a service reference to the project and point to the MyServiceLibrary project.  My solution looks like the following:

My Solution Explorer

My Solution Explorer

When I add the service, I right click on the WCFClientBasic project and choose “Add  – Service Reference” which brings up the following dialogue:

Add Service Reference

Add Service Reference

I clicked “Discover” and located the entry from MyServiceLibrary to add to the WCFClientBasic project.  With that reference added, I can write some simple client code to connect to the service and demonstrate some basic data interactions:

With that code in place, that simply creates a client connection to the Service and executes the GetData and GetDataUsingDataContract, we can run this sample client code in the Visual Studio debugger and verify that it works.

Deploying the WCF Host to Docker

I’ll start by creating a publish folder on disk inside of my solution. Next, I’ll take the simple host application and copy the EXEs, DLLs, and config files into a folder named bin within the publish folder.  I’ll then create a Dockerfile at the root of publish with this content:

This file directs Docker to add the WCF-HTTP Activation feature to Windows Server Core, and then copy our host content to the c:\app folder.  It exposes port 83, as was configured in our host’s app.config file earlier.  Finally, it launches the BasicHttpHost application.  We can build this Dockerfile into a Docker image by executing the docker build command like so:

docker build -t wcfhost:latest -t wcfhost:1 .

This creates an image called “wcfhost” with a version of 1 that is also tagged as the latest version.  This build step will take a few minutes for Windows to configure the WCF features inside the container.  Once complete, you can launch an instance of your host with this command:

docker run -itd --name host wcfhost

We can then inspect the container to determine the IP address of our service.  We can use a format string to grab the IP address directly from the container information:

docker inspect -f="{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" host

Copy that IP address into the app.config of the WCFClientBasic project and update the endpoint address from localhost:83 to your ip address (mine was 172.19.18.87).  You should then be able to run your WCFClientBasic and have it attach to the container, returning the expected text results in a console window:

Results from Docker

Results from Docker

Summary

We’ve shown how WCF services can be configured using the standard WindowsServerCore container image.  There are other Windows options and features that can be configured in this container, based on your service’s needs. The container architecture allows us to scale our service easily as well as deploy the same binaries and configuration that we run in development and staging into a production environment.

Is this something that you might use with your existing WCF services?

The WCF team is working on simplifying Docker integration with service creation and debugging.  We would like to hear from you about how you use WCF services and what you want in a containerized WCF solution.  Let us know your thoughts in the comment area below and we’ll follow up as we work to bring container support to WCF.


Viewing all articles
Browse latest Browse all 7144

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>