A custom MS SQL Server image, patched to work with tmpfs. Speeds up CI/CD test runs.
6.0K
A custom image that uses mcr.microsoft.com/mssql/server as a base,
but adds tmpfs support.
Running database containers with tmpfs volume mounts can save a lot
of time in integration/E2E test scenarios, since volatile memory
(RAM) is way more faster to access. This image is intended to do
just that.
This image is designed for CI/CD pipelines - specifically for
running MS SQL Server in E2E/Integration tests via Testcontainers or
similar tools. By storing database files in RAM instead of on disk,
test suites execute significantly faster, translating to real-world
time savings in your CI/CD workflows.
Since MS SQL Server 2025, tmpfs is supported, but only for tempdb.
This might not be ideal for everybody, since some cleanup tools like
Respawn don't work with that.
docker pull vkotzsev/mssql-server-tmpfs:2025-latest
Available tags:
2025-latest โ latest build on the 2025 track (updated on every push)2022-latest โ legacy build on the 2022 tracklatest โ latest build from master branch<commit-sha> โ pinned to a specific build (e.g. a845231)docker run -d \
--name mssql-tmpfs \
--tmpfs /var/opt/mssql/data:uid=10001,gid=10001,size=4G \
--tmpfs /var/opt/mssql/log:uid=10001,gid=10001,size=1G \
-e ACCEPT_EULA=Y \
-e MSSQL_SA_PASSWORD=<password> \
-p 1433:1433 \
vkotzsev/mssql-server-tmpfs:2025-latest
Once the container is running, you can verify that the data and log directories are mounted as tmpfs:
docker exec mssql-tmpfs df -h | grep tmpfs
Expected output:
tmpfs 4.0G 73M 4.0G 2% /var/opt/mssql/data
tmpfs 1.0G 236K 1.0G 1% /var/opt/mssql/log
You can also confirm the preload hook is active:
docker exec mssql-tmpfs cat /etc/ld.so.preload
Expected output:
/nodirect_open.so
MS SQL Server opens data files with O_DIRECT, a flag that performs
direct I/O โ reading and writing straight to storage, bypassing the
OS page cache. This is excellent for production workloads on SSDs/NVMe
drives, but it is incompatible with tmpfs mounts. When the kernel
detects O_DIRECT on a tmpfs filesystem, it rejects it with EINVAL,
and MS SQL fails to start:
Direct open file /var/opt/mssql/data/master.mdf failed with error 22
ld.so.preloadRather than patching MS SQL's source code (which would require rebuilding
the entire database engine), this image uses ld.so.preload โ a
Linux mechanism that lets you interpose arbitrary shared library
functions into every process before it starts.
nodirect_open.c is a tiny shared library that overrides the open()
system call. When any process in the container calls open(), it goes
through our wrapper first, which strips the O_DIRECT flag before
calling the real open(). This allows MS SQL to operate on tmpfs
mounts without ever attempting direct I/O.
int open(const char *pathname, int flags, ...)
{
static orig_open_f_type orig_open;
if (!orig_open)
orig_open = dlsym(RTLD_NEXT, "open");
return orig_open(pathname, flags & ~O_DIRECT);
}
| Approach | Pros | Cons |
|---|---|---|
| Source-patch MS SQL | Clean, official | Requires rebuild of entire DB engine; legally/commercially complex |
ld.so.preload (this) | Zero MS SQL changes, ~16 lines of C, works for all versions | Slight syscall overhead (negligible vs DB workload) |
| Bind mount workaround | No code needed | Loses tmpfs benefits (disk-backed) |
The preload approach is lightweight, non-invasive, and works regardless of which SQL Server version or CU you're running.
This image is designed to work seamlessly with
Testcontainersโ
for .NET integration and end-to-end testing. By running MS SQL Server
with tmpfs, tests execute significantly faster since database
operations happen in-memory rather than hitting disk.
[TestMethod]
public async Task TestWithTmpfs()
{
var container = new MsSqlBuilder()
.WithImage("vkotzsev/mssql-server-tmpfs:2025-latest")
.WithTmpfs(new Dictionary<string, string>
{
{ "/var/opt/mssql/data", "size=4G,uid=10001,gid=10001" },
{ "/var/opt/mssql/log", "size=1G,uid=10001,gid=10001" }
})
.WithPassword("TestPassword123!")
.Build();
await container.StartAsync();
// Tests run against in-memory database - much faster!
}
Respawnโ is a smart database
cleanup library for .NET that resets your database to a clean state
between tests. However, Respawn doesn't work with tempdb because
it's designed to work with actual user databases.
Since MS SQL Server 2025 only supports tmpfs for tempdb out of the
box, this custom image enables tmpfs for the actual database files.
This allows you to:
Respawn for intelligent test data cleanupUsing tmpfs for your MS SQL container in CI/CD pipelines provides
substantial performance gains:
| Aspect | Disk-based | tmpfs (RAM) |
|---|---|---|
| Query execution | Baseline | 2-10x faster |
| Write operations | Disk I/O bottleneck | Near-instant |
| Container startup | Disk initialization required | ~Instant |
| Test suite execution | Minutes | Seconds to minutes less |
Why it's faster:
This makes it particularly valuable for CI/CD pipelines where test execution time directly impacts delivery speed.
Content type
Image
Digest
sha256:a8cb743d7โฆ
Size
580.7 MB
Last updated
6 days ago
docker pull vkotzsev/mssql-server-tmpfs