Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WCF Docker Containers #4876

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# https://docs.docker.com/engine/reference/builder/#dockerignore-file
# Exclude files not relevant to the build
# This helps to avoid unnecessarily sending large or sensitive files and directories to Docker daemon

# Ignore everything and use Docker volumes
*
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ syntax: glob
# Tool Runtime Dir
/[Tt]ools/
.dotnet/
.dotnet-linux/

# User-specific files
*.suo
Expand All @@ -14,6 +15,7 @@ syntax: glob

# Build results
artifacts/
artifacts-linux/
.idea/
[Dd]ebug/
[Dd]ebugPublic/
Expand Down Expand Up @@ -279,4 +281,4 @@ config.ps1

# Debug files
*.etl
*.dmp
*.dmp
9 changes: 9 additions & 0 deletions Docker/Client/Linux.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Linux Docker image - Host WCF Client
FROM mcr.microsoft.com/dotnet/sdk:6.0.300-focal-amd64

# Run commands:
# Setup environment variables
# Install Root certificate
# Run WCF Tests
CMD /wcf/src/System.Private.ServiceModel/tools/scripts/SetClientEnv-Linux.sh && /wcf/src/System.Private.ServiceModel/tools/scripts/InstallRootCertificate.sh --cert-file /tmp/wcfrootca.crt && /wcf/eng/common/cibuild.sh -configuration Release --prepareMachine --ci --test --integrationTest

12 changes: 12 additions & 0 deletions Docker/Client/Windows.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Windows Docker image - Host WCF Client
FROM mcr.microsoft.com/dotnet/framework/sdk:4.8

# Set Powershell as default Container shell
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"]

# Run commands:
# Setup environment variables
# Run WCF Tests
CMD C:\wcf\src\System.Private.ServiceModel\tools\scripts\SetClientEnv-Windows.cmd; C:\wcf\eng\common\cibuild.cmd -configuration Release -prepareMachine /p:Restore=true /p:Sign=false /p:Test=true /p:IntegrationTest=true /p:Pack=false /p:Publish=false;


19 changes: 19 additions & 0 deletions Docker/Service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Windows Docker image - Host WCF Service
FROM mcr.microsoft.com/dotnet/framework/wcf

# Open IIS Hosted ports
EXPOSE 80 808 443 44345

# Open Self Hosted ports
EXPOSE 8081 8083 8084 44285 809

# Set Powershell as default Container shell
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"]

# Set ENTRYPOINT to Powershell
# Keeps the Service Container always running
ENTRYPOINT ["powershell"]

# Container Startup command:
# Setup WCF IIS Hosted and Self Hosted Services, using Docker Volume at C:\wcf
CMD ./wcf/src/System.Private.ServiceModel/tools/scripts/SetupWcfIISHostedService.cmd 38 /p:"c:\wcf"; ./wcf/src/System.Private.ServiceModel/tools/scripts/StartWCFSelfHostedSvc.cmd; powershell
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
<add key="CrlFileLocation" value="c:\wcftest\test.crl"/>
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the reason for raising the supported runtime version to 4.8?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Building the CertificateGenerator tool using VS 2022 Developer Command Prompt requires to install .NET 4.5 SDK/Targeting Pack manually, I thought it would be nice to upgrade the runtime version and build the tool directly. This is what I get when using .NET 4.5:
Error MSB3644: The reference assemblies for .NETFramework,Version=v4.5 were not found. To resolve this, install the Developer Pack (SDK/Targeting Pack) for this framework version or retarget your application. You can download .NET Framework Developer Packs at https://aka.ms/msbuild/developerpacks

</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
<OutputType>Exe</OutputType>
<RootNamespace>CertificateGenerator</RootNamespace>
<AssemblyName>CertificateGenerator</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BouncyCastle.Crypto.dll" Version="1.8.1" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.2" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
Expand Down
7 changes: 7 additions & 0 deletions src/System.Private.ServiceModel/tools/scripts/BuildSource.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:: Build tools on Docker host machine.
:: This saves time during container startup and running tests (simply mount a volume for the build artifacts)

:: Build certifcate generator tool
call BuildCertUtil.cmd
:: Build Self Hosted service
call BuildWCFSelfHostedService.cmd
8 changes: 8 additions & 0 deletions src/System.Private.ServiceModel/tools/scripts/BuildTest.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
:: Build tests on Docker host machine.

:: Windows Release Build
call ..\..\..\..\eng\common\cibuild.cmd -configuration Release -prepareMachine /p:Root_Certificate_Installed=true /p:Client_Certificate_Installed=true /p:SSL_Available=true /p:Test=false




Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
echo off
setlocal
echo **********************************
echo Starting WCF Service on Docker
echo **********************************

:: Use this script to start docker container for WCF Services - IIS Hosted and Self Hosted

:: Variables
set _exitCode=0
set "ServiceImageTag=wcf:service"
set "ServiceContainerName=WCFServiceContainer"
set "ServiceHostName=wcfservicehost"

:: Check if docker is running
docker ps>nul 2>&1
if ERRORLEVEL 1 (
echo. & echo ERROR: Please make sure docker is running.
goto :Failure
)

:: Check if docker is using Windows Containers
CALL "C:\Program Files\Docker\Docker\DockerCli.exe" -SwitchWindowsEngine

:: Check if WCF service is already running
FOR /F "tokens=* USEBACKQ" %%F IN (`docker container inspect -f '{{.State.Status}}' %ServiceContainerName%`) DO (
if %%F == 'running' (
echo. & echo WCF Service container is already running.
goto :Done
))

:: Change directory to wcf folder
cd ../../../..

echo. & echo Building Docker image for WCF service

:: Building docker image.
docker build -f ./Docker/Service/Dockerfile -t %ServiceImageTag% .
if ERRORLEVEL 1 (
echo. & echo ERROR: Building docker image failed.
goto :Failure
)
echo. & echo Building image success..

:: Starting docker container from the image.
echo. & echo Starting WCF Service Container
:: Run docker container and mount current directory for wcf source as container volume - C:\wcf
docker run --name %ServiceContainerName% --rm -it -d -h %ServiceHostName% -v "%cd%":"C:\wcf" %ServiceImageTag%
if ERRORLEVEL 1 (
echo. & echo ERROR: Starting WCF service container failed.
goto :Failure
)

echo. & echo Started WCF Service Container.
:: Print service container IP address and host name
echo. & echo WCF Service Container IP address and Host name:
docker inspect --format="{{.NetworkSettings.Networks.nat.IPAddress}}" %ServiceContainerName%
echo %ServiceHostName%

exit /b

:Failure
echo. & echo Error...
set _exitCode=1

:Done
exit /b %_exitCode%
endlocal
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
echo off
setlocal
echo **********************************
echo Starting WCF Client on Docker
echo **********************************

:: Use this script to start docker Linux container for WCF Client

:: Variables
set _exitCode=0
set "TestContainerName=WCFTestContainerLinux"
set "ServiceContainerName=WCFServiceContainer"
set "ServiceHostName=wcfservicehost"

:: Check if docker is running
docker ps>nul 2>&1
if ERRORLEVEL 1 (
echo. & echo ERROR: Please make sure docker is running.
goto :Failure
)

echo. & echo Checking WCF service container status and IP address.

:: Switch to Windows Containers to check WCF Service status
START /B /WAIT "" "C:\Program Files\Docker\Docker\DockerCli.exe" -SwitchWindowsEngine

:: Check if WCF service is already running
docker container inspect -f '{{.State.Status}}' %ServiceContainerName%
if ERRORLEVEL 1 (
echo. & echo Warning: WCF Service container is not running.
CALL DockerStartWCFService.cmd
)

:: set ServiceUri
FOR /F "tokens=* USEBACKQ" %%F IN (`docker inspect --format="{{.NetworkSettings.Networks.nat.IPAddress}}" %ServiceContainerName%`) DO (
:: SET ServiceIPAddress=%%F
SET ServiceUri=%ServiceHostName%/WcfService38
)
echo %ServiceUri%

:: Switch to Linux Containers to run Linux tests
START /B /WAIT "" "C:\Program Files\Docker\Docker\DockerCli.exe" -SwitchLinuxEngine

:: Change directory to wcf src
cd ../../../..

echo. & echo Building Docker image for WCF client

:: Building docker image.
docker build -f ./Docker/Client/Linux.dockerfile --tag=wcf:client .
if ERRORLEVEL 1 (
echo. & echo ERROR: Building docker image failed.
goto :Failure
)
echo. & echo Building image success..

:: Starting docker container from the image.
echo. & echo Starting WCF client
:: run docker container and mount current directory for wcf source as container volume '/wcf'
:: mount volume '.dotnet-linux' CLI cache directory inside the container as '.dotnet'
:: mount volume 'artifacts-linux' inside the container as 'artifacts'
:: mount volumes 'artifacts/bin' and 'artifacts/obj' inside the container, since it contains the test assemblies
docker run --name %TestContainerName% --rm -it --memory=4g -v "%cd%":"/wcf" -v "%cd%/.dotnet-linux":"/wcf/.dotnet" -v "%cd%/artifacts-linux":"/wcf/artifacts" -v "%cd%/artifacts/bin":"/wcf/artifacts/bin" -v "%cd%/artifacts/obj":"/wcf/artifacts/obj" -e ServiceUri=%ServiceUri% wcf:client
if ERRORLEVEL 1 (
echo. & echo ERROR: Starting WCF client container failed.
goto :Failure
)

exit /b

:Failure
echo. & echo Error...
set _exitCode=1

:Done
exit /b %_exitCode%
endlocal
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
echo off
setlocal
echo **********************************
echo Starting WCF Client on Docker
echo **********************************

:: Use this script to start docker Windows container for WCF Client

:: Variables
set _exitCode=0
set "TestContainerName=WCFTestContainerWin"
set "ServiceContainerName=WCFServiceContainer"
set "ServiceHostName=wcfservicehost"

:: Check if docker is running
docker ps>nul 2>&1
if ERRORLEVEL 1 (
echo. & echo ERROR: Please make sure docker is running.
goto :Failure
)

echo. & echo Checking WCF service container status and IP address.

:: Switch to Windows Containers to check WCF Service status
START /B /WAIT "" "C:\Program Files\Docker\Docker\DockerCli.exe" -SwitchWindowsEngine

:: Check if WCF service is already running
docker container inspect -f '{{.State.Status}}' %ServiceContainerName%
if ERRORLEVEL 1 (
echo. & echo Warning: WCF Service container is not running.
CALL DockerStartWCFService.cmd
)

:: set ServiceUri
FOR /F "tokens=* USEBACKQ" %%F IN (`docker inspect --format="{{.NetworkSettings.Networks.nat.IPAddress}}" %ServiceContainerName%`) DO (
:: SET ServiceIPAddress=%%F
SET ServiceUri=%ServiceHostName%/WcfService38
)
echo %ServiceUri%

:: Change directory to wcf src
cd ../../../..

echo. & echo Building Docker image for WCF client

:: Building docker image.
docker build -f ./Docker/Client/Windows.dockerfile --tag=wcf:client .
if ERRORLEVEL 1 (
echo. & echo ERROR: Building docker image failed.
goto :Failure
)
echo. & echo Building image success..

:: Starting docker container from the image.

echo. & echo Starting WCF client
:: run docker container and mount current directory for wcf source as container volume C:\wcf
docker run --name %TestContainerName% --rm -it --memory=4g -v "%cd%":"C:\wcf" -e ServiceUri=%ServiceUri% wcf:client
if ERRORLEVEL 1 (
echo. & echo ERROR: Starting WCF client container failed.
goto :Failure
)

exit /b

:Failure
echo. & echo Error...
set _exitCode=1

:Done
exit /b %_exitCode%
endlocal
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@ acquire_certificate()

echo "Obtaining certificate from '$ServiceUri'"

# Need to make a call as the original user as we need to write to the cert store for the current
# user, not as root
echo "Making a call to '${__service_host}/TestHost.svc/RootCert' as user '$SUDO_USER'"
sudo -E -u $SUDO_USER $__curl_exe -o $__cafile "http://${__service_host}/TestHost.svc/RootCert?asPem=true"
# Need to make a call as the original user as we need to write to the cert store for the current user, not as root
# if $EUID = 0, user is 'root'
if [ "$EUID" -ne 0 ]; then
echo "Making a call to '${__service_host}/TestHost.svc/RootCert' as user '$SUDO_USER'"
sudo -E -u $SUDO_USER $__curl_exe -o $__cafile "http://${__service_host}/TestHost.svc/RootCert?asPem=true"
else
# Docker containers has no Sudo installed, by default it is running root user
echo "Making a call to '${ServiceUri}/TestHost.svc/RootCert' as root user"
$__curl_exe -o $__cafile "http://${ServiceUri}/TestHost.svc/RootCert?asPem=true"
fi

return $?
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Setup environment variables
export Windows_Authentication_Available=true
export SPN_Available=true
export Server_Domain_Joined=true
export Ambient_Credentials_Available=true
export Domain_Available=true
export Explicit_Credentials_Available=true
# Set username and password
#export ExplicitUserName=
#export ExplicitPassword=
export SSL_Available=true
export Root_Certificate_Installed=true
export Client_Certificate_Installed=true
export Peer_Certificate_Installed=true
#export NegotiateTestDomain=
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
:: Setup environment variables
setx Windows_Authentication_Available true
setx Digest_Authentication_Available true
setx Ambient_Credentials_Available true
setx SPN_Available true
setx NTLM_Available true
setx Server_Domain_Joined true
:: Set username and password
::setx ExplicitUserName
::setx ExplicitPassword
setx Domain_Available true
setx UPN_Available true
setx Root_Certificate_Installed true
setx Client_Certificate_Installed true
setx Peer_Certificate_Installed true
Loading