Sitecore 10 with Docker – Create a solution from the scratch – Create solution and enable Sitecore Serialization

Create our Solution
Now we can start creating code and a solution structure.
We will cover how we can add code to our docker environment and serialize and deserialize items.
Create the Visual Studio Solution
We will start by creating a folder structure based on Helix as followed
- src
- Feature
- Foundation
- Project

Open visual Studio and create a blank solution in your root (I named mine “MyDockerExperience”)

We create new solution folders for Projet, Foundation and Feature

Visual Studio creates by default a folder for your solution. Move the items of this folder to your root and delete the empty folder. Your root folder should look something similar like the following

Create our first project
Now we will create our first project called “MyDockerExperience.Platform”


After adding configuration folder structure it should look like following

Create a deploy folder
In our docker folder we create subfolders deploy –> platform, which will be our local deployment target for our code

Create VS publishing profile
Now we are using the previously created folder as publishing target for our platform project.
Therefore we create a new folder publishing profile in Visual Studio


In settinga we switch to Debug as it is for our dev workstation

If we publish now we are deploying to our folder.
At the moment there will be just a bin folder, as we have not patched any configuration or added any files.

Mount deployment to docker
For now we just have a folder on our filesystem where our platform is published to, but this folder and files are currently never used in our docker instances.
To be able to code for our new solution we want that our published code is deployed to the CM & CD docker instance.
For that we will start mounting our deployment folder to the CD & CM instances.
We create a new variable in our .env file and point it to our deploy folder
LOCAL_DEPLOY_PATH=.\docker\deploy
Next we mount the folder to CD & CM by adding a new volume entry in the docker-compose.override.yml
volumes: - ${LOCAL_DEPLOY_PATH}\platform:C:\deploy
cm: image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cm:${VERSION:-latest} build: context: ./docker/build/cm args: BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cm:${SITECORE_VERSION} depends_on: - solution volumes: - ${LOCAL_DATA_PATH}\cm:C:\inetpub\wwwroot\App_Data\logs - ${LOCAL_DEPLOY_PATH}\platform:C:\deploy cd: image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cd:${VERSION:-latest} build: context: ./docker/build/cd args: BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cd:${SITECORE_VERSION} depends_on: - solution volumes: - ${LOCAL_DATA_PATH}\cd:C:\inetpub\wwwroot\App_Data\logs - ${LOCAL_DEPLOY_PATH}\platform:C:\deploy
This means now our local path is mounted to the path C:\deploy of CD & CM.
Anyway the current code is still not part of CM & CD website, which means it is not deployed to our website.
So the next step would be to move the deployed from the mounted folder to our website.
Deploy code from mounted folder to website
Sitecore thankfully provides the Sitecore Docker Tools, which are utilities which assist Sitecore developers in initializing and running containerized Sitecore environments.

We will use first of all the sitecore-docker-tools-assets image and create an entrypoint which calls a powershell command, which monitors our deployment folder on both instances.
If you want to know more about entrypoints you can visit: https://www.bmc.com/blogs/docker-cmd-vs-entrypoint/#:~:text=Docker%20ENTRYPOINT,with%20command%20line%20arguments%20stated.
In the .env file we use following parameters
SITECORE_TOOLS_REGISTRY=scr.sitecore.com/tools/ TOOLS_VERSION=10.2-1809
In the docker-compose.override.yml we add the new TOOLING Image and the entrypoint
cm: image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cm:${VERSION:-latest} build: context: ./docker/build/cm args: BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cm:${SITECORE_VERSION} SPE_IMAGE: ${SITECORE_MODULE_REGISTRY}sitecore-spe-assets:${SPE_VERSION} SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sitecore-sxa-xm1-assets:${SXA_VERSION} HEADLESS_SERVICES_IMAGE: ${SITECORE_MODULE_REGISTRY}sitecore-headless-services-xm1-assets:${HEADLESS_SERVICES_VERSION} MANAGEMENT_SERVICES_IMAGE: ${SITECORE_MODULE_REGISTRY}sitecore-management-services-xm1-assets:${MANAGEMENT_SERVICES_VERSION} TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION} volumes: - ${LOCAL_DEPLOY_PATH}\platform:C:\deploy - ${LOCAL_DATA_PATH}\cm:C:\inetpub\wwwroot\App_Data\logs entrypoint: powershell -Command "& C:\\tools\\entrypoints\\iis\\Development.ps1" cd: image: ${REGISTRY}${COMPOSE_PROJECT_NAME}-xm1-cd:${VERSION:-latest} build: context: ./docker/build/cd args: BASE_IMAGE: ${SITECORE_DOCKER_REGISTRY}sitecore-xm1-cd:${SITECORE_VERSION} SXA_IMAGE: ${SITECORE_MODULE_REGISTRY}sitecore-sxa-xm1-assets:${SXA_VERSION} HEADLESS_SERVICES_IMAGE: ${SITECORE_MODULE_REGISTRY}sitecore-headless-services-xm1-assets:${HEADLESS_SERVICES_VERSION} TOOLING_IMAGE: ${SITECORE_TOOLS_REGISTRY}sitecore-docker-tools-assets:${TOOLS_VERSION} depends_on: - solution volumes: - ${LOCAL_DEPLOY_PATH}\platform:C:\deploy - ${LOCAL_DATA_PATH}\cd:C:\inetpub\wwwroot\App_Data\logs entrypoint: powershell -Command "& C:\\tools\\entrypoints\\iis\\Development.ps1"
Even if a lot of examples are using just one backslash for the entrypoint (e.g. C:\tools\entrypoints\iis\Development.ps1) i faced some issues with that and it worked by using double backslashes (C:\\tools\\entrypoints\\iis\\Development.ps1)
Finally in our Dockefiles for CM & CD we include the tools.
ARG TOOLING_IMAGE FROM ${TOOLING_IMAGE} as tooling # Copy development tools and entrypoint COPY --from=tooling \tools\ \tools\
CD
# escape=` ARG BASE_IMAGE ARG SXA_IMAGE ARG TOOLING_IMAGE ARG HEADLESS_SERVICES_IMAGE ARG SOLUTION_IMAGE FROM ${SOLUTION_IMAGE} as solution FROM ${SXA_IMAGE} as sxa FROM ${HEADLESS_SERVICES_IMAGE} AS headless_services FROM ${TOOLING_IMAGE} as tooling FROM ${BASE_IMAGE} SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] # Copy development tools and entrypoint COPY --from=tooling \tools\ \tools\ WORKDIR C:\inetpub\wwwroot # Add SXA module COPY --from=sxa \module\cd\content .\ COPY --from=sxa \module\tools \module\tools RUN C:\module\tools\Initialize-Content.ps1 -TargetPath .\; ` Remove-Item -Path C:\module -Recurse -Force; # Copy and init the JSS / Headless Services Module COPY --from=headless_services C:\module\cd\content C:\inetpub\wwwroot COPY --from=headless_services C:\module\tools C:\module\tools RUN C:\module\tools\Initialize-Content.ps1 -TargetPath C:\inetpub\wwwroot; ` Remove-Item -Path C:\module -Recurse -Force;
CM
# escape=` ARG BASE_IMAGE ARG SXA_IMAGE ARG SPE_IMAGE ARG MANAGEMENT_SERVICES_IMAGE ARG HEADLESS_SERVICES_IMAGE ARG TOOLING_IMAGE ARG SOLUTION_IMAGE FROM ${SOLUTION_IMAGE} as solution FROM ${SPE_IMAGE} as spe FROM ${SXA_IMAGE} as sxa FROM ${HEADLESS_SERVICES_IMAGE} AS headless_services FROM ${MANAGEMENT_SERVICES_IMAGE} AS management_services FROM ${TOOLING_IMAGE} as tooling FROM ${BASE_IMAGE} # Copy development tools and entrypoint COPY --from=tooling \tools\ \tools\ WORKDIR C:\inetpub\wwwroot SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] COPY --from=spe \module\cm\content .\ COPY --from=sxa \module\cm\content .\ COPY --from=sxa \module\tools \module\tools RUN C:\module\tools\Initialize-Content.ps1 -TargetPath .\; ` Remove-Item -Path C:\module -Recurse -Force; # Copy the Sitecore Management Services Module COPY --from=management_services C:\module\cm\content C:\inetpub\wwwroot # Copy and init the JSS / Headless Services Module COPY --from=headless_services C:\module\cm\content C:\inetpub\wwwroot COPY --from=headless_services C:\module\tools C:\module\tools RUN C:\module\tools\Initialize-Content.ps1 -TargetPath C:\inetpub\wwwroot; ` Remove-Item -Path C:\module -Recurse -Force;
Let’s have a look in the entrypoint script which we are calling when initializing the container. https://github.com/Sitecore/docker-tools/blob/main/image/src/entrypoints/iis/Development.ps1
This script is calling another script to open a file watcher handing over our mounted file path and the IIS Destination as parameter.

The called watcher script https://github.com/Sitecore/docker-tools/blob/main/image/src/scripts/Watch-Directory.ps1 identifies changes in the deploy folder and keeps the iis wwwroot folder in sync.

docker-compose down ./clean.ps1 docker-compose build Run docker-compose up -d
Deploy the first test page
After we successfully set up everything we want to make sure that our deployment works.
Let’s just create a simple Hello world HTML page and publish it from visual studio.



Add Sitecore Serialization to the docker environment
Previously we installed the managed services and connected via Sitecore CLI.
Now we want to serialize our first item. For the first serialization we will use the home item.
Therefore we edit the sitecore.json file in the root of our our solution folder. We add following entry
"modules": [ "src/*/*/*.module.json" ]
This is pointing to all folders 2 level under src.
Note: Remember we are setting up a solution based on helix, which means src/Layer/Projectname/*.module.json
Let’s go to the Project layer and just create a folder “Example”

In this folder we add an example.module.json file and add following content
{ "namespace": "ExampleNamespace", "items": { "includes": [ { "name": "home", "path": "/sitecore/content/home" } ] } }
In PowerShell we call
dotnet sitecore ser info
Result

Now we serialize items to disk by calling
dotnet sitecore ser pull
Result

In our example folder we have now our serialized home item as yml file


Let’s open the home.yml and make some changes which we will sync with our environment (do not do this in normal development – it’s just for example reasons).
We will change the description too “Welcome to my docker experience”

In Powershell we call
dotnet sitecore ser push


By calling
dotnet sitecore ser watch
we can sync changes automatically to our file system.
In the next part we will add the ASP.NET Rendering Host and configure SXA-JSS to work with the rendering host