Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Run Docker Compose in GitHub Actions by treating the workflow as a short-lived CI environment: use a Linux runner, check out the repository, start the Compose project with docker compose up --build --wait, execute tests in a disposable container, collect logs if anything fails, and remove the stack in an always() cleanup step.

The important design choice is where the job runs. A job running directly on the runner reaches mapped Compose ports through localhost. A container job reaches service containers by their Compose/GitHub service labels, such as redis. Whichever model you choose, make the addresses in your test configuration match it and express readiness with Compose healthchecks rather than an arbitrary sleep.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The minimal workflow

This workflow is a practical baseline for a repository whose Compose file defines a service named web and whose tests run with pytest:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Start services
        run: docker compose up --build --wait

      - name: Run tests
        run: docker compose run --rm web pytest

      - name: Show status and logs on failure
        if: failure()
        run: |
          docker compose ps
          docker compose logs --no-color

      - name: Tear down
        if: always()
        run: docker compose down

up builds images when requested, recreates containers when necessary, starts the services, and attaches to them. The --wait option makes the command wait for services to be running or healthy; --build ensures the workflow uses the current checkout rather than an older local image. The test command uses run for a one-off container and --rm to remove that container when the command ends.

#1 Best Overall
Sale
Compressed Air Duster,130000RPM Super Power Cordless Air Duster,Rechargeable Brushless Blower,3 Gear Adjustable Blower with LED Light,Dust Remover for Computer/House/Outdoor/Car
  • Powerful Turbo Fan:CAGIWIRU Electric Air Duster have reached speed up to 130000RPM,Can efficient remove dust and debris.With LED light and Three Adjustable Speed to meet with different cleaning tasks.
  • With Attached USB C Fasting Charging cable.Charing 3 hours,Enjoy up to 240 minutes of use on the lowest setting, For third speed can use for 25mins.with four charging options to meet with your needs.
  • Wide Application:Upgraded attached 5 different nozzles,making it suitable for a variety of scenes, such as car,pet, pc, keyboards, and other electronic devices. It also serves for office and home clean duster.
  • Handy Design & Portable:Cordless air duster electric nozzle is Light weight and small size, design and comfortable to hold and space saving, convenient to carry around. You can put it in your room or inside the car without taking up space.
  • Warranty & Support: Our Electric air duster comes with 5 years warranty and 24/7 customer service. During this period, if you have any questions,pls kindly feel free to contact us.

Replace web pytest with the service and command used by your project. A Node.js project might run its test runner in web; a migration job might run a database migration command in an application service. The Compose file, not the workflow, remains the single definition of the application stack.

Choose the GitHub Actions execution model

Docker Compose can be used in CI, but GitHub’s Docker-based workflow features require Linux. GitHub-hosted jobs should use an Ubuntu runner. A self-hosted runner must be Linux and have Docker installed and available to the runner account.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Job on the runner machine

With the ordinary job form, such as runs-on: ubuntu-latest, workflow steps execute on the runner host. Compose containers are still isolated, but any service that tests need to reach must publish a port in the Compose file. The test process then uses localhost:<port> or 127.0.0.1:<port>.

This model is convenient when the workflow already uses host-level shell tools, Docker commands, or scripts that assume the runner filesystem. It also makes debugging with direct host commands straightforward. Keep the port mapping explicit and avoid binding a service to a port that another step or parallel process could already be using.

Container job

If the job itself runs in a container, GitHub connects the job container and its service containers to a user-defined bridge network. A configured service label becomes the hostname: a service labeled redis is addressed as redis, not as localhost. This gives tests a fully containerized environment and service-name discovery, but every tool required by the job must exist in the job image.

Use a container job when reproducibility and container-to-container networking matter more than host tooling. Use a runner-machine job when existing scripts and host Docker access are the priority. Do not mix the addressing assumptions: changing the job placement without changing the database or cache hostname is a common cause of connection failures.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Decision Runner-machine job Container job
Required platform Linux for Docker-based workflow features; GitHub-hosted jobs should use Ubuntu Linux runner; GitHub connects the job and services on a user-defined bridge network
Service address used by tests localhost:<mapped-port> or 127.0.0.1:<mapped-port> The configured service label, such as redis
Best fit Host shell tooling, direct Docker commands, and localhost-based scripts A fully containerized test environment and label-based service discovery

Prepare the Compose project for CI

Keep the stack definition complete

Your Compose file should define every dependency needed by the test service: application containers, databases, caches, queues, and supporting services. A CI run starts from a clean runner, so it cannot rely on a container left over from a developer’s previous command. Put image names, build contexts, environment variables, networks, volumes, and dependency relationships in the Compose configuration or in explicitly supplied environment files.

The service that runs tests should be separate from long-running application services when possible. That lets the workflow start the stack once and invoke a disposable test container for each test command. It also allows a migration or administrative operation to use the same images and network without turning the test command into the main service’s permanent process.

Rank #2
EVEO® Screen Cleaner Spray Kit (Streak-Free) TV Screen Cleaner for Smart TV, Lcd, LEd, Oled | Computer Screen Cleaner Spray and Wipe Microfiber Cloth - TV, Monitor, Laptop, iPad, Car - 6.7oz 1 Pack
  • Screen Cleaner is Your Screen’s New Bestfriend! - EVEO is proud to present a screen cleaner that’s perfectly suited for your TV. Meet your new screen cleaner, computer screen cleaner, laptop cleaner, iPad cleaner, Macbook,tv cleaner or any other electronic device. Our screen cleaner spray and wipe along with the included plush microfiber cloth, easily removes dust, fingerprints & other smudges on the screen’s surface. Clean effectively for a streak-free screen
  • Gentle on your Screens - Our screen cleaner spray and wipes is compatible to be used even for the most sensitive LCD, LED, CRT, and OLED screens in proper use. Be at ease knowing that this product is compatible with all the major brands: LG, SONY, Samsung, Sharp, iPad, iPhone, Android screens, Kindle, PC monitors - we’ve got you covered! Can be used as LCD screen cleaner, tv cleaner, smart tv screen cleaner, and more
  • Premium Super Soft Plush Microfiber Cloth - Included in this efficient screen cleaning kit. This screen cleaner spray and wipe has our signature plush microfiber cloth specially designed to comply with screens and monitors and leave them streak-free. Has been shown to effectively absorbs stubborn stains, zero streaks, and no fiber shedding. Always use this together with our screen cleaner for the best results
  • Easy-to-Use Screen Cleaner Kit + microfiber cleaning cloth - The EVEO Screen Cleaning Kit will easily be your new favorite tool when it comes to taking care of the things you love most, quick and easy solution for a streak-free screen. Simply screw on the sprayer gun on the screen cleaner bottle. Spray the cleaning liquid onto the microfiber cloth, then wipe the screen until desired cleanliness & shine is achieved.
  • Quality Screen Care Kit Worth Purchasing - Enjoy a convenient Screen Cleaner anytime, anywhere you need it. Your satisfaction is our top priority. We stand behind the quality of our products and that’s why, you shouldn’t be worrying at all. We manufacture the Best Screen Cleaner. and can be used for laptop cleaning kit, laptop screen cleaner, tv screen cleaner for smart tv. MacBook screen cleaner, monitor cleaner or screen cleaner spray for electronic devices with microfiber cleaning cloth

Define application readiness with healthchecks

A container being started does not necessarily mean the application inside it can accept connections. Add a healthcheck that represents the real readiness condition: for an HTTP service, an endpoint that confirms the application is initialized; for a database, a command that verifies the server accepts requests; for a cache, a probe that confirms the daemon responds. The probe must be available in the image or use a command that the image actually provides.

services:
  api:
    build: .
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
      interval: 5s
      timeout: 3s
      retries: 20

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 5s
      timeout: 3s
      retries: 20

The commands and endpoint in this example are illustrative; adapt them to the software and image used by your project. A weak probe that only checks whether a process exists can let tests start too early. A probe that performs a meaningful application check gives docker compose up --wait a useful condition to wait for.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Make CI configuration explicit

Decide whether the application should connect to a service by a container hostname or a mapped host port. In a runner-machine job, configuration commonly points at localhost and the published port. In a container job, it points at the service label and the service’s internal port. Keep that setting in an environment variable or CI-specific configuration so the workflow does not silently use a developer’s local address.

Build the workflow step by step

1. Check out the commit

Use actions/checkout@v4 before any Compose command. The build context, Compose file, application code, and test files all come from the checked-out revision. If the checkout is omitted, a build may use an empty or unrelated directory on the runner.

2. Start and wait for the stack

Run:

docker compose up --build --wait

--build asks Compose to build images before starting services. --wait waits for services to reach their running or healthy state. Compose also provides --wait-timeout when a project needs a bounded, project-appropriate startup window. Choose a timeout that reflects the stack’s real initialization work; do not compensate for an inaccurate healthcheck with an ever-growing number.

Detached mode leaves services running while the workflow proceeds. If you use a detached invocation explicitly, retain the same readiness and failure-handling approach; the test step must not race the startup step.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Run tests as a one-off container

Use:

docker compose run --rm web pytest

docker compose run creates a temporary container for a one-off command such as tests, a migration, a fixture loader, or an administrative check. The --rm flag removes that container after completion, preventing stopped test containers from obscuring later diagnostics.

By default, run does not create the ports declared by the service. That behavior prevents a one-off test container from accidentally colliding with ports already published by the running stack. If the command genuinely must expose the service’s ports, request service-port behavior explicitly and make sure the chosen ports are free.

Rank #3
BladeHawks RGB Gaming Mouse Pad Extra Large Extended 31.5x12 Inch-Black
  • 【Large size】:Measuring 800 x 300 mm/ 31. 5×12 inches, which is wider and taller than others. Large mouse pad can perfectly fit your keyboard and mouse of any size, and there is also ample space for peripherals such as phones, tablets, etc.
  • 【LED backlight mouse pad】:Blade Hawks RGB mouse pad provides 7 static modes and 7 dynamic modes will give you the options you are looking for. Power-off memory function remembers the last lighting mode you selected. The super glow fiber Chroma will give you a colorful gaming setup that you want.
  • 【Anti-slip rubber base】:Made from Natural rubber, this gaming mousepad will firmly grip your desktop, allowing you to enjoy the ultimate precision in the games you are most passionate about. It also comes with a texture that enhances this ability even further.
  • 【Smooth and waterproof surface】: Micro-textured cloth surface, for extremely precise mouse control and a smooth movement. When liquid splashes on the gaming mouse pad, it forms water droplets and slides down. Will not delay your work or gameplay.
  • 【Plug and play】: This mouse and keyboard pad is powered by USB, plug and play, no driver required. One button control light modes. Press one time to change the lighting mode, press twice to change the brightness, press and hold about 3 seconds turn ON/OFF.

4. Preserve the evidence when a step fails

Diagnostics must run before teardown removes the containers. Guard the diagnostic step with if: failure():

- name: Show status and logs on failure
  if: failure()
  run: |
    docker compose ps
    docker compose logs --no-color

docker compose ps shows which services were created and their current state. docker compose logs --no-color provides readable output for the Actions log and avoids terminal color codes hiding the useful lines. Looking at both commands distinguishes a container that exited immediately from one that is running but not healthy.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

5. Tear down on every outcome

Finish with:

- name: Tear down
  if: always()
  run: docker compose down

if: always() runs the cleanup after successful tests, failed tests, and failed startup. Without it, a failure can leave containers and networks on a self-hosted runner, contaminating the next run. Use the same Compose project context and file options in teardown that you used to start the stack.

Understand networking and database connections

Runner job: mapped ports and localhost

When the workflow runs directly on the runner, publish the database or cache port in Compose and point the test process to the host address:

services:
  db:
    image: postgres:16
    ports:
      - "5432:5432"

The application or test configuration then uses a host such as localhost and the published port. The left-hand port is the address visible to the runner; the right-hand port is the port inside the container. Keep the mapping consistent with the connection string used by the test command.

Container job: service-label hostnames

When the job runs in a container, do not use localhost for a sibling service. Inside the job container, localhost refers to the job container itself. Use the service label supplied to GitHub, such as redis, and the service’s listening port. This is service discovery on the user-defined bridge network, not a host-port lookup.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The distinction also applies to databases. A test running in the job container should use a database hostname such as db if that is the configured service label. A test running on the runner should use the mapped host port. If the same test suite must run in both modes, provide the hostname through an environment variable rather than hard-coding one value.

Make readiness deterministic

There is no universal delay that works for every Compose project. Image extraction, database initialization, migrations, and application startup vary between commits and runners. A fixed sleep 30 can waste time when startup is fast and still fail when startup is slow.

Rank #4
Sale
Vaydeer Wrist Rest for Keyboard and Mouse, Computer Ergonomic Wrist Support Pad, Soft Memory Foam Arm Cushion for Desk, Palm Hand Office Laptop Typing
  • 【Softer and More Comfortable】Vaydeer wrist rest has unique diamond pattern, which is the combination of softness and aesthetics. The materials of wrist rest are improved into higher quality memory foam and covered with silky smooth lycra. The computer wrist rest makes you as comfortable and cushiony as like rest your wrists on clouds.
  • 【Ergonomic Wrist Saver】The wrist rests for keyboard and mouse comes with a 17.32×3.15×0.83 inch keyboard wrist pad and a 5.94×3.15×0.83 inch mouse wrist support. Based on ergonomic design, the unique concave shape is the perfect fit for your wrist joints. The wrist rest pad fits most computer keyboards and laptops, improve hand and wrist posture, release your wrist and arm stress.
  • 【Non-Slip Rubber Bottom】Featuring an anti-skid silicone base on the bottom, this wrist keyboard support stays firmly in place on your desk, preventing the padding from sliding around, ensuring stable and consistent wrist support during extended computer sessions.
  • 【Better Experience & Pain Relief】Our keyboard arm rest is beneficial to alleviate the soreness caused by direct contact and friction between your arm and a hard desk surface, reducing the risk of wrist fatigue or carpal tunnel. The soft texture of memory foam can evenly distribute the pressure around your wrists and provide good support with just enough give.
  • 【Helpful in Multiple Scenarios】Whether you're working, studying, writing, typing, gaming, this keyboard and mouse rest combo is an essential accessory to add comfort and support to your hands and wrists. It’s also a great gift for men, women, family, friend, coworker, gamer, teacher, etc.

Use service healthchecks and start the project with --wait. If the project needs a longer bounded window, add --wait-timeout. The healthcheck should fail until the application can perform the operation the tests depend on. For example, checking that a database process exists is weaker than checking that it accepts authenticated connections.

Custom polling is appropriate only when readiness cannot be represented by a Compose healthcheck or when an external dependency is involved. In that case, poll the actual endpoint or command, stop after a defined timeout, and print the failing service’s status and logs. Do not hide a failed readiness check behind an unbounded loop.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Control exit status and test orchestration

Use run for isolated commands

The one-off pattern is usually the clearest:

docker compose run --rm web pytest

The command’s exit status becomes the step result, while the main services continue running for the duration of the test. The same form works for a migration before tests or a data-validation command after tests. Because service ports are not created automatically for run, accidental port conflicts are less likely.

Use --exit-code-from when a service is the test process

Compose provides --exit-code-from so a selected service determines the command’s exit status. This is useful when the Compose project includes a dedicated test service whose process should control whether the workflow passes. It is a different orchestration style from invoking a one-off command with run: one lets a service’s lifecycle drive the result, while the other lets an explicit workflow step run a command.

Choose one style for a given workflow and make the ownership of the exit code obvious. If a test service exits, still collect docker compose ps and logs before teardown so the failure is diagnosable.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Diagnose common failures

The runner cannot execute Docker commands

Check the runner type first. Docker container actions, job containers, and service containers require Linux. A GitHub-hosted workflow should use an Ubuntu runner; a self-hosted runner must be Linux with Docker installed and usable by the account that runs Actions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Tests report “connection refused”

  • Confirm that the service reached a healthy state before the test step.
  • Check whether the test runs on the runner or in a container.
  • For a runner job, verify the required port is published and use localhost or 127.0.0.1.
  • For a container job, use the service label as the hostname and the container’s listening port.
  • Inspect docker compose ps and docker compose logs --no-color before teardown.

The stack starts but readiness never completes

Inspect the healthcheck command inside the image. A probe can fail because its utility is not installed, its endpoint is bound to a different port, credentials are wrong, or initialization takes longer than the configured retries and timeout. Correct the probe to represent real readiness, then set a bounded --wait-timeout appropriate for the project.

Ports collide during a one-off test

Remember that docker compose run does not publish the service’s declared ports unless you request service-port options. Remove an unnecessary port request from the test command, or choose a free host port when the test genuinely needs external access.

Best Value
Sale
Under Desk Cable Management Tray No Drill, Metal Mesh Cable Management Under Desk with Clamp Mount, 2 Hole Cable Tray with Wire Management and Cord Organizer for Home Office Standing Desk
  • 【No Drill Mounted】Cable management tray can be assembled in as little as 3 minutes or less-simply. Side clips easily clampe the edge of desk, pass through the holes on the sides, and secure excess cables with baskets. Desk cable management supports inward or outward installation to meet your needs in different scenarios, and provides you with great convenience when collecting and organizing wires.
  • 【Rubber Pad Protects Desk】Wire organizer under desk built-in soft rubber pads on the clamp protect your desk from scratches, so you will not damage your furniture or office.
  • 【Sturdy and Beautiful】Cord management under desk is made of high-quality carbon steel and holds about 15 lbs. The wire basket has 2 holes on each side of the tray to enable your cables to pass freely. Cable baskets are suitable for desk thickness use from 0.4" to 2.4".
  • 【Space Saving & Keep Organized】Desk cable management tray holds all your power cords, outlet strips, USB hubs and computer transformers hidden from your feet, and the data cables will not enter the vacuum cleaner to keep your desk clean and tidy. Desk wire organizer is also suitable for use in the kitchen and outdoors.
  • 【Reduce Safety Risks】Cable tray under desk keeps all plugs away from your kids, no more worry about tripping. Using 2 holes wire tray saves extra space, helps you easily cabling and wire protection. The mesh design is not easy to accumulate dust, but avoids safety accidents caused by messy wires.

A later run sees stale containers or data

Use docker compose down at the end of the job to remove the containers and writable-layer data created for that run. If you use docker compose stop instead, stopped containers remain and can affect later commands. On a self-hosted runner, deliberate cleanup is especially important because the machine persists between jobs.

Choose the right cleanup and persistence policy

down is the isolation-oriented default for CI. It removes the Compose containers and writable-layer data so the next run starts from a known state. This is appropriate when each test run should create its own database and cache.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

stop preserves stopped containers. That can be useful for a deliberately reused local environment, but it is usually the wrong default for independent CI runs because leftover state can mask a failure or change test results.

If data must survive the workflow, do not depend on writable container layers. Use a deliberately managed volume or an external service and document its lifecycle. Persistence is a test-design decision: retaining a database can make a migration test possible, while isolating it catches tests that accidentally depend on data from an earlier run.

Decide whether to build or pull images

A build-based workflow uses the checked-out source and runs docker compose up --build --wait. It is the natural choice when the commit under test changes an application image or when the Compose file defines local build contexts.

A pull-based workflow uses images already published to a registry. It can shorten startup when the image is immutable and available to the runner, but the workflow must select the intended image version and still wait for health. Keep the image strategy consistent with the purpose of the job: build the revision being tested, or explicitly pull the artifact whose behavior you want to verify.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A complete implementation checklist

  • The workflow checks out the revision before invoking Compose.
  • The job uses a Linux runner; GitHub-hosted jobs use Ubuntu, and self-hosted runners have Docker installed.
  • The Compose file defines every service required by the tests.
  • Each dependency has a healthcheck that tests meaningful readiness.
  • The startup step uses docker compose up --build --wait or an equivalent command with a bounded wait timeout.
  • The test command runs in the intended service and uses --rm for disposable containers.
  • Tests use localhost only when they run on the runner and ports are mapped; container jobs use service-label hostnames.
  • Failure diagnostics print docker compose ps and docker compose logs --no-color before cleanup.
  • The teardown step uses if: always().
  • The workflow deliberately chooses down for isolation or retained volumes/external services for required persistence.
  • If a dedicated test service controls the run, --exit-code-from is used so its result determines the workflow status.

What a reliable Compose-based CI run looks like

A reliable run has a clear lifecycle: the checked-out commit builds or pulls the intended images; Compose starts every dependency; healthchecks establish readiness; tests execute in an isolated command container; failures preserve service state and logs; and teardown removes the environment regardless of the result. The only project-specific pieces are the service names, test command, healthcheck probes, ports, and persistence policy. Keeping those choices explicit makes the workflow reproducible on every Linux runner.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.