Test Management in Docker: The Compose File Is Only Day One
A docker compose up gets your test case manager running in minutes. Here is everything it quietly leaves you holding after that.

Someone on your team has probably already tried this. It is a Tuesday afternoon, the sprint retro raised the same complaint it raised last sprint, that test cases are scattered across a spreadsheet, a Confluence page, and someone's memory, and a volunteer says they will "just spin up a proper tool" before standup tomorrow. They find a self hosted test case manager, copy a docker compose file from the project's README, run docker compose up, and by the time the coffee is done there is a login screen. It genuinely works. That is not the problem this post is about.
The problem shows up three weeks later, when someone asks where the test history lives, whether the login page is reachable from outside the office network, and what happens when a new version ships. Those are day two questions, and the compose file was never going to answer them, because that is not its job. This post is for the person who typed the commands, not the person who is still evaluating options, and it spends its second half on exactly what the compose file left for you to figure out.
What a container based install actually removes
Be precise about the win here, because it is real. A single compose file removes three specific chores that used to eat the first hour of any self hosted install.
- Dependency versions: you are not hunting for the right Python or PHP version, the right database driver, or a library that conflicts with something else on the box.
- Service wiring: the app, the database, and often a cache or a mail relay are already configured to talk to each other on the right ports with the right credentials.
- The first hour of guesswork: instead of reading an install guide and translating it into commands for your specific Linux distribution, you run one command and get a running stack.
That is a genuine kindness, and it is why containerized installs have become the default way self hosted test tools get distributed. It is also the easy 5% of running the thing. The compose file made a set of decisions on your behalf so it could hand you something that boots, and every one of those decisions is now yours to live with.
The four decisions the compose file made without asking you
Read a typical compose file for a self hosted app and you will find it has quietly decided four things.
- Where the database volume lives on disk, and whether that path is on the same drive as your OS or a separate, backed up mount.
- How secrets like the database password and any admin token are supplied, often as plain environment variables sitting in the compose file itself.
- Whether the database runs in the same compose stack as the app, sharing its lifecycle, or as a separate managed service you point the app at.
- What ports are exposed to the host machine, and by extension, to whatever network that machine sits on.
None of these are wrong choices for a five minute demo. All four are worth revisiting before this thing holds test cases anyone depends on. A team that runs the demo defaults for six months usually finds out the hard way, when a laptop reboot wipes an unbacked volume, or when a port that was meant for local access turns out to be reachable from the guest wifi.
Persistence, stated bluntly
Here is the sentence that should be pinned above every self hosted test tool: a named volume is not a backup. Docker's named volumes solve a real problem, they let data survive a container being stopped and restarted, and that alone feels like durability. It is not the same thing as durability.
If someone runs docker compose down -v to do a clean reset, or a host gets rebuilt and the volume is never recreated at the same path, every test case, every run history, every attachment is gone with it. This is not a hypothetical. It is the exact failure mode that turns "we moved off the spreadsheet" into "we lost three months of regression history and had to rebuild it from a spreadsheet anyway." Back up the volume the same day you stand up the container, not after the first scare.
Putting it behind a reverse proxy, and why the certificate renewal matters more than the certificate
The default compose file usually exposes the app on a raw port like 8080, reachable by IP address over plain HTTP. That is fine for a laptop demo. It is not fine for a tool your whole QA team logs into with real passwords. The fix is a reverse proxy in front of it, terminating TLS, so the login screen is served over HTTPS on a real domain name.
The part teams get wrong is not putting the proxy in place, it is forgetting that a certificate expires. A certificate issued today is often valid for 90 days. If renewal is a task someone has to remember to run manually, it will eventually be missed, usually right before a demo or an audit, and the whole team gets a browser warning instead of a login page. Automate renewal the same day you set up the proxy, using a tool like Caddy or an ACME client tied to cron, so it is infrastructure rather than a recurring reminder on someone's calendar.
The architecture check nobody thinks to do first
This is a live issue in the self hosted test management category specifically, and it is worth checking before you pick a tool, not after. Not every project publishes container images for every CPU architecture. Kiwi TCMS's Community Edition images are x86_64 only as of 25 August 2026, per their own documentation at kiwitcms.org. That means if your infrastructure runs on Apple Silicon Macs for local development, or on Graviton instances in AWS for production, the free tier images will not run natively there.
This is worth stating plainly because it is an easy thing to discover too late, after the compose file has already been written into a runbook. Check the image's supported architectures against the machines you actually plan to run it on, including your CI runners if you plan to spin up an ephemeral instance for testing, before you standardize on it.
The upgrade path, and why a rolling tag takes the decision away from you
A compose file that pins an image to :latest looks convenient right up until an upgrade happens without anyone choosing it. Pull a new base image, restart the stack, and you may get a schema migration you did not review, applied to a database you did not back up first, at a time you did not pick. The fix is boring and it works: pin a specific version tag, read the release notes before you move to a new one, and change that one line deliberately when you are ready.
This matters more for a test case manager than for a lot of other self hosted tools, because the data at risk is not disposable content, it is the record of what your team has already verified. A team running the 900 test case suite that takes 50 minutes to execute does not want to discover mid sprint that a silent upgrade changed a field mapping and orphaned half their run history.
Questions people ask
Is a docker compose file enough to run a test case manager in production?
It is enough to get it running. Production readiness needs a real reverse proxy with automated TLS renewal, an actual backup of the data volume, and a version pinned image, none of which the default compose file sets up for you.
Does a named Docker volume protect my test history from data loss?
It protects against a container restart. It does not protect against a deleted volume, a rebuilt host, or someone running a destructive compose command. Treat it as storage, and back it up separately.
Can I run these self hosted tools on an Apple Silicon Mac or an AWS Graviton instance?
It depends on the specific project and image. Check published architecture support directly. Kiwi TCMS's Community Edition images were x86_64 only as of 25 August 2026, so Apple Silicon and Graviton were not covered on the free tier.
Why does the image tag I use for an upgrade matter?
A rolling tag like :latest applies whatever the newest image is the next time you restart the stack, including any schema migration in it. A pinned version tag means you choose when that migration happens, after reading the release notes and backing up first.
What's the actual cost of self hosting a test case manager versus a managed one?
Self hosting trades a subscription cost for operational time: reverse proxy setup, certificate renewal, backups, upgrade testing, and architecture compatibility checks all become your team's ongoing work, not the vendor's.
Day one is the cheap day. The compose file gets you a login screen by lunchtime, and that speed is real and worth something. The bill arrives afterward, in the storage decisions you have to revisit, the certificate renewal you have to automate, the architecture you have to confirm, and the upgrade path you have to own going forward. None of that makes self hosting a bad choice. It makes it a choice with a second invoice, due later, paid in engineering time instead of dollars.
Try Tesbo, or get the next useful idea
Start building your testing workflow now, or get one practical email a month.
Start freeOne email a month
What we shipped, what we learned, and the occasional infographic worth pinning. Unsubscribe in one click.


