I had another "things work differently in containers" moment recently. One of the fun points of changing the approach to your deployments is that sometimes you have to look differently at how some core configuration issues too. And this seems like an issue others will encounter too:
A project I was working recenly on had a long-running background process which would occasionally get terminated unexpectedly. Running on the Sitecore CM server role, it was processing some data import - but we were seeing failures to complete the job. After a bit of debugging, it turned out that these terminations were coinciding with IIS choosing to recycle the worker process for the website, which pointed us towards the underlying cause being the default behaviour of IIS where it recycles a worker process every 29 hours...
(Why 29 hours? Apparently it's because it's the smallest prime number of hours after 24. So now you know...)
Anyway, most developers are used to configuring this sort of thing via the IIS Manager tool. Right-clicking your site's application pool gives an option for "Recycling":
If you don't want the automatic recycle, you can uncheck that first option, and you're good to go...
But if you're running your site in containers you don't have access to this UI. So what's the right approach to managing this if you're building your app for Docker and/or Kubernetes?
Under the surface, IIS keeps the data for .Net Apps in the
ApplicationHost.config
file. Under
<system.applicationHost/>
and
<applicationPools/>
there's an element for each app pool. That has an optional
<recycling/>
element which
can define the behaviour you want. By default your config file won't have this recycle config - so to go this way you need to add it yourself.
This is doable, but patching an XML config file that ships in a base image, as part of your docker build process is a bit of a pain to set up. Is there an easier way?
Well yes - there is: PowerShell can help you here.
PowerShell has a module called
WebAdministration
which
can help you manage settings in IIS. Once that's enabled you can use the
Set-ItemProperty
command to change the settings
of an app pool.
You want the change to be in effect every time your image is run, so you want to set this up in your Dockerfile for the relevant role(s). You can add something like:
RUN Import-Module WebAdministration; ` Set-ItemProperty "IIS:\AppPools\DefaultAppPool" -Name Recycling.periodicRestart.time -Value 0.00:00:00;
Note the trailing back-tick character on that
RUN
line - it's necessary to ensure that both of the commands here run in the same context.
Also note that the
-Name
parameter can be a bit fiddly about case - the capital
R
in
periodicRestart
seems to be required for certain PowerShell and Windows Server versions, according to some comments I've seen.
You can set the
-Value
here to whatever recycle timespan you want here. The format is
d.hh:mm:ss
and zero implies no automatic recycling.
And once that's in place you can rebuild your image and this behaviour will be in place. To check, you can connect to PowerShell in a container based on the image:
docker exec -it myproject_cm_1 powershell
And then once that session starts up, ask what the value of this setting is:
Import-Module WebAdministration Get-ItemProperty "IIS:\AppPools\DefaultAppPool" -Name Recycling.periodicRestart.time
That should return "zero" after the change above is applied:
And your container should no longer recycle itself...
↑ Back to top