带有 Windows 容器的 Docker 在 tcp 服务上支持 wcf

Posted

技术标签:

【中文标题】带有 Windows 容器的 Docker 在 tcp 服务上支持 wcf【英文标题】:Docker with Windows container support wcf on tcp services 【发布时间】:2018-09-27 16:04:41 【问题描述】:

我有一个简单的测试 wcf 服务,net.tcp 与此配置绑定:

<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" />

我用这个 dockerfile 构建了一个基于 windows/wcf 镜像的 docker 镜像:

    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 构建命令:

docker build -t axesnetbws.image .

然后我使用以下命令运行容器:

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

之后我得到容器的 IP 地址:

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

然后我打开我的网络浏览器(Chrome)并输入地址http://&lt;uri_from_docker_inspect&gt;:83/Service1.svc?wsdl

我收到一个错误:

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

奇怪的是,如果我只是将站点复制到默认网站 (COPY ./inetpub/wwwroot/) 并调用 http://&lt;uri_from_docker_inspect_NO_PORT&gt;/Service1.svc?wsdl 它可以工作!那么在使用新网站或应用程序时会出现什么问题呢?

【问题讨论】:

解决在 docker 容器内运行的应用程序问题的最佳方法是启动新的服务器核心映像并在映像内运行 DOCKERFILE 命令,看看问题是否可重现。如果是,那么与对 docker 容器进行故障排除相比,故障排除将采用不同的方式 【参考方案1】:

我终于通过将网站转换为 Web 应用程序来实现它。刚刚在 EXPOSE 83 之前添加了这一行:

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

所以最终的 dockerfile 是:

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

【讨论】:

以上是关于带有 Windows 容器的 Docker 在 tcp 服务上支持 wcf的主要内容,如果未能解决你的问题,请参考以下文章

如何在容器上编辑 Docker 端口和参数? (使用适用于 Windows 的 Docker 桌面)[重复]

多台主机上的 Docker(Windows 和 Ubuntu)

如何在 Elasticbeanstalk 环境中运行的 docker 容器中承担 AWS 角色?

为 Docker 容器分配静态 IP

Docker 容器操作命令

用于 Windows 网络的 Docker