Docker workflow (mujocolab/mjlab)
The Docker workflow from mujocolab/mjlab, explained and optimized by Latchkey.
CI health: B - good
Point runs-on at Latchkey and get job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Docker workflow from the mujocolab/mjlab repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: Docker
on:
workflow_dispatch:
push:
branches:
- "main"
pull_request:
types:
- opened
- reopened
- synchronize
- ready_for_review
concurrency:
group: docker-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
shell: bash
env:
FORCE_COLOR: 1
REGISTRY: ghcr.io
IMAGE_NAME: mujocolab/mjlab
permissions:
id-token: write
packages: write
jobs:
check_paths:
runs-on: ubuntu-22.04
outputs:
build: ${{ steps.filter.outputs.any }}
steps:
- uses: actions/checkout@v6
- id: filter
uses: dorny/paths-filter@v3
with:
list-files: shell
filters: |
any:
- ".github/workflows/docker.yml"
- "Dockerfile"
build:
needs: check_paths
if: ${{ needs.check_paths.outputs.build == 'true' }}
runs-on: ubuntu-22.04
steps:
- name: Checkout repo
uses: actions/checkout@v6
- name: Setup Docker buildx
uses: docker/setup-buildx-action@v3
- name: Log into registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.ref == 'refs/heads/main' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: |
type=gha
type=registry,ref=ghcr.io/mujocolab/mjlab/mjlab:buildcache
cache-to: |
type=gha,mode=max
type=registry,ref=ghcr.io/mujocolab/mjlab/mjlab:buildcache,mode=max
platforms: linux/amd64
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Docker on: workflow_dispatch: push: branches: - "main" pull_request: types: - opened - reopened - synchronize - ready_for_review concurrency: group: docker-${{ github.ref }} cancel-in-progress: true defaults: run: shell: bash env: FORCE_COLOR: 1 REGISTRY: ghcr.io IMAGE_NAME: mujocolab/mjlab permissions: id-token: write packages: write jobs: check_paths: timeout-minutes: 30 runs-on: latchkey-small outputs: build: ${{ steps.filter.outputs.any }} steps: - uses: actions/checkout@v6 - id: filter uses: dorny/paths-filter@v3 with: list-files: shell filters: | any: - ".github/workflows/docker.yml" - "Dockerfile" build: timeout-minutes: 30 needs: check_paths if: ${{ needs.check_paths.outputs.build == 'true' }} runs-on: latchkey-small steps: - name: Checkout repo uses: actions/checkout@v6 - name: Setup Docker buildx uses: docker/setup-buildx-action@v3 - name: Log into registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract Docker metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch type=raw,value=latest,enable={{is_default_branch}} - name: Build and push Docker image uses: docker/build-push-action@v6 with: context: . push: ${{ github.ref == 'refs/heads/main' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: | type=gha type=registry,ref=ghcr.io/mujocolab/mjlab/mjlab:buildcache cache-to: | type=gha,mode=max type=registry,ref=ghcr.io/mujocolab/mjlab/mjlab:buildcache,mode=max platforms: linux/amd64
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Add a job timeout so a hung step cannot burn hours of runner time.
5 third-party actions are referenced by a movable tag. Pin them to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Container pulls and builds
This workflow runs 2 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.