feat(infra): add docker-compose support and configure testcontainers#23
Conversation
- Add Postgres and Redis configurations to the application.yml files in the api and worker modules. - Remove autoconfigure excludes from the application.yml files.
…and worker - Add spring-boot-testcontainers and testcontainers dependencies to both modules - Implement AbstractIntegrationTest base class for automatic Postgres and Redis setup - Update existing tests to extend AbstractIntegrationTest for isolated test environments - Ensure Flyway and datasource connectivity via @Serviceconnection in integration tests
martian56
left a comment
There was a problem hiding this comment.
I verified this end to end on my machine: docker compose up brings postgres:16 and redis:7 online, docker compose ps shows both running, and the api and worker jars built from this branch boot against the stack and report UP on their health endpoints. All four checkboxes on #4 hold up, and @Serviceconnection is the right modern way to hook Testcontainers into the tests. Good PR.
Cleanup before merge:
- There is a junk empty file at backend/docker, looks like a shell redirect accident. Remove it, and add a git status skim to your pre-push routine. This is the second PR in a row to ship one of these, and I will be grumpier about the third.
- Coordinate with Arzu: this PR and #21 both rewrite the api application.yml and the api test setup. The plan from my #21 review is that her PR drops its api changes and this one owns the api and worker wiring, so expect a small rebase depending on which lands first. Talk to each other.
- The rest is inline: a version pin that should not exist, health indicator flags that are now wrong, a volume the database needs, and a README paragraph that oversells what compose runs.
One for the future rather than this PR: AbstractIntegrationTest is duplicated identically in api and worker. Fine for two apps, but if a third consumer appears we hoist it into a shared test fixture instead of copying again.
…pi and worker modules.
- Add named volume for database persistence to prevent data loss. - Add pg_isready healthcheck for service readiness. - Sync postgres image tag to 16-alpine for consistency with integration tests.
…connectivity - Setup .env and .env.example for centralized config - Updated .gitignore to exclude sensitive .env file - Refactored docker-compose and application.yml files to use environment variables for DB and Redis connections
martian56
left a comment
There was a problem hiding this comment.
This one I verified end to end, and it holds up. From a clean checkout:
- docker compose up brings up postgres:16-alpine and redis:7. The postgres healthcheck works, the container reports healthy, and there is a named volume so the data survives a recreate. All three of my compose asks from last round are in.
- I built the api and worker jars and booted both against the stack. The api connected through HikariPool to jdbc:postgresql://localhost:5432/cleat_db (PostgreSQL 16.14), Flyway initialized its history table, Tomcat came up, and CleatApiApplication started. Both /actuator/health report UP, the worker with liveness and readiness groups. The dynamic database connectivity is real, not just configured.
- The env-var defaults are now in compose and in both ymls, the db and redis health indicators are re-enabled, the worker yml indentation is fixed, and the testcontainers-bom version pin is gone so Boot manages those versions. README no longer claims compose runs the api and worker.
That is the whole list from last round bar one. Approving, with these to clean up before you merge:
- backend/docker, the empty junk file, is still in the tree. This is the exact one I flagged last round, so this is me being grumpier as promised. Delete it, and please skim git status before pushing so the next one does not slip in.
- README leftover, inline.
- A small api/worker health-config asymmetry, inline.
nit: redis has no healthcheck, only postgres does. A redis-cli ping check would let future services depends_on it cleanly. Optional.
Coordination, same as I told Arzu on #21: the api application.yml here owns the real datasource now, which supersedes the excludes she restored. Your version should be the one that survives the merge. Sort the ordering with her so nobody clobbers the other.
Solid, well-verified PR. Clear the junk file and it is ready.
martian56
left a comment
There was a problem hiding this comment.
Retracting my approval from yesterday, because today's merge of main (462dbf5) broke the api config. Not your earlier work, the merge resolution.
backend/apps/api/src/main/resources/application.yml now has leftover merge-conflict residue. Lines 4 and 28 each contain a bare feature/4-docker-compose-setup. That is the tail of a >>>>>>> feature/4-docker-compose-setup marker: the >>>>>>> got hand-stripped while resolving the #21-vs-#23 collision on this file, but the branch label survived. As it stands this is not valid YAML, so Spring will fail to parse it and the api will not boot. This is exactly the api.yml collision I flagged when both PRs touched this file.
The good news is the resolution mostly went the right way: your datasource block (lines 5-14) is intact and is the version that should win, since this PR owns the real wiring. The fix is just to delete the two stray label lines so the file is clean YAML again. Details inline.
After that, please actually run it before re-requesting: docker compose up, then boot the api jar and confirm HikariPool connects and /actuator/health is UP. A YAML parse error is the kind of thing a quick boot catches instantly.
One more still open from my approval: backend/docker, the empty junk file, is still in the tree. This is the third PR running with one of these, so please delete it and add a git status skim before you push.
Everything else I verified last time still stands, compose, the healthcheck and volume, env-var defaults, health indicators, the dropped BOM pin, the README. Clean up the two yml lines and the junk file and this goes back to approved.
martian56
left a comment
There was a problem hiding this comment.
The actual blocker is fixed, I confirmed it. I ran both ymls through a YAML parser: api and worker both parse cleanly now, the datasource block is intact, health.db and health.redis are on, and you even added the probes block to the api so it matches the worker, which clears the asymmetry nit from before. The conflict residue is gone, backend/docker is gone, and you added a backend/.gitignore. Good progress.
I am still requesting changes for one reason: this round added new junk files. Three of them, all empty:
- backend/Task
- backend/There
- backend/initializationError
Those are accidental shell redirects of Gradle output. 'Task' is the start of a '> Task :apps:api:test' line, 'There' is from 'There were failing tests', and 'initializationError' is a JUnit failure label. So a Gradle run got pasted into a shell and the '>' wrote three files. Delete all three.
This is the third PR in a row with stray files, so I am going to keep holding on it until a branch comes through clean. The backend/.gitignore you added is a good move, but it will not catch these since they are not ignore patterns. The thing that actually prevents this is a five second git status skim before every push. Please make that a habit, it is the whole fix.
One more, smaller: the .env.example you added at the repo root has the right contents, but it is in the wrong place. docker compose up run from backend/ loads its .env from backend/, so a root .env.example will never be picked up by the stack it is meant to document. Move it to backend/.env.example, next to compose.yaml, or drop it. Details inline.
I could not run the full compose boot this round, Docker was not up on my machine, but the YAML parsing cleanly is the thing that was broken, and I verified the whole stack end to end on this branch's substance last time. Please do a quick docker compose up plus an api boot yourself before merging, since a bad yml shows up the instant the app starts.
Clear the three stray files and sort the env example, and this is back to approved. You are basically there.
martian56
left a comment
There was a problem hiding this comment.
Approving. The blockers are cleared and I re-checked the tree this round:
- The api application.yml is clean valid YAML again, no conflict residue, and it has not changed since I ran it through a parser last round, so that check still holds. The datasource block, the health indicators, and the probes are all intact.
- All the stray files are gone: backend/docker, backend/Task, backend/There, backend/initializationError. The diff against main is finally all legitimate files, nothing accidental.
- backend/.env.example now sits next to compose.yaml where it will actually be picked up. Good.
One thing to do before you merge, and it is the last thing: delete the root .env.example. You added backend/.env.example, which is the correct one, but the old root copy is still there with identical contents, so right now there are two. The root one will not be read by the compose stack, so just remove it and keep the backend one. Inline note on it.
I did not re-run the full compose boot this round, but the yml parsing cleanly was the thing that broke last time and that is confirmed, and I verified the whole stack end to end on this branch earlier. Do a quick docker compose up plus an api boot before you merge just to be safe, then drop the root .env.example and ship it.
Thanks for grinding through the cleanup. This is a good PR.
| @@ -0,0 +1,9 @@ | |||
| POSTGRES_USER=cleat | |||
There was a problem hiding this comment.
This is the leftover from last round. You correctly added backend/.env.example, but this root copy is still here with the same contents, so delete this one. The backend/ copy is the one that the compose stack will actually read. Removing this leaves a single, correctly placed example.


What does this change?
This PR sets up the Docker development environment and integrates Testcontainers to ensure robust integration testing.
docker-compose.ymlfor Postgres and Redis.AbstractIntegrationTestwith@ServiceConnectionfor automated container management.README.md.Related issue
Closes #4
Area
Screenshots
N/A
Checklist
bun run typecheck && bun run buildinapps/web(for frontend changes)