Pipery Docker CI#

Reusable GitHub Action for a complete Docker CI pipeline with structured logging via Pipery.

GitHub Marketplace Version License: MIT

Table of Contents#

Quick Start#

name: CI
on: [push, pull_request]

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pipery-dev/docker-ci@v1.1.0
        with:
          project_path: .
          image_name: ghcr.io/${{ github.repository }}
          image_tag: ${{ github.sha }}
          registry_password: ${{ secrets.GITHUB_TOKEN }}
          github_token: ${{ secrets.GITHUB_TOKEN }}

Pipeline Overview#

StepToolSkip InputDescription
Linthadolintskip_lintValidates Dockerfile syntax and best practices
SASTTrivyskip_sastDetects Docker image vulnerabilities
SCAGrype / syftskip_scaIdentifies vulnerable dependencies
Builddocker buildskip_buildBuilds Docker image
TestContainer smoke testskip_testRuns container tests
VersionSemantic versioningskip_versioningBumps version and creates git tag
PackagingImage taggingskip_packagingTags image with versions
Releasedocker pushskip_releasePushes to container registry
ReintegrateGit mergeskip_reintegrationMerges back to default branch

Configuration Options#

NameDefaultDescription
project_path.Path to the project source tree.
config_file``Path to config file for the action.
dockerfileDockerfileDockerfile name relative to project_path.
image_name``Name of the Docker image to build.
image_taglatestTag for the Docker image.
registryghcr.ioContainer registry hostname.
registry_username``Username for registry login.
registry_password``Password or token for registry login.
build_args``Comma-separated build args in VAR=val format.
platformslinux/amd64Platforms to build for (e.g., linux/amd64,linux/arm64).
tests_path``Command or script to run inside container for testing.
version_bumppatchVersion bump type: patch, minor, or major.
github_token``GitHub token for reintegration.
log_filepipery.jsonlPath to the JSONL structured log file.
skip_lintfalseSkip the hadolint step.
skip_sastfalseSkip the SAST step.
skip_scafalseSkip the SCA step.
skip_buildfalseSkip the Docker build step.
skip_testfalseSkip the container smoke test step.
skip_versioningfalseSkip the versioning step.
skip_packagingfalseSkip the packaging (image tagging) step.
skip_releasefalseSkip the release (registry push) step.
skip_reintegrationfalseSkip the reintegration step.

Usage Examples#

Example 1: Basic Docker image build and push#

name: CI
on: [push, pull_request]

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pipery-dev/docker-ci@v1.1.0
        with:
          project_path: .
          image_name: ghcr.io/${{ github.repository }}
          image_tag: ${{ github.sha }}
          registry_username: ${{ secrets.REGISTRY_USERNAME }}
          registry_password: ${{ secrets.REGISTRY_PASSWORD }}
          github_token: ${{ secrets.GITHUB_TOKEN }}

Example 2: Build for multiple platforms (amd64 + arm64)#

- uses: pipery-dev/docker-ci@v1.1.0
  with:
    project_path: .
    image_name: ghcr.io/${{ github.repository }}
    platforms: linux/amd64,linux/arm64
    registry_password: ${{ secrets.GITHUB_TOKEN }}
    github_token: ${{ secrets.GITHUB_TOKEN }}

Example 3: Skip security scanning for speed#

- uses: pipery-dev/docker-ci@v1.1.0
  with:
    project_path: .
    image_name: myapp
    skip_sast: true
    skip_sca: true
    github_token: ${{ secrets.GITHUB_TOKEN }}

Example 4: Custom Dockerfile with build arguments#

- uses: pipery-dev/docker-ci@v1.1.0
  with:
    project_path: ./docker
    dockerfile: Dockerfile.prod
    image_name: myapp
    build_args: BUILD_DATE=${{ github.event.head_commit.timestamp }},VCS_REF=${{ github.sha }}
    registry_password: ${{ secrets.REGISTRY_PASSWORD }}

Example 5: Container health check test#

- uses: pipery-dev/docker-ci@v1.1.0
  with:
    project_path: .
    image_name: myapp
    tests_path: curl http://localhost:8080/health || exit 1
    github_token: ${{ secrets.GITHUB_TOKEN }}

Example 6: Minor version bump for release#

- uses: pipery-dev/docker-ci@v1.1.0
  with:
    project_path: .
    image_name: ghcr.io/${{ github.repository }}
    version_bump: minor
    registry_password: ${{ secrets.GITHUB_TOKEN }}
    github_token: ${{ secrets.GITHUB_TOKEN }}

GitLab CI#

Use the GitLab mirror template when .gitlab-ci.yml is published for this pipeline family. Import it from the mirrored GitLab project or use it as a reference implementation for running the same Pipery pipeline outside GitHub Actions.

The GitLab pipeline maps action inputs to CI/CD variables, publishes pipery.jsonl as an artifact, and maintains the same skip controls. Store credentials as protected GitLab CI/CD variables.

include:
  - project: pipery-dev/docker-ci
    ref: v1.1.0
    file: /.gitlab-ci.yml

GitLab CI Variables#

Configure these protected variables in Settings > CI/CD > Variables:

  • REGISTRY_PASSWORD - Registry authentication token
  • GITHUB_TOKEN - GitHub API access for reintegration
  • IMAGE_NAME - Docker image name (e.g., ghcr.io/org/app)

Bitbucket Pipelines#

Bitbucket Cloud pipelines provide an alternative to GitHub Actions. Use Bitbucket shared pipeline imports to reference the exported Pipery pipeline instead of copying YAML into every application repository.

Getting Started#

  1. Add a Bitbucket import source for the shared Pipery pipeline and import the exported pipeline by name:
definitions:
  imports:
    pipery-shared: pipery-dev/docker-ci:v1.1.0
    pipery-custom: pipery-dev/docker-ci:v1.1.0:.bitbucket/shared-pipelines.yml

pipelines:
  branches:
    main:
      import: pipery-docker-ci@pipery-shared

  custom:
    run-pipery:
      import: pipery-docker-ci@pipery-custom

Use {project-path}/{repo-slug}:{branch-or-tag} for a shared repository bitbucket-pipelines.yml, or {project-path}/{repo-slug}:{branch-or-tag}:{config-filepath} for another exported YAML file.

  1. Configure Protected Variables in Repository Settings > Pipelines > Repository Variables:
    • REGISTRY_PASSWORD - Container registry password or token
    • GITHUB_TOKEN - GitHub API access (for reintegration)
    • IMAGE_NAME - Docker image name (e.g., ghcr.io/org/app)
  2. Commit and push to trigger the pipeline

Pipeline Stages#

The Bitbucket equivalent follows the same structure:

checkout → setup → lint (hadolint) → SAST (Trivy) → SCA (Grype) → build → test → versioning → packaging → release → reintegration → logs

Skip Flags#

Disable any stage using environment variables:

  • SKIP_LINT, SKIP_SAST, SKIP_SCA, SKIP_BUILD, SKIP_TEST, SKIP_VERSIONING, SKIP_PACKAGING, SKIP_RELEASE, SKIP_REINTEGRATION

Example: Set SKIP_LINT=true to skip Dockerfile linting.

Features#

  • Docker image linting (hadolint)
  • Container vulnerability scanning (Trivy, Grype)
  • Multi-platform builds (amd64, arm64, etc.)
  • Custom build arguments support
  • Container smoke testing
  • Automatic versioning and tagging
  • Docker registry push with auth
  • JSONL-based pipeline logging
  • 30-90 day artifact retention

About Pipery#

Pipery Pipery is an open-source CI/CD observability platform. Every step script runs under psh (Pipery Shell), which intercepts all commands and emits structured JSONL events — giving you full visibility into your pipeline without any manual instrumentation.

Development#

# Run the action locally against test-project/
pipery-actions test --repo .

# Regenerate docs
pipery-actions docs --repo .

# Dry-run release
pipery-actions release --repo . --dry-run