Patrice Cote
Patrice Cote

Reputation: 3716

Docker with Windows container support wcf on tcp services

I have a simple test wcf service with net.tcp binding with this config :

<system.serviceModel>
<services>
  <service name="WcfServiceWebApp.Service1">
    <endpoint binding="basicHttpBinding" contract="WcfServiceWebApp.IService1" />
    <endpoint address="" binding="netTcpBinding" contract="WcfServiceWebApp.IService1" bindingConfiguration="noSecurityBind"/>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:83/Service1.svc" />
      </baseAddresses>
    </host>
  </service>
</services>
<bindings>
  <netTcpBinding>
    <binding name="noSecurityBind" portSharingEnabled="false">
      <security mode="None" />
    </binding>
  </netTcpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
<protocolMapping>
    <add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>    
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

I build a docker image based on windows/wcf image with this dockerfile :

    FROM microsoft/wcf:4.7.1
# 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:"

RUN Import-Module WebAdministration; Set-ItemProperty "IIS:\\Sites\\WcfServiceTest" -name bindings -value (@{protocol='net.tcp';bindingInformation='808:*'},@{protocol='http';bindingInformation='*:83:'});
# This instruction tells the container to listen on port 83.
EXPOSE 83

COPY . C:\\WcfServiceTest

Docker build command :

docker build -t axesnetbws.image .

I then run the container with the command :

 docker run -d -p 83:83 --name testcontainer mytestimage

After that I get the IP address of the container with :

docker inspect --format="{{.NetworkSettings.Networks.nat.IPAddress}}" testcontainer 

Then I get on my web browser (Chrome) and enter the address http://<uri_from_docker_inspect>:83/Service1.svc?wsdl

I get an error :

Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Registered base address schemes are [http].
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Registered base address schemes are [http].

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 


[InvalidOperationException: Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Registered base address schemes are [http].]
   System.ServiceModel.ServiceHostBase.MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding, UriSchemeKeyedCollection baseAddresses) +16350098
   System.ServiceModel.Description.ConfigLoader.LoadServiceDescription(ServiceHostBase host, ServiceDescription description, ServiceElement serviceElement, Action`1 addBaseAddress, Boolean skipHost) +723
   System.ServiceModel.ServiceHostBase.LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, ServiceElement serviceSection) +99
   System.ServiceModel.ServiceHostBase.ApplyConfiguration() +205
   System.ServiceModel.ServiceHostBase.InitializeDescription(UriSchemeKeyedCollection baseAddresses) +203
   System.ServiceModel.ServiceHost..ctor(Type serviceType, Uri[] baseAddresses) +162
   System.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(Type serviceType, Uri[] baseAddresses) +42
   System.ServiceModel.HostingManager.CreateService(String normalizedVirtualPath, EventTraceActivity eventTraceActivity) +1756
   System.ServiceModel.HostingManager.ActivateService(ServiceActivationInfo serviceActivationInfo, EventTraceActivity eventTraceActivity) +65
   System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity) +733

[ServiceActivationException: The service '/Service1.svc' cannot be activated due to an exception during compilation.  The exception message is: Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Registered base address schemes are [http]..]
   System.Runtime.AsyncResult.End(IAsyncResult result) +609562
   System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +231
   System.Web.CallHandlerExecutionStep.InvokeEndHandler(IAsyncResult ar) +212
   System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +166

What's weird is that if I just copy the site in Default Web Site (COPY . /inetpub/wwwroot/) and call http://<uri_from_docker_inspect_NO_PORT>/Service1.svc?wsdl IT WORKS ! So what would be the problem when using a new website or application ?

Upvotes: 4

Views: 3134

Answers (1)

Patrice Cote
Patrice Cote

Reputation: 3716

I finally got it working by transforming the site to a web application. Just added this line before EXPOSE 83 :

RUN windows\system32\inetsrv\appcmd.exe set app 'WcfServiceTest/' /enabledProtocols:"http,net.tcp"

So the final dockerfile is :

FROM microsoft/wcf:4.7.1
ARG source
# 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:"

RUN Import-Module WebAdministration; Set-ItemProperty "IIS:\\Sites\\WcfServiceTest" -name bindings -value (@{protocol='net.tcp';bindingInformation='808:*'},@{protocol='http';bindingInformation='*:83:'});
RUN windows\system32\inetsrv\appcmd.exe set app 'WcfServiceTest/' /enabledProtocols:"http,net.tcp"
# This instruction tells the container to listen on port 83.
EXPOSE 83

COPY ${source:-obj/Docker/publish} c:\\WcfServiceTest

Upvotes: 4

Related Questions