Skip to content
Latchkey

Running Containers in a GitHub Actions Workflow

GitHub Actions can run your whole job inside a container, attach service containers, or just hand you a Docker daemon.

GitHub Actions has first-class container support, but the three options serve different purposes. This lesson shows when to use a container job, when to use service containers, and when to drive Docker yourself with run steps.

Option 1: run the whole job in a container

The job-level container key runs every step inside the named image, so you control the exact toolchain.

.github/workflows/test.yml
jobs:
  test:
    runs-on: ubuntu-latest
    container: node:20-slim
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

Option 2: service containers for dependencies

Use services to spin up databases or queues your tests need. Actions networks them and exposes ports.

.github/workflows/test.yml
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: postgres
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - run: npm test
        env:
          DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres

Option 3: drive Docker yourself

On a standard runner the Docker daemon is already available, so you can docker build and docker run directly in run steps. This is the most flexible option and matches how you build images for a registry.

.github/workflows/test.yml
- run: docker build -t myapp:ci .
- run: docker run --rm myapp:ci npm test

Choosing between them

Use a container job when you need a pinned toolchain. Use service containers for external dependencies like databases. Drive Docker yourself when you are building and pushing an image, which is the common path for delivery pipelines.

Key takeaways

  • The container key runs an entire job inside an image for a pinned toolchain.
  • Service containers provide databases and queues with health checks and networking.
  • You can also run docker build and docker run directly on a standard runner.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →