﻿![]()

#### 

Working on Sitecore projects hosted in Docker or in Kubernetes, sometimes we need to add custom code or config changes to the Identity server, XConnect, Marketing Automation, etc. This article describes the approach to achieve that, which is common and applies to all Sitecore roles.

During the last project, which is a corporate website, I had the need to add a config with a custom Client configuration to the Identity server. This client configuration allows you to log in to Sitecore through Sitecore CLI using a secret token. That is useful when you need to build CI/CD processes and you need to run serialization/publish/index rebuild remotely. So that is a good example to explore.

First of all, we need to create a Class Library project within our solution that will contain our custom, identity server-related, changes. I have called this project **Corporate.Environment.Identity**

**![](https://www.brimit.com/-/media/images/blog/deploy-config-changes-into-sitecore/image2.png?h=403&amp;w=700&amp;hash=1084AB11390E1D756D37688A06548EE1)**

All custom configs need to be placed in the Config folder. I have added only one file **Sitecore.IdentityServer.Corporate.xml** with the following content:

| &lt;?xml version="1.0" encoding="utf-8"?&gt;<br>
            &lt;Settings&gt;<br>
             &lt;Sitecore&gt;<br>
              &lt;IdentityServer&gt;<br>
               &lt;Clients&gt;<br>
                &lt;!-- used to authenticate servers with client id and client secret --&gt;<br>
                &lt;CliServerClient&gt;<br>
                 &lt;ClientId&gt;Corporate\_CI&lt;/ClientId&gt;<br>
                 &lt;ClientName&gt;Corporate\_CI&lt;/ClientName&gt;<br>
                 &lt;AccessTokenType&gt;0&lt;/AccessTokenType&gt;<br>
                 &lt;AccessTokenLifetimeInSeconds&gt;3600&lt;/AccessTokenLifetimeInSeconds&gt;<br>
                 &lt;IdentityTokenLifetimeInSeconds&gt;3600&lt;/IdentityTokenLifetimeInSeconds&gt;<br>
                 &lt;RequireClientSecret&gt;true&lt;/RequireClientSecret&gt;<br>
                 &lt;AllowOfflineAccess&gt;false&lt;/AllowOfflineAccess&gt;<br>
                 &lt;AllowedGrantTypes&gt;<br>
            &lt;!-- client\_credentials authenticates with client ID and client secret which is good for CI, tools, etc. However, it's not tied to a USER, it's tied to a client ID.--&gt;<br>
                  &lt;AllowedGrantType1&gt;client\_credentials&lt;/AllowedGrantType1&gt;<br>
                 &lt;/AllowedGrantTypes&gt;<br>
                 &lt;ClientSecrets&gt;<br>
                  &lt;ClientSecret1&gt;260CA22A3F9R40498DEA074C117DAFB8&lt;/ClientSecret1&gt;<br>
                 &lt;/ClientSecrets&gt;<br>
                 &lt;AllowedScopes&gt;<br>
                  &lt;!-- this is required even if not a 'user' for Sitecore to like us --&gt;<br>
                  &lt;AllowedScope3&gt;sitecore.profile.api&lt;/AllowedScope3&gt;<br>
                 &lt;/AllowedScopes&gt;<br>
                &lt;/CliServerClient&gt;<br>
               &lt;/Clients&gt;<br>
              &lt;/IdentityServer&gt;<br>
             &lt;/Sitecore&gt;<br>
            &lt;/Settings&gt; |
| --- |

The **ClientId** and **ClientSecret1** will be used to log in to Sitecore during the CI/CD process.

Since we don’t need anything else, we are ready to switch to updating our docker images.

First of all, we need to add a build command in our solution Dockerfile and copy build artifacts to the image:

| # escape=`<br>
            ARG BUILD\_IMAGE<br>
            <br>
            FROM ${BUILD\_IMAGE} AS nuget-prep<br>
            SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]<br>
            # Gather only artifacts necessary for NuGet restore, retaining directory structure<br>
            COPY \*.sln nuget.config Directory.Build.targets Packages.props /nuget/<br>
            COPY src/ /temp/<br>
            RUN Invoke-Expression 'robocopy C:/temp C:/nuget/src /s /ndl /njh /njs \*.csproj \*.scproj packages.config'<br>
            <br>
            FROM ${BUILD\_IMAGE} AS builder<br>
            ARG BUILD\_CONFIGURATION<br>
            <br>
            SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]<br>
            WORKDIR /build<br>
            <br>
            # Copy prepped NuGet artifacts, and restore as a distinct layer to take advantage of caching.<br>
            COPY --from=nuget-prep ./nuget ./<br>
            <br>
            RUN nuget restore -Verbosity quiet<br>
            <br>
            # Copy remaining source code<br>
            COPY src/ ./src/<br>
            <br>
            # Copy transforms, retaining directory structure<br>
            RUN Invoke-Expression 'robocopy /build/src /build/transforms /s /ndl /njh /njs \*.xdt'<br>
            <br>
            # Build the Sitecore main platform artifacts<br>
            RUN msbuild .\src\Environment\platform\Corporate.Environment.Platform.csproj /p:Configuration=$env:BUILD\_CONFIGURATION /p:DeployOnBuild=True /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:PublishUrl=/build/sitecore<br>
            RUN msbuild .\src\Environment\identity\Corporate.Environment.Identity.csproj /p:Configuration=$env:BUILD\_CONFIGURATION <br>
             /p:DeployOnBuild=True /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:PublishUrl=/build/identity<br>
            <br>
            # Build the rendering host<br>
            WORKDIR /build/src/Project/Corporate/rendering/<br>
            RUN dotnet publish -c $env:BUILD\_CONFIGURATION -o /build/rendering --no-restore<br>
            <br>
            FROM mcr.microsoft.com/windows/nanoserver:1809<br>
            WORKDIR /artifacts<br>
            # Copy final build artifacts<br>
            COPY --from=builder /build/sitecore ./sitecore/<br>
            COPY --from=builder /build/transforms ./transforms/<br>
            COPY --from=builder /build/rendering ./rendering/<br>
            COPY --from=builder /build/identity/Config ./identity/Config |
| --- |

Once our solution image contains the required artifacts, we need to update our **docker-compose.override.yml** to pass the solution image to the identity server build:

| # Use our retagged Identity Server image.<br>
             # Configure for a mounted license file instead of using SITECORE\_LICENSE.<br>
             id:<br>
             image: ${REGISTRY}${COMPOSE\_PROJECT\_NAME}-id:${VERSION:-latest}<br>
             build:<br>
             context: ./docker/build/id<br>
             args:<br>
             PARENT\_IMAGE: ${SITECORE\_DOCKER\_REGISTRY}sitecore-id:${SITECORE\_VERSION} <br>
             SOLUTION\_IMAGE: ${REGISTRY}${COMPOSE\_PROJECT\_NAME}-solution:${VERSION:-latest}<br>
             depends\_on:<br>
             - solution<br>
             volumes:<br>
             - ${HOST\_LICENSE\_FOLDER}:c:\license<br>
             environment:<br>
             SITECORE\_LICENSE\_LOCATION: c:\license\license.xml |
| --- |

Then we need to update the identity server build docker file itself to copy config from solution image to the identity one:

![](https://www.brimit.com/-/media/images/blog/deploy-config-changes-into-sitecore/image3.png?h=237&amp;w=700&amp;hash=340F63CD3A0E90A2B5F123D5F954E442)

| | # escape=`<br>
                        <br>
                        ARG PARENT\_IMAGE<br>
                        ARG SOLUTION\_IMAGE<br>
                        <br>
                        FROM ${SOLUTION\_IMAGE} as solution<br>
                        FROM ${PARENT\_IMAGE}<br>
                        <br>
                        SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]<br>
                        <br>
                        WORKDIR C:\Identity<br>
                        <br>
                        # Copy identity artifacts<br>
                        COPY --from=solution /artifacts/identity/ ./<br>
                        <br>
                        ENTRYPOINT ["dotnet", "Sitecore.IdentityServer.Host.dll"] |<br>| --- | |
| --- |

After the next docker-compose build all new configs will be deployed to the docker. It allows us to use Sitecore CLI within CI/CD processes. You can find the Powershell script to run Sitecore Serialization sync below:

| function Arg { param([Parameter()][string]$Parameter) return $Parameter }<br>
            <br>
            $idHost= Arg '$(ID\_HOST)';<br>
            $cmHost= Arg '$(CM\_HOST)';<br>
            $clientSecret= Arg '$(ID\_SERVER\_CORPORATE\_CLIENT\_SECRET)';<br>
            <br>
            # Add nuget source & install Sitecore CLI<br>
             Write-Host "Installing Sitecore CLI"<br>
             dotnet nuget add source $(SITECORE\_PUBLIC\_NUGET\_FEED) --name "Sitecore-Public-Nuget-Feed"<br>
             dotnet tool install --add-source=$(SITECORE\_PUBLIC\_NUGET\_FEED) --version 3.0.0 sitecore.cli<br>
             <br>
             dotnet tool restore<br>
            <br>
             # Login to ID Server<br>
             Write-Host "Logging into ID Server"<br>
             dotnet sitecore login --client-credentials true --auth https://$idHost --cm https://$cmHost --allow-write true --client-id "Camao\_CI" --client-secret "$clientSecret"<br>
             <br>
             # Deserialize Content<br>
             Write-Host "Push Content"<br>
             dotnet sitecore ser push<br>
             <br>
             # Publish Database<br>
             Write-Host "Publish Database"<br>
             dotnet sitecore publish |
| --- |

###### Author

[!\[artsiom-photo\](https://www.brimit.com/-/jssmedia/feature/blogs/authors/artsiom-200.jpg?h=202&amp;iar=0&amp;w=200&amp;hash=41797D2540DF6EB6FDF558360F6F62B8)
Artsem Prashkovich
Sitecore MVP/ Solution Architect](https://www.brimit.com/blog/author?authors=Artsem%20Prashkovich)

###### More By Categories

[#E-commerce](https://www.brimit.com/blog?categories=#E-commerce)[#How-to](https://www.brimit.com/blog?categories=#How-to)[#Guides](https://www.brimit.com/blog?categories=#Guides)[Tech Talks](https://www.brimit.com/blog?categories=Tech%20Talks)[#OrderCloud](https://www.brimit.com/blog?categories=#OrderCloud)

###### More by Platform

[Data and AI](https://www.brimit.com/blog?platforms=Data%20and%20AI)[DXP](https://www.brimit.com/blog?platforms=DXP)[E-commerce](https://www.brimit.com/blog?platforms=E-commerce)[Internet of Things](https://www.brimit.com/blog?platforms=Internet%20of%20Things)[Sales and marketing automation](https://www.brimit.com/blog?platforms=Sales%20and%20marketing%20automation)

#### More on Sitecore

[!\[How Vercel Will Help You Save Effort When Deploying Sophisticated Sitecore Projects\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2024/vercel_cover-image.png)
#Guides#How-toDXPE-commerce
##### How Vercel Will Help You Save Effort When Deploying Sophisticated Sitecore Projects
Optimize and accelerate the development and deployment of complex multisite Sitecore projects.
Alexei Vershalovich on July 17, 2024](https://www.brimit.com/blog/how-vercel-will-help-you-save-effort-when-deploying-sophisticated-sitecore-projects)

[!\[Training Up Tomorrow's Sitecore MVPs: a Mentoring Success Story\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2023/sitecore-mentoring---cover-image.png)
#How-toDXP
##### Training Up Tomorrow's Sitecore MVPs: a Mentoring Success Story
How to participate in the Sitecore Mentor program and help younger colleagues jump-start a career in Sitecore development.
Sergey Baranov on October 2, 2023](https://www.brimit.com/blog/training-up-tomorrows-sitecore-mvps)

[!\[Going Headless. Part 2: When a Headless CMS Is Your Best Bet (if you have Sitecore)\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2022/headless/adobestock_456986731.jpg)
#How-toDXPE-commerce
##### Going Headless. Part 2: When a Headless CMS Is Your Best Bet (if you have Sitecore)
Discover how a headless CMS can benefit organizations that use Sitecore.
Daniil Raschupkin, Palina Trokhautsava on September 15, 2022](https://www.brimit.com/blog/going-headless-part-2-when-a-headless-cms-is-your-best-bet-if-you-have-sitecore)

![](https://bat.bing.net/action/0?ti=187017043&amp;tm=gtm002&amp;Ver=2&amp;mid=4ab2473b-b148-4945-bfe5-c4d636f69928&amp;bo=2&amp;gtm_tag_source=1&amp;pi=0&amp;lg=en-US&amp;sw=800&amp;sh=600&amp;sc=24&amp;nwd=1&amp;tl=Deploying%20config%20changes%20into%20Sitecore%20roles%20hosted%20in%20Docker%20or%20Kubernetes&amp;kw=Kubernetes,%20Sitecore,%20Docker,%20Debug,%20Powershell&amp;p=https%3A%2F%2Fwww.brimit.com%2Fblog%2Fdeploying-config-changes-into-sitecore-roles-hosted-in-docker-or-kubernetes&amp;r=&amp;lt=282&amp;evt=pageLoad&amp;sv=2&amp;asc=D&amp;cdb=AQAY&amp;rn=865203)