SQL Server Linux Container Images Got Smaller: Image Size and Startup Time Across Cumulative Updates
Page content
This week I was at PASS Data Community Summit in Seattle, and I attended a session called “An Inside Look at How Microsoft Builds SQL Features, by Bob Ward, Naveen Prakash, and Travis Wright, all of whom are on the SQL Server team. In this session, Travis mentioned that they reduced the SQL Server container image size by a meaningful amount using AI agents that helped discover unused code in the image, but details on how much and when were lost when the conversation moved on to the next topic. So I set out to find out exactly which SQL Server build this came out in, and I also wanted to measure how much we saved. They also mentioned that startup times were better now.
I use SQL Server containers nearly every day, and I’ve written a ton about containers on this blog, so I got to work. So I pulled the CU images for SQL Server 2025 and SQL Server 2022, measured each one, and timed how long it took to get from docker run to a successful query.
In this post, I’m going to show you where the images got a lot smaller, including a 25% smaller download for SQL Server 2025 CU11, and I’ll show you that the smaller images didn’t start any faster in my testing. Let’s go.
The Test Setup
Here’s what I tested on my Mac, running through Rosetta: I used images from mcr.microsoft.com/mssql/server and started one fresh container per tag, from the newest CU to the oldest.
To isolate the impact of the cumulative update, I stuck with one base OS for each major version:
- SQL Server 2025: CU1 through CU11, using the Ubuntu 22.04 tags.
- SQL Server 2022: CU1 and CU3 through CU28, using the Ubuntu 20.04 tags. CU2 isn’t in the registry’s tag list.
For each image, I captured three measurements:
- Compressed layers: the sum of the layer sizes in the registry manifest. This approximates the bytes you download when you pull the image.
- Local image size: what
docker image inspectreports for the pulled image. - Startup to query: wall-clock seconds from just before
docker run -duntilsqlcmdconnected and returnedSELECT SERVERPROPERTY('ProductVersion').
The startup number is a coarse, end-to-end measurement. It includes Docker creating and starting the container, so it’s more than SQL Server’s own startup time. I polled for a connection every half second.
SQL Server 2025 Results
Let’s start with SQL Server 2025. In the table below, sizes are in decimal units and the startup time is from a single run per tag.
| Tag | Product Version | Compressed Layers (MB) | Local Image (GB) | Startup to Query (s) |
|---|---|---|---|---|
| 2025-CU11 | 17.0.5065.9 | 480.7 | 2.221 | 8.64 |
| 2025-CU10 | 17.0.5035.5 | 640.1 | 2.434 | 8.03 |
| 2025-CU9 | 17.0.5005.3 | 638.1 | 2.427 | 8.80 |
| 2025-CU8 | 17.0.4075.5 | 636.9 | 2.423 | 8.78 |
| 2025-CU7 | 17.0.4065.4 | 636.3 | 2.420 | 9.49 |
| 2025-CU6 | 17.0.4055.5 | 664.6 | 2.525 | 8.52 |
| 2025-CU5 | 17.0.4045.5 | 661.7 | 2.515 | 8.97 |
| 2025-CU4 | 17.0.4035.5 | 661.8 | 2.515 | 8.35 |
| 2025-CU3 | 17.0.4025.3 | 657.9 | 2.500 | 8.45 |
| 2025-CU2 | 17.0.4015.4 | 655.6 | 2.493 | 8.58 |
| 2025-CU1 | 17.0.4006.2 | 653.2 | 2.485 | 7.52 |
As you can see in the table above, every image from CU1 through CU10 lands between about 636 and 665 MB compressed. Then CU11 drops to 480.7 MB. That’s 159 MB, or 24.9%, less to download than CU10. The local image is 213 MB, or 8.7%, smaller too.
Notice the startup column, though. CU11 took 8.64 seconds, and CU10 took 8.03 seconds. A smaller image didn’t get me a faster start. More on that in a bit.
SQL Server 2022 Results
SQL Server 2022 is where things get interesting. Here’s every CU I tested, and three of them really stand out.
| Tag | Product Version | Compressed Layers (MB) | Local Image (GB) | Startup to Query (s) |
|---|---|---|---|---|
| 2022-CU28 | 16.0.4325.4 | 474.7 | 2.167* | 6.85 |
| 2022-CU27 | 16.0.4295.3 | 618.4 | 2.309 | 6.10 |
| 2022-CU26 | 16.0.4265.3 | 618.0 | 2.308 | 6.12 |
| 2022-CU25 | 16.0.4255.1 | 615.0 | 2.299 | 6.15 |
| 2022-CU24 | 16.0.4245.2 | 606.5 | 2.275 | 6.52 |
| 2022-CU23 | 16.0.4236.2 | 606.1 | 2.274 | 6.11 |
| 2022-CU22 | 16.0.4225.2 | 606.1 | 2.274 | 6.59 |
| 2022-CU21 | 16.0.4215.2 | 606.1 | 2.274 | 7.13 |
| 2022-CU20 | 16.0.4205.1 | 612.8 | 2.297 | 6.31 |
| 2022-CU19 | 16.0.4195.2 | 603.5 | 2.265 | 6.20 |
| 2022-CU18 | 16.0.4185.3 | 611.6 | 2.292 | 6.34 |
| 2022-CU17 | 16.0.4175.1 | 601.4 | 2.256 | 6.19 |
| 2022-CU16 | 16.0.4165.4 | 582.9 | 2.205 | 6.44 |
| 2022-CU15 | 16.0.4145.4 | 583.2 | 2.206 | 6.22 |
| 2022-CU14 | 16.0.4135.4 | 582.6 | 2.204 | 6.33 |
| 2022-CU13 | 16.0.4125.3 | 579.7 | 2.194 | 6.66 |
| 2022-CU12 | 16.0.4115.5 | 580.7 | 2.197 | 6.65 |
| 2022-CU11 | 16.0.4105.2 | 573.9 | 2.180 | 6.89 |
| 2022-CU10 | 16.0.4095.4 | 572.2 | 2.173 | 6.14 |
| 2022-CU9 | 16.0.4085.2 | 572.4 | 2.173 | 6.43 |
| 2022-CU8 | 16.0.4075.1 | 1,036.7 | 3.962 | 6.13 |
| 2022-CU7 | 16.0.4065.3 | 1,037.1 | 3.963 | 6.26 |
| 2022-CU6 | 16.0.4055.4 | 1,037.2 | 3.962 | 6.37 |
| 2022-CU5 | 16.0.4045.3 | 572.0 | 2.175 | 6.32 |
| 2022-CU4 | 16.0.4035.4 | 571.4 | 2.172 | 6.47 |
| 2022-CU3 | 16.0.4025.1 | 574.2 | 2.200 | 6.74 |
| 2022-CU1 | 16.0.4003.1 | 574.9 | 2.204 | 6.77 |
Here’s what jumps out:
- CU6, CU7, and CU8 are about double the size: roughly 1 GB compressed and almost 4 GB locally. CU5, right before them, is 572 MB compressed and 2.175 GB locally.
- CU9 brings it right back down: going from CU8 to CU9 cuts 464 MB (44.8%) from the download and 1.79 GB (45.2%) from the local image.
- CU28 drops again: compressed layers go from 618.4 MB in CU27 to 474.7 MB in CU28. That’s 144 MB, or 23.2%, less to download.
- The images grow in between: from CU9 through CU27, the download goes from 572 MB to 618 MB.
What’s Actually Happening
So why are CU6 through CU8 so big? I looked at the layer history for a few of these images with docker history --no-trunc. Here’s what I found around the SQL Server payload layers, with approximate sizes:
- 2022 CU5: a 1.33 GB
COPYpayload layer and a 195 MB install layer. - 2022 CU6 and CU8: a 1.33 GB
COPY install.tarlayer, a second 1.33 GB extraction layer, and a 193 MB install layer. - 2022 CU9: a 1.33 GB extraction layer and a 193 MB install layer. The separate
COPY install.tarlayer is gone.
That’s consistent with CU6 through CU8, which carry the install archive in one layer and the extracted files in another. If that’s what’s going on, those images store the same payload twice. In CU9, the archive layer is gone. My guess is something slipped into the build process that shouldn’t have.
Does a Smaller Image Start Faster?
I tested the SQL Server 2025 CU10 to CU11 and SQL Server 2022 CU27 to CU28 transitions. For each CU, I started five fresh containers and alternated which version ran first.
The table shows the median startup time for each version, with the fastest and slowest run in parentheses.
| Transition | Earlier CU median (range) (s) | Later CU median (range) (s) |
|---|---|---|
| 2025 CU10 to CU11 | 9.25 (8.05 to 9.38) | 8.13 (8.04 to 9.47) |
| 2022 CU27 to CU28 | 6.99 (5.86 to 7.73) | 6.85 (5.84 to 7.11) |
CU11’s median was 1.12 seconds lower than CU10’s. CU28’s median was 0.14 seconds lower than CU27’s. But the ranges overlap in both comparisons, so these runs don’t show a consistent startup improvement.
The Bottom Line
The key thing here is that a smaller image saves you time and space on the pull, and in my testing that’s where the benefit ends. Once the image is on the host, startup time looks the same.
That’s still a win, and it’s particularly valuable for:
- CI/CD pipelines: runners that start clean pull the image on every run, so 159 MB less per pull adds up.
- Kubernetes clusters: a new node has to pull the image before the first Pod can start.
Wrapping Up
The SQL Server Linux container images got about 25% smaller in SQL Server 2025 CU11 and SQL Server 2022 CU28. Startup time didn’t change much in my testing.
Related Posts
- SQL Server 2025 CU1 Fixes the Docker Desktop AVX Issue on macOS - Getting SQL Server 2025 containers running on Docker Desktop
- Getting SQL Server 2025 RTM Running in Containers on macOS - The original AVX issue and the OrbStack workaround
- Automated SQL Server Benchmarking with HammerDB and Docker - A containerized framework for TPC-C and TPC-H testing