WCF has always been a preferred framework for Service oriented applications until REST became popular. Even then WCF services are very relevant and widely used in the industry. Can we not create microservices using WCF? Should all the microservices follow REST principles only ? Not really.. WCF services can very well be deployed as Microservices and that’s exactly what we are going to learn in this post.
Prerequisites
- Windows 10 Professional/Enterprise edition
- Windows Server 2016
- On Windows 10, Install Docker for Windows
- Enable Container support (Windows 10/Windows Server 2016)
- Visual Studio 2015/2017 Community Edition
Getting started
Since the focus of this post is to understand how we can deploy a WCF service in windows containers, we will be using the default WCF service created using WCF project template. (I will be using Visual Studio 2017, however the same works with 2015 as well)
This post is just an extension to the samples and readme provided in the below Microsoft github’s repo. The sample app can be downloaded from Github at : https://github.com/Microsoft/wcf-docker-samples/tree/master/4.6.2/WcfBasicIISHost
- Clone the repo and open the solution in VS 2017/2015.
- Open the Dockerfile located at the root directory.
- If the Dockerfile is not visible in Visual Studio, right click on Solution -> Add existing item and select the dockerfile present in the root folder of the solution.
- Build the project, right click the
WcfServiceTest
project and publish. Create a new publish profile and publish into a folder within the root directory of the solution. (This is a very important step, as we would be copying the published website from the local machine to the container from this folder). I have published the website within a folder calledPublished
under the root directory. - Modify the dockerfile to reflect the paths properly. The dockerfile should look like the one below
# install WCF basic docker image FROM microsoft/wcf # Next, this Dockerfile creates a directory for your application RUN mkdir C:\WcfServiceTest # configure the new site in IIS. RUN powershell -NoProfile -Command \ Import-module IISAdministration; \ New-IISSite -Name "WcfServiceTest" -PhysicalPath C:\WcfServiceTest -BindingInformation "*:83:" # This instruction tells the container to listen on port 83. EXPOSE 83 # The final instruction copies the site you published earlier into the container. COPY /Published/ C:\WcfServiceTest
As the comments indicate, we are trying to create the image for our app using microsoft/wcf
image, we then create a new folder (wcfservicetest
)within the container, and then add a new site to the IIS – note that the WCF image is built on top of microsoft/iis
image, so we don’t have to install IIS – copy the contents of our published folder to the folder within the container (wcfservicetest
) and then expose the port83
for the host to access the same.
Build the docker image
Next is to build the actual image using this dockerfile. To build an image use the below command from the root directory of the application(where the dockerfile is also present)
docker build -t wcf-iis-host .
You should be seeing the below output from your powershell window
Sending build context to Docker daemon 29.76 MB Step 1/5 : FROM microsoft/wcf ---> a7bf2990ed31 Step 2/5 : RUN mkdir C:\WcfServiceTest ---> Using cache ---> 15b00b631be3 Step 3/5 : RUN powershell -NoProfile -Command Import-module IISAdministration; New-IISSite -Name "WcfServiceTest " -PhysicalPath C:\WcfServiceTest -BindingInformation "*:83:" ---> Using cache ---> cd352e934940 Step 4/5 : EXPOSE 83 ---> Using cache ---> 1d85bd85e4af Step 5/5 : COPY /Published/ C:\WcfServiceTest ---> Using cache ---> ae55c6487ba4 Successfully built ae55c6487ba4
Run the built docker image
Now that image is available, we can run it using the below command. The below command runs the container in detached mode and maps the container port 83 to host port 83.
docker run -d -p 83:83 --name wcf-iis-host wcf-iis-host
Accessing the service running within the container
As per Docker docs and Microsoft docker hub’s instructions, accessing the running container using localhost
is having issues (as of this writing) Hence to access the service we need to grab the IP address of the running container by using the below command,
docker inspect -f "{{.NetworkSettings.Networks.nat.IPAddress}}" wcf-iis-host
The last parameter is the container name that should match the name provided for --name
argument while running the container. My command returned the IP address 172.24.218.147
.
So to access the service WSDL, simply access http://172.24.218.147:83/Service1.svc and you should see the response as shown below:
Running the WCF Client
The solution also contains a WCF client to hit this service and get back the data. Modify the binding endpoints to point to the appropriate one. In my case the binding looks like below :
<client><endpoint address="http://172.24.218.147:83/service1.svc/Service1" binding ="basicHttpBinding" bindingConfiguration= "BasicHttpBinding_IService1" contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1"/> </client>
Running the client produces the below output :
As of this writing http/https/NetTCP with anonymous access endpoints are supported for WCF, with more support and features getting added in future.
Can confirm that this is still an issue: https://github.com/Microsoft/wcf-docker/issues/18
Thanks for the article, how would one do this when self-hosting in a Windows Service instead of IIS?
Hi Paul, AFAIK, self hosting in a windows service is not possible. However if you self host in a console app, it’s definitely possible to dockerize and run within windows containers. Every docker image should have an entry point defined which could be an exe or a web endpoint listening on a specific port that could keep the container alive. Since windows services are more of a background process, docker wouldn’t be aware of that process and container wouldn’t simply run. Short answer for self hosted WCF services are Console apps which can be run within windows containers.