Deploy your Sitecore Commerce XC 9.3 solution to Docker

Akshay Sura - Partner

5 May 2020

Share on social media

As I mentioned in my recent blog posts, Docker was built for Sitecore Commerce. The script I use for commerce deploys locally to Docker is similar to what I used to use for a local install when using Sitecore Commerce 9.2 and 9.1.

I modified the script a tiny bit to work with my Docker instances.

Please go through our previous blog posts on Docker for Sitecore Commerce: Dockerify your Sitecore 9.3 XP development environment - SSL, CM and Identity

Docker was built for Sitecore Commerce XC 9.3

Once your commerce solution is up and running you have to perform the following tasks to push your .NET Core app:

  • Build your Sitecore.Commerce.Engine.exe (console app with IIS bindings)
  • Build all the project references of Sitecore.Commerce.Engine project (DLL’s)
  • Gather the build output
  • While making a copy for Authoring, Minion, Ops and Shops, modify the AppSettings in the src\Sitecore.Commerce.Engine\wwwroot\config.json file. We need to modify the SiteTitle and EnvironmentName
  • Remove Kestrel related attributes SslPort, SslPfxPath and SslPfxPassword
  • Push the appropriate temp folder to the appropriate Docker data folder for Authoring, Minions, Ops, and Shops,
  • If Bootstrap flag is passed in, get the Token from the Identity server and Bootstrap the Commerce engine on the Ops role

NOTE: Be careful when you build the solution using dotnet publish as opposed to the Sitecore.Commerce.Engine project, we ran in to an odd issue and documented it in a blog post: Sitecore Commerce Build & Deployment Error - Could not load file or assembly System.Runtime.CompilerServices.Unsafe Version=4.0.4.1 and System.IO.Compression Version=4.2.0.0

Here are the AppSettings from the Docker\data\commerce-minions\wwwroot\wwwroot\config.json :

"AppSettings": { "SiteTitle": "CommerceMinions_FRIEND", "BootStrapFile": "Global", "DeploymentId": "Deployment01", "EnvironmentName": "BeMyFriendMinions", "EncryptionProtectionType": "Machine", "EncryptionCertificateHash": "Enter a valid certificate thumbprint for a PXF file. X-509 not supported yet", "EncryptionSID": "Enter a valid SID for a domain registered user", "EncryptionKeyStorageLocation": "c:\\Encryption-Keys\\", "SitecoreIdentityServerUrl": "https://identity.BeMyFriend.local", "AllowedOrigins": [ "https://bizfx.BeMyFriend.local", "http://cd.BeMyFriend.local", "https://cm.BeMyFriend.local", "https://localhost:4200" ], "AntiForgeryEnabled": false, "CommerceServicesHostPostfix": "", "UseHttpsInKestrel": "false" }

Here the copy of my script which I use multiple times daily and it works on my machine ;)

Param( [string]$identityServerHost = "identity.BeMyFriend.local", [switch]$Bootstrap, [switch]$SkipPublish, [string]$dockerDataRoot = "C:\code\BeMyFriend\Docker\data", [string[]] $engines = @("Authoring", "Minions", "Ops", "Shops"), [string]$CommerceOps = "commerce-ops.BeMyFriend.local", [string]$adminUser = "admin", [string]$adminPassword = "b", [string]$solutionFolder = "C:\code\BeMyFriend\Commerce", [string]$publishFolder = (Join-Path $solutionFolder "publishcode"), [string]$engineProjectPath = (Join-Path $solutionFolder "src\Sitecore.Commerce.Engine\Sitecore.Commerce.Engine.csproj") ) Function Start-CommerceEngineCompile ( [string] $basePublishPath = $(Join-Path $publishFolder "engine") ) { if (Test-Path $publishFolder) { Remove-Item -Path $publishFolder -Recurse -Force } Write-Host ("Compiling and Publishing Engine to {0}" -f $basePublishPath) -ForegroundColor Green dotnet publish $engineProjectPath -o $basePublishPath } Function Start-CommerceEnginePrepare ( [string] $basePublishPath = $(Join-Path $publishFolder "engine") ) { foreach ($engine in $engines) { Write-Host ("Customizing configuration values for {0}" -f $engine) -ForegroundColor Green $engineFullName = ("commerce-{0}" -f $engine) $engineFullName = $engineFullName.ToLower() $siteTitle = $("Commerce" + $engine + "_FRIEND") $environmentName = ("BeMyFriend{0}" -f $engine) $enginePath = Join-Path $publishFolder $engineFullName Copy-Item $basePublishPath $enginePath -Recurse -Force $pathToJson = $(Join-Path -Path $enginePath -ChildPath "wwwroot\config.json") $config = Get-Content $pathToJson -Raw | ConvertFrom-Json $appSettings = $config.AppSettings $appSettings.EnvironmentName = $environmentName $appSettings.SiteTitle = $siteTitle $appSettings = $appSettings| Select-Object * -ExcludeProperty SslPort, SslPfxPath, SslPfxPassword $config.AppSettings = $appSettings $config | ConvertTo-Json -Depth 10 -Compress | set-content $pathToJson } } Function Publish-CommerceEngine { Write-Host ("Deploying Commerce Engine") -ForegroundColor Green foreach ($engine in $engines) { $engineFullName = ("commerce-{0}" -f $engine) $engineFullName = $engineFullName.ToLower() $enginePath = ("{0}\{1}\*" -f $publishFolder,$engineFullName) $engineWebRoot = ("{0}\{1}\wwwroot" -f $dockerDataRoot, $engineFullName) Write-Host ("Copying to {0}" -f $engineWebRoot) -ForegroundColor Green if (Test-Path $engineWebRoot) { $deleteFiles = Join-Path $engineWebRoot "\*" Remove-Item -Path $deleteFiles -Recurse -Force -Exclude *.gitkeep } Copy-Item -Path "$enginePath" -Destination $engineWebRoot -Container -Recurse -Force } } Function Get-IdServerToken { $UrlIdentityServerGetToken = ("https://{0}/connect/token" -f $identityServerHost) $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" $headers.Add("Content-Type", 'application/x-www-form-urlencoded') $headers.Add("Accept", 'application/json') $body = @{ password = "$adminPassword" grant_type = 'password' username = ("sitecore\{0}" -f $adminUser) client_id = 'postman-api' scope = 'openid EngineAPI postman_api' } Write-Host "Getting Identity Token From Sitecore.IdentityServer" -ForegroundColor Green $response = Invoke-RestMethod $UrlIdentityServerGetToken -Method Post -Body $body -Headers $headers $sitecoreIdToken = "Bearer {0}" -f $response.access_token $global:sitecoreIdToken = $sitecoreIdToken Write-Host $global:sitecoreIdToken } Function BootStrapCommerceServices { $UrlCommerceShopsServicesBootstrap = ("https://{0}/commerceops/Bootstrap()" -f $CommerceOps) Write-Host "BootStrapping Commerce Services: $($urlCommerceShopsServicesBootstrap)" -ForegroundColor Green $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" $headers.Add("Authorization", $global:sitecoreIdToken) Invoke-RestMethod $UrlCommerceShopsServicesBootstrap -TimeoutSec 1200 -Method PUT -Headers $headers Write-Host "Commerce Services BootStrapping completed" -ForegroundColor Green } if (!($SkipPublish)) { Start-CommerceEngineCompile Start-CommerceEnginePrepare Publish-CommerceEngine } if ($Bootstrap) { Get-IdServerToken } if ($Bootstrap) { BootStrapCommerceServices }

If you have any questions, please get in touch with me. @akshaysura13 on Twitter or on Slack.


Sign up to our newsletter


Tags:


Share on social media

Akshay Sura

Akshay is a nine-time Sitecore MVP and a two-time Kontent.ai. In addition to his work as a solution architect, Akshay is also one of the founders of SUGCON North America 2015, SUGCON India 2018 & 2019, Unofficial Sitecore Training, and Sitecore Slack.

Akshay founded and continues to run the Sitecore Hackathon. As one of the founding partners of Konabos Consulting, Akshay will continue to work with clients to lead projects and mentor their existing teams.


Subscribe to newsletter