0

Updating SQL Server container memory limits on the fly

When running multiple SQL Server containers on a Docker host we should always be setting CPU and Memory limits for each container (see the flags for memory and cpus here). This helps prevent the whole noisy neighbour situation, where one container takes all the host’s resources and staves the other containers.

But what if we forget to set those limits? Well, no worries…we can update them on the fly!

Let’s have a look. First let’s run a container with no memory limits: –

docker container run -d \
--publish 15789:1433 \
--env ACCEPT_EULA=Y \
--env MSSQL_SA_PASSWORD=Testing1122 \
--name sqlcontainer1 \
mcr.microsoft.com/mssql/server:2019-CU12-ubuntu-18.04

Confirm the container is up and running: –

docker container ls

Now have a look at the stats of the container: –

docker stats

This container is running on a host with 4GB of RAM so pretty much no limit in place. Let’s add a limit: –

docker update sqlcontainer1 --memory 2048MB

N.B. – Thanks to Anthony Nocentino (b|t) for pointing this out to me, I was under the (wrong) impression that limits couldn’t be changed on a running container…so this is really cool.

In fact, if you want a better explanation on container limits I recommend you check out Anthony’s post Container Limits and SQL Server

Anyhoo, now let’s have a look at the limits in place: –

docker stats

Cool! So we’ve set a limit for our running container!

BUT! What if we know how those limits are enforced…can we enforce a limit on a running container without using docker update?

Let’s have a go! First remove the existing container and re-deploy: –

docker container rm sqlcontainer1 -f

docker container run -d \
--publish 15789:1433 \
--env ACCEPT_EULA=Y \
--env MSSQL_SA_PASSWORD=Testing1122 \
--name sqlcontainer1 \
mcr.microsoft.com/mssql/server:2019-CU12-ubuntu-18.04

Confirm, no limit in place: –

docker stats

Same as before.

Right, limits on containers are enforced by control groups (cgroups)…when processes are placed in cgroups those cgroups (for memory, cpu etc.) limit the amount of the host’s resources that a process can use.

And that’s all containers really are…just processes running on the host.

So let’s find the cgroup for the memory limit for the container.

First grab the container ID (have to set the limit as root so switching here): –

sudo su

CONTAINERID=$(docker ps -aq) && echo $CONTAINERID

Then have a look at the memory control group

find /sys/fs/cgroup/ -name *$CONTAINERID*

MEMORYCGROUP=$(find /sys/fs/cgroup/ -name *$CONTAINERID* | grep memory) && echo $MEMORYCGROUP

ls $MEMORYCGROUP

cat $MEMORYCGROUP/memory.limit_in_bytes

So no limit in place. Let’s set a limit and confirm: –

echo 2147483648 > $MEMORYCGROUP/memory.limit_in_bytes

cat $MEMORYCGROUP/memory.limit_in_bytes

Looks good, now let’s check docker stats: –

docker stats

And there’s the limit in place! Kinda cool…working out how Docker is placing resource limits on containers by using cgroups. If you fancy reading more about how container works, check out my SQL Containers From Scratch blog here.

Thanks for reading!