How to Run Compose on Self-Hosted Runners
Self-hosted runners persist state between jobs, so leftover Compose containers and volumes are the main risk and cleanup is the fix.
Because a self-hosted runner is not fresh each run, isolate every job with a unique project name and always tear down, so one job never inherits another job's containers or volumes.
Steps
- Set a unique
-pproject name per job or run. - Always run
docker compose down -vat the end, even on failure. - Prune dangling images periodically so disk does not fill.
CI job
.github/workflows/ci.yml
jobs:
test:
runs-on: self-hosted
steps:
- uses: actions/checkout@v4
- run: docker compose -p ci-${{ github.run_id }} up -d --wait
- run: npm run test:int
- if: always()
run: docker compose -p ci-${{ github.run_id }} down -v --remove-orphansGotchas
- Without a unique project name, two concurrent jobs on one runner clash over container names.
- Latchkey managed runners are ephemeral and auto-heal transient failures, so this class of leftover-state flake does not occur.
Related guides
How to Run Parallel Compose Stacks Per CI JobRun isolated Compose stacks in parallel CI jobs by giving each a unique project name with -p or COMPOSE_PROJE…
How to Tear Down a Compose Stack and Clean Volumes in CIClean up after a Compose based CI job with docker compose down --volumes --remove-orphans so no stale data or…
How to Cache Compose Image Builds in CISpeed up docker compose build in CI with BuildKit inline cache or a registry cache backend so unchanged layer…