Finally! AMIRITE? Now that we’ve spun our solr and sql containers up, it’s time to move to the big guns: The CM Server. I’m not going to cover the CD Server, as it’s fairly similar. XP topology is also not very far deviant from the concepts you’ve conquered so far. Let’s get to it. The good news is, we’ve create all the base images for the CM image. Woot! Let’s look at that Dockerfile though, and see whats’ going on. It’s a bit to take in:

# escape=`
ARG BASE_IMAGE
ARG ASSETS_IMAGE

FROM $ASSETS_IMAGE as assets
FROM $BASE_IMAGE as build

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

ARG ASSETS_USE_WDP
ARG SC_ROLE_CONFIG_DIRECTORY

COPY --from=assets ["${ASSETS_USE_WDP}", "C:\\temp\\packages\\"]

# expand selected wdp and copy to install into the webroot
RUN Expand-Archive -Path 'C:\\temp\\packages\\*.zip' -DestinationPath 'C:\\temp'; `
    Copy-Item -Path 'C:\\temp\\Content\\Website\\*' -Destination 'C:\\inetpub\\wwwroot' -Recurse -Force;

# copy patches
COPY --from=assets ["c:\\patches\\", "c:\\patches\\"]

# apply patches
RUN Get-ChildItem -Path 'C:\\patches' -Exclude ".gitkeep" | Copy-Item -Destination 'C:\\inetpub\\wwwroot' -Recurse -Force;

# configure wwwroot
RUN Copy-Item -Path 'C:\\inetpub\\wwwroot\\App_Config\\Include\\Examples\\Sitecore.Owin.Authentication.IdentityServer.Disabler.config.example' -Destination 'C:\\inetpub\\wwwroot\\App_Config\\Include\\Sitecore.Owin.Authentication.IdentityServer.Disabler.config'; `
    Copy-Item -Path 'C:\\inetpub\\wwwroot\\App_Config\\Include\\Examples\\Sitecore.LoadBalancing.config.example' -Destination 'C:\\inetpub\\wwwroot\\App_Config\\Include\\Sitecore.LoadBalancing.config'; `
    New-Item -Path 'C:\\inetpub\\wwwroot\\upload' -ItemType Directory | Out-Null; `
    New-Item -Path 'C:\\inetpub\\wwwroot\\sitecore\\shell\\override' -ItemType Directory | Out-Null; `
    Remove-Item -Path 'C:\\inetpub\\wwwroot\\App_Data\\logs' -Force -Recurse;

# copy tools and transforms
COPY --from=assets ["C:\\install\\tools\\", "C:\\inetpub\\wwwroot\\temp\\install\\tools\\"]
COPY ${SC_ROLE_CONFIG_DIRECTORY} C:\\inetpub\\wwwroot\\

# find transform files and do transformation
RUN $xdts = (Get-ChildItem -Path 'C:\\inetpub\\wwwroot\\*.config.xdt'), (Get-ChildItem -Path 'C:\\inetpub\\wwwroot\\App_Config\\*.config.xdt' -Recurse); `
    $xdts | ForEach-Object { & 'C:\\inetpub\\wwwroot\\temp\\install\\tools\\scripts\\Invoke-XdtTransform.ps1' -Path $_.FullName.Replace('.xdt', '') -XdtPath $_.FullName -XdtDllPath 'C:\\inetpub\\wwwroot\\temp\\install\\tools\\bin\\Microsoft.Web.XmlTransform.dll'; }; `
    $xdts | ForEach-Object { Remove-Item -Path $_.FullName; };

# add config patches
COPY .\config\*.config C:\\inetpub\\wwwroot\\App_Config\\Include\\

# add installers
COPY --from=assets ["C:\\install\\setup\\", "C:\\inetpub\\wwwroot\\temp\\install\\setup\\"]

FROM $BASE_IMAGE

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

ARG SC_ROLE_DEFINE

COPY --from=build ["C:\\inetpub\\wwwroot\\", "C:\\inetpub\\wwwroot\\"]

RUN $env:INSTALL_TEMP = 'C:\\inetpub\\wwwroot\\temp\\install'; `
    $env:IIS_SITE_PATH = 'IIS:\Sites\Default Web Site'; `
    $env:IIS_SITE_HOMEDIR_PATH = 'C:\\inetpub\\wwwroot'; `
    $env:IIS_APPPOOL_IDENTITY = 'IIS AppPool\DefaultAppPool'; `
    # install dependencies
    Start-Process msiexec.exe -ArgumentList '/i', (Join-Path $env:INSTALL_TEMP '\\setup\\urlrewrite.msi'), '/quiet', '/norestart' -NoNewWindow -Wait; `
    Start-Process (Join-Path $env:INSTALL_TEMP '\\setup\\vc_redist.exe') -ArgumentList '/install', '/passive', '/norestart' -NoNewWindow -Wait; `
    # install tools
    Copy-Item -Path (Join-Path $env:INSTALL_TEMP '\\tools') -Destination 'C:\\tools' -Recurse -Force; `
    setx /M PATH $($env:PATH + ';C:\tools\scripts;C:\tools\bin') | Out-Null; `
    # configure Windows to disable DNS caching
    Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name 'ServerPriorityTimeLimit' -Value 0 -Type DWord; `
    # configure app pool group memberships
    Add-LocalGroupMember -Group 'Performance Monitor Users' -Member $env:IIS_APPPOOL_IDENTITY; `
    # configure app pool filesystem permissions
    $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($env:IIS_APPPOOL_IDENTITY, 'FullControl', @('ContainerInherit', 'ObjectInherit'), 'None', 'Allow'); `
    $acl = Get-Acl -Path $env:IIS_SITE_HOMEDIR_PATH; `
    $acl.SetAccessRule($rule); `
    $acl | Set-Acl -Path $env:IIS_SITE_HOMEDIR_PATH; `
    # configure role
    Import-Module WebAdministration; `
    Set-WebConfigurationProperty -PSPath $env:IIS_SITE_PATH -Filter '/appSettings/add[@key=\"role:define\"]' -Name 'value' -Value $env:SC_ROLE_DEFINE; `
    # delete temporary files
    Remove-Item -Path $env:INSTALL_TEMP -Force -Recurse;

So woof. There’s a lot to have in there. One thing you WON’T notice is SIF. These Dockerfiles are sans-SIF (like the font, right?) which, honestly is just a reduction of complexity and a pretty good idea, if you ask me. With this Dockerfile, let’s setup our instance of Sitecore!

docker image build --build-arg BASE_IMAGE=mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-1903 --build-arg ASSETS_IMAGE=sitecore-assets:9.2.0-nanoserver-1903 --build-arg ASSETS_USE_WDP='C:\\packages\\Sitecore 9.2.0 rev. 002893 (XM) (OnPrem)_cm.scwdp.zip' --build-arg SC_ROLE_CONFIG_DIRECTORY='\\config\\cm' --build-arg SC_ROLE_DEFINE='ContentManagement, Indexing' --isolation 'hyperv' --tag sitecore-xm-cm:9.2.0-windowsservercore-1903 .\windows\9.2.x\sitecore-xm\

This looks a little more like Sitecore. We see the path to the WDP (which is now in the Assets Image. We see our config to change the role (CM vs CD here) and we see the Role Define which will be used to transform the web.config as it moves into the Image. Here’s our new Image list:

This feels fresh.

Let’s go ahead and spin our container up and check it out:

docker run -d --publish 44000:80 --mount type=bind,source=C:/Dev/docker/sitecore/dummy/cm,target=C:/inetpub/wwwroot/App_Data/logs --mount type=bind,source=C:/Dev/docker/sitecore/dummy,target=C:/license --name sitecore_cm_920 sitecore-xm-cm:9.2.0-windowsservercore-1903

A quick thing to point out here: For simplicity, the license file is kept OUTSIDE the container, which means you’re going to need a secondary mount. That’s fine, you can have as many as you want to. Just make sure you license file is in the source folder.

Let’s run it! Open up your browser and visit http://localhost:44000 ahhhh what. It isn’t working???

Well this isn’t good. But it isn’t unexpected, either.

Unfortunately, containers a, by nature, isolated. That’s cool though, we can fix that. What we need to do is, is create a network for them to talk over. If you run the following command, you’ll see what networks are there out of the box:

docker network ls
Out of the box networks

We see four out of the box. We could attempt to attach our containers directly to the ‘nat’ network, but that wouldn’t entirely fix our issue. We really want to be able to name our containers on the network. That’s pretty easy once we have a network. So let’s make one and call it something logical:

docker network create -d nat sc_920

All that does is make a new network of type ‘nat’, and name it. We should see this now in our network list:

Oh hi there, new network

Cool cool cool. Let’s put our containers on that network now:

docker network connect --alias sql sc_920 sql_xm_920
docker network connect --alias solr sc_920 solr_xm_920
docker network connect --alias cm sc_920 sitecore_cm_920

The important thing here comes in the alias option. We’re able to name the container on the network, and when we request http://solr:8983, it’ll find our solr_xm_920 container. Pretty neat? Let’s refresh that browser:

SUCCESS! We now have Sitecore running in a docker container, connected to solr in a docker container as well as sql in a docker container. All running in an isolated network. Nice work!

Can we make this easier? It’s a little laborious spinning all the containers up, adding to network, validating the shares, etc. Let’s call our friend Docker Compose for some assistance. He’s hanging out in Part 9: Compose all the Things.

The TL;DR Code

#build our image
docker image build --build-arg BASE_IMAGE=mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-1903 --build-arg ASSETS_IMAGE=sitecore-assets:9.2.0-nanoserver-1903 --build-arg ASSETS_USE_WDP='C:\\packages\\Sitecore 9.2.0 rev. 002893 (XM) (OnPrem)_cm.scwdp.zip' --build-arg SC_ROLE_CONFIG_DIRECTORY='\\config\\cm' --build-arg SC_ROLE_DEFINE='ContentManagement, Indexing' --isolation 'hyperv' --tag sitecore-xm-cm:9.2.0-windowsservercore-1903 .\windows\9.2.x\sitecore-xm\
#create the container
docker run -d --publish 44000:80 --mount type=bind,source=C:/Dev/docker/sitecore/dummy/cm,target=C:/inetpub/wwwroot/App_Data/logs --mount type=bind,source=C:/Dev/docker/sitecore/dummy,target=C:/license --name sitecore_cm_920 sitecore-xm-cm:9.2.0-windowsservercore-1903
#create a network
docker network create -d nat sc_920
#add containers to the network
docker network connect --alias sql sc_920 sql_xm_920
docker network connect --alias solr sc_920 solr_xm_920
docker network connect --alias cm sc_920 sitecore_cm_920

This is a post in the “Yet Another Sitecore Docker Series.” Other Posts include


Facebooktwitterredditlinkedinmail Facebooktwitterredditlinkedinmail