Skip to main content
This guide will help you validate your first container image with Check Image in just a few minutes.

Prerequisites

1

Install Check Image

If you haven’t installed Check Image yet, follow the installation guide.Quick install with Homebrew:
brew tap jarfernandez/tap
brew install check-image
2

Verify Installation

Confirm Check Image is installed correctly:
check-image version --short
Expected output:
v0.19.4

Your First Validation

Let’s validate the official nginx image with a simple age check:
check-image age nginx:latest --max-age 90
This command checks if the nginx:latest image was created within the last 90 days. Images older than this may contain outdated dependencies or security vulnerabilities.

Understanding the Output

Successful validation:
✓ Image is less than 90 days old

Image: nginx:latest
Created: 2026-02-04T23:53:09Z
Age: 28 days
Max Age: 90 days
Failed validation:
✗ Image is older than 90 days

Image: nginx:latest
Created: 2025-10-15T12:30:00Z
Age: 141 days
Max Age: 90 days

Common Validation Checks

Now let’s try the most common security and operational checks:
1

Check Image Size

Validate that an image is smaller than 200MB:
check-image size nginx:latest --max-size 200
This ensures images stay lean and deploy quickly. Large images can:
  • Slow down deployments
  • Increase network transfer costs
  • Contain unnecessary dependencies
2

Check for Root User

Verify the image runs as a non-root user:
check-image root-user nginx:latest
Running containers as root is a security risk. If the container is compromised, the attacker has root privileges.
For nginx, this check will fail because the official image runs as root. Let’s try a safer image:
check-image root-user nginxinc/nginx-unprivileged:latest
3

Check for Secrets

Scan for embedded passwords, tokens, and keys:
check-image secrets myapp:latest
This scans:
  • Environment variables for sensitive patterns (password, secret, token, key)
  • Files across all layers for SSH keys, cloud credentials, password files
Use --skip-env-vars or --skip-files to limit the scan scope.
4

Check Registry Trust

Validate the image comes from a trusted registry:First, create a simple registry policy file:
config/registry-policy.json
{
  "trusted-registries": [
    "docker.io",
    "ghcr.io",
    "gcr.io"
  ]
}
Then run the check:
check-image registry nginx:latest \
  --registry-policy config/registry-policy.json

Run All Checks at Once

Instead of running checks individually, use the all command to run multiple checks:
check-image all nginx:latest \
  --max-age 90 \
  --max-size 200 \
  --skip registry,labels,platform
We skip registry, labels, and platform checks because they require additional configuration files. We’ll cover those in the next section.

Understanding the All Command Output

Text output shows a summary:
✓ Age check passed
✓ Size check passed
✗ Root user check failed
✓ Healthcheck passed
✗ Ports check failed
✓ Secrets check passed
✓ Entrypoint check passed

Summary:
  Total: 7
  Passed: 5
  Failed: 2
  Errored: 0
  Skipped: registry, labels, platform
JSON output provides full details:
check-image all nginx:latest --skip registry,labels,platform -o json

Using Configuration Files

For production use, define all your validation rules in a config file:
1

Create Config File

Create .check-image/config.yaml in your project:
.check-image/config.yaml
checks:
  age:
    max-age: 90
  size:
    max-size: 200
    max-layers: 20
  root-user: {}
  healthcheck: {}
  secrets:
    skip-env-vars: false
    skip-files: false
  entrypoint:
    allow-shell-form: false
  ports:
    allowed-ports:
      - 80
      - 443
      - 8080
  registry:
    registry-policy:
      trusted-registries:
        - docker.io
        - ghcr.io
        - gcr.io
2

Run Validation with Config

Now run all checks defined in the config:
check-image all myapp:latest --config .check-image/config.yaml
This is ideal for:
  • CI/CD pipelines
  • Consistent validation across teams
  • Version-controlled policies

Working with Different Image Sources

Check Image supports multiple image transport formats:
# Default behavior: tries Docker daemon first, then registry
check-image age myapp:latest

JSON Output for Scripting

All commands support JSON output for integration with scripts and tools:
check-image age nginx:latest --max-age 90 -o json
Output:
{
  "check": "age",
  "image": "nginx:latest",
  "passed": true,
  "message": "Image is less than 90 days old",
  "details": {
    "created-at": "2026-02-04T23:53:09Z",
    "age-days": 28.5,
    "max-age": 90
  }
}
Use with jq for parsing:
if check-image age nginx:latest -o json | jq -e '.passed'; then
  echo "Image validation passed"
else
  echo "Image validation failed"
  exit 1
fi

Exit Codes for CI/CD

Check Image uses standard exit codes:
Exit CodeMeaningExample
0Validation succeededAll checks passed
1Validation failedImage too old, runs as root
2Execution errorImage not found, invalid config
Use in scripts:
check-image all myapp:latest --config .check-image/config.yaml
if [ $? -eq 0 ]; then
  echo "✓ All checks passed - safe to deploy"
  docker push myapp:latest
else
  echo "✗ Validation failed - deployment blocked"
  exit 1
fi

Using in CI/CD Pipelines

GitHub Actions

Add to your workflow:
.github/workflows/validate.yml
name: Validate Image
on: [push]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .
      
      - name: Validate image
        uses: jarfernandez/[email protected]
        with:
          image: myapp:${{ github.sha }}
          config: .check-image/config.yaml

Docker

Use the Docker image in any CI system:
docker run --rm \
  -v "$(pwd)/config:/config:ro" \
  ghcr.io/jarfernandez/check-image:latest \
  all myapp:latest \
  --config /config/config.yaml

Next Steps

Now that you’ve validated your first images, explore the full command reference:

Age Check

Validate image freshness and age limits

Size Check

Control image size and layer count

Security Checks

Verify non-root users, secrets, and ports

All Command

Run comprehensive validation suites

Common Issues

Make sure:
  • The image name and tag are correct
  • You have network access to the registry
  • For private registries, you’re authenticated (docker login or use --username/--password-stdin)
  • For local images, Docker daemon is running
This usually means:
  • Invalid command syntax or arguments
  • Missing required configuration files
  • Config file has invalid JSON/YAML syntax
  • Image reference format is incorrect
If installed with go install, version shows as dev. This is normal.For production use with proper version numbers, use:
  • Pre-built binaries from releases
  • Homebrew installation
  • Docker image
  • GitHub Action
For private registries, provide credentials:
# Using environment variables (recommended for CI)
export CHECK_IMAGE_USERNAME=myuser
export CHECK_IMAGE_PASSWORD=mytoken
check-image age myregistry.example.com/myapp:latest

# Using --password-stdin (avoids password in process list)
echo "mytoken" | check-image age myregistry.example.com/myapp:latest \
  --username myuser \
  --password-stdin

# Using Docker config (if already logged in)
docker login myregistry.example.com
check-image age myregistry.example.com/myapp:latest

Build docs developers (and LLMs) love