GitHub Actions Tutorial — Docker Actions

1 minute read

Docker Actions

Docker actions run inside a container, giving you full control over the runtime — any language, any tool, any OS packages. The trade-off is slower startup (image pull) and Linux-only support.


When to Use Docker Actions

Use Case Example
Non-JavaScript language Python, Go, Rust, Ruby
Specific OS packages Custom binaries, system libraries
Consistent environment Exact tool versions across all runners
Complex toolchains Multi-step builds with specific dependencies

Project Structure

my-docker-action/
├── action.yml          # metadata
├── Dockerfile
├── entrypoint.sh       # entry point script
└── README.md

Basic Docker Action

action.yml:


name: 'Lint Markdown'
description: 'Lint markdown files using markdownlint'

inputs:
  path:
    description: 'Path to lint'
    required: false
    default: '.'

runs:
  using: 'docker'
  image: 'Dockerfile'
  args:
    - ${{ inputs.path }}

Dockerfile:

FROM node:20-alpine

RUN npm install -g markdownlint-cli

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh:

#!/bin/sh
set -e

LINT_PATH="${1:-.}"
echo "Linting markdown files in: $LINT_PATH"
markdownlint "$LINT_PATH" --config .markdownlint.json || true

Pre-Built Image

Skip the build step by pointing to a pre-built image:


runs:
  using: 'docker'
  image: 'docker://ghcr.io/my-org/my-action:v1'
  args:
    - ${{ inputs.path }}

Pros: Faster (no Docker build during the workflow). Cons: Must maintain and publish the image separately.


Environment Variables and Inputs

Docker actions receive inputs as environment variables prefixed with INPUT_:


inputs:
  config-file:
    description: 'Config file path'
    required: true

Inside the container, the input is available as:

  • INPUT_CONFIG-FILE (with the INPUT_ prefix, uppercased)

In your entrypoint script:

#!/bin/sh
CONFIG="${INPUT_CONFIG-FILE}"
echo "Using config: $CONFIG"

Docker Action Limitations

Limitation Detail
Linux only Docker actions only run on Linux runners
Slower startup Image build or pull adds 10-60 seconds
File system Workspace is mounted at /github/workspace
Networking Container shares the runner’s network
No services Can’t define services: inside a Docker action

Common Mistakes

Mistake Fix
Action fails on Windows/macOS Docker actions are Linux-only
Entrypoint not executable Add RUN chmod +x /entrypoint.sh
Files not found Workspace is at /github/workspace inside the container
Slow action Use a pre-built image instead of building from Dockerfile

Quick Reference

Concept Detail
Runtime using: 'docker'
Local image image: 'Dockerfile'
Pre-built image: 'docker://registry/image:tag'
Arguments args: array passed to ENTRYPOINT
Inputs Available as INPUT_<NAME> env vars
Platform Linux runners only

← Previous: JavaScript Actions

Next: Action Metadata →

Updated: