Catch container runtime issues before they catch you
Features | Installation | Usage | Rules | CI/CD
Building Go applications for containers seems straightforward until runtime failures occur:
- Binary crashes with
exec format errorin scratch images exec.Command("curl", ...)fails silently in distroless containers- CGO binaries segfault on Alpine due to musl/glibc mismatch
- Shell scripts that worked in development break in production
go-runtime-compat statically analyzes your Go code and Dockerfiles to detect these issues before deployment.
| Feature | Description |
|---|---|
| Go Code Analysis | Detects exec.Command usage, CGO dependencies, and system binary calls |
| Dockerfile Analysis | Analyzes multi-stage builds, base images, and build configurations |
| Image Inspection | Checks for dynamic linking issues using ldd |
| Correlation Engine | Cross-references code dependencies with container capabilities |
| Multiple Outputs | CLI (human-readable), JSON, and CSV formats |
Download the latest release for your platform from GitHub Releases:
# Linux (amd64)
curl -LO https://github.com/Jonsy13/go-runtime-compat/releases/latest/download/go-runtime-compat_linux_amd64.tar.gz
tar -xzf go-runtime-compat_linux_amd64.tar.gz
sudo mv go-runtime-compat /usr/local/bin/
# Linux (arm64)
curl -LO https://github.com/Jonsy13/go-runtime-compat/releases/latest/download/go-runtime-compat_linux_arm64.tar.gz
tar -xzf go-runtime-compat_linux_arm64.tar.gz
sudo mv go-runtime-compat /usr/local/bin/
# macOS (Apple Silicon)
curl -LO https://github.com/Jonsy13/go-runtime-compat/releases/latest/download/go-runtime-compat_darwin_arm64.tar.gz
tar -xzf go-runtime-compat_darwin_arm64.tar.gz
sudo mv go-runtime-compat /usr/local/bin/
# macOS (Intel)
curl -LO https://github.com/Jonsy13/go-runtime-compat/releases/latest/download/go-runtime-compat_darwin_amd64.tar.gz
tar -xzf go-runtime-compat_darwin_amd64.tar.gz
sudo mv go-runtime-compat /usr/local/bin/go install github.com/Jonsy13/go-runtime-compat@latestgit clone https://github.com/Jonsy13/go-runtime-compat.git
cd go-runtime-compat
go build .# Analyze Go source code
go-runtime-compat analyze --project ./myapp
# Analyze a Dockerfile
go-runtime-compat analyze --dockerfile ./Dockerfile
# Analyze a built Docker image
go-runtime-compat analyze --image myapp:latest
# Full analysis (recommended)
go-runtime-compat analyze --project ./myapp --dockerfile ./Dockerfile
# Strict mode - exit non-zero on warnings
go-runtime-compat analyze --project . --dockerfile ./Dockerfile --strict# Human-readable CLI output (default)
go-runtime-compat analyze --project . --output cli
# JSON for programmatic processing
go-runtime-compat analyze --project . --output json
# CSV for spreadsheet analysis
go-runtime-compat analyze --project . --output csvgo-runtime-compat rules
go-runtime-compat rules --output json| Rule | Severity | Description |
|---|---|---|
CCG001 |
Warning | External binary execution via exec.Command |
CCG002 |
Warning | Shell command execution (sh, bash, etc.) |
CCG003 |
Warning | System binary dependencies |
CCG004 |
Info | Binary usage summary across codebase |
CCG005 |
Warning | Dynamic/unresolved command in exec.Command |
CCG010 |
Warning | CGO_ENABLED=1 detected |
CCG011 |
Error | Direct CGO import (import "C") |
| Rule | Severity | Description |
|---|---|---|
CCG030 |
Info | Scratch base image - requires static linking |
CCG031 |
Info | Distroless base image - no shell available |
CCG032 |
Warning | Alpine base image - uses musl instead of glibc |
CCG033 |
Warning | Go build without CGO_ENABLED=0 in minimal image |
CCG040 |
Info | Multi-stage build detected |
CCG041 |
Warning | Build/runtime stage CGO mismatch |
| Rule | Severity | Description |
|---|---|---|
CCG100 |
Error | Shell command used but base image has no shell |
CCG101 |
Error | Required binary unavailable in base image |
CCG102 |
Warning | exec.Command with minimal base image |
CCG103 |
Error | CGO detected but base image lacks glibc |
CCG104 |
Error | CGO binary with Alpine (musl/glibc mismatch) |
╔══════════════════════════════════════════════════════════════════╗
║ go-runtime-compat Analysis Report ║
╚══════════════════════════════════════════════════════════════════╝
📊 Summary
──────────────────────────────────────────────────────────────────
Total Findings: 3
❌ Errors: 1
⚠️ Warnings: 2
ℹ️ Info: 0
❌ Status: FAILED
📋 Findings by Category
──────────────────────────────────────────────────────────────────
📁 Correlation (1 finding)
────────────────────────────────────────────────────────────
❌ [CCG100] Shell command 'bash' used but Dockerfile uses scratch which has no shell
📍 Location: main.go:42
📄 Code: exec.Command("bash", "-c", "echo hello")
💡 Suggestion: Either use a base image with a shell or remove shell command usage
📁 Exec Command (2 findings)
────────────────────────────────────────────────────────────
⚠️ [CCG002] Shell 'bash' executed - verify shell is available in your container
📍 Location: main.go:42
💡 Suggestion: Ensure your base image has a shell
name: Go Runtime Compatibility Check
on: [push, pull_request]
jobs:
compat-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Install go-runtime-compat
run: go install github.com/Jonsy13/go-runtime-compat@latest
- name: Run compatibility check
run: go-runtime-compat analyze --project . --dockerfile ./Dockerfile --strictcontainer-compatibility:
image: golang:1.25
stage: test
script:
- go install github.com/Jonsy13/go-runtime-compat@latest
- go-runtime-compat analyze --project . --dockerfile ./Dockerfile --output json > compat-report.json
artifacts:
paths:
- compat-report.json
reports:
codequality: compat-report.json#!/bin/sh
# .git/hooks/pre-commit
if command -v go-runtime-compat &> /dev/null; then
go-runtime-compat analyze --project . --dockerfile ./Dockerfile --strict
figo-runtime-compat works seamlessly with AI coding assistants and autonomous agents. The JSON output format is designed for programmatic consumption.
When working with AI agents (Claude, GPT, Copilot, etc.), use JSON output for structured analysis:
go-runtime-compat analyze --project . --dockerfile ./Dockerfile --output jsonExample JSON output:
{
"findings": [
{
"rule_id": "CCG100",
"category": "correlation",
"severity": "error",
"message": "Shell command 'bash' used but Dockerfile uses scratch which has no shell",
"location": "main.go:42",
"suggestion": "Use a base image with a shell or remove shell command usage"
}
],
"summary": {
"total_findings": 1,
"error_count": 1,
"warning_count": 0,
"info_count": 0,
"passed": false
}
}Add this to your AI agent's system prompt for container-aware Go development:
When working on Go projects with Dockerfiles, run `go-runtime-compat analyze --project . --dockerfile ./Dockerfile --output json` to detect container compatibility issues before deployment. Parse the JSON output to identify:
- exec.Command calls that may fail in minimal containers
- CGO dependencies incompatible with scratch/alpine images
- Missing binaries in the target container environment
Always address "error" severity findings before building container images.
For Model Context Protocol (MCP) compatible agents, expose go-runtime-compat as a tool:
{
"name": "analyze_container_compatibility",
"description": "Analyze Go project for container runtime compatibility issues",
"input_schema": {
"type": "object",
"properties": {
"project_path": {
"type": "string",
"description": "Path to Go project directory"
},
"dockerfile_path": {
"type": "string",
"description": "Path to Dockerfile"
}
},
"required": ["project_path"]
}
}Tool implementation:
go-runtime-compat analyze --project "$project_path" --dockerfile "$dockerfile_path" --output jsonimport subprocess
import json
def check_container_compatibility(project_path: str, dockerfile_path: str = None) -> dict:
"""Run go-runtime-compat and return structured findings."""
cmd = ["go-runtime-compat", "analyze", "--project", project_path, "--output", "json"]
if dockerfile_path:
cmd.extend(["--dockerfile", dockerfile_path])
result = subprocess.run(cmd, capture_output=True, text=True)
return json.loads(result.stdout)
# Use in agent loop
findings = check_container_compatibility("./myapp", "./Dockerfile")
if not findings["summary"]["passed"]:
errors = [f for f in findings["findings"] if f["severity"] == "error"]
# Agent can now reason about and fix these issuesFROM golang:1.25 AS builder
WORKDIR /app
COPY . .
# Disable CGO for static binary
ENV CGO_ENABLED=0
# Build with optimizations
RUN go build -ldflags="-s -w" -o /app/server .
FROM scratch
COPY --from=builder /app/server /server
ENTRYPOINT ["/server"]Key points:
- Always set
CGO_ENABLED=0 - Avoid
exec.Commandcalls - use pure Go alternatives - No shell available - use direct binary entrypoint
FROM golang:1.25-alpine AS builder
WORKDIR /app
# Option 1: Disable CGO (recommended)
ENV CGO_ENABLED=0
RUN go build -o /app/server .
# Option 2: Build with musl (if CGO required)
# RUN apk add --no-cache gcc musl-dev
# RUN go build -o /app/server .
FROM alpine:3.19
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/server /server
ENTRYPOINT ["/server"]Key points:
- Alpine uses musl libc, not glibc
- CGO binaries built with glibc will fail
- Either disable CGO or compile against musl
go-runtime-compat/
├── main.go # CLI entry point
└── internal/
├── analyzer/
│ └── go_analyzer.go # Go AST analysis
├── cli/
│ └── root.go # Cobra command definitions
├── correlator/
│ └── correlator.go # Cross-reference engine
├── docker/
│ ├── dockerfile_analyzer.go # Dockerfile parsing
│ └── image_inspector.go # Docker image inspection
├── report/
│ └── reporter.go # Output formatting
└── rules/
├── engine.go # Rules evaluation
└── types.go # Type definitions
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Commit your changes:
git commit -m 'Add my feature' - Push to the branch:
git push origin feature/my-feature - Open a Pull Request
# Run tests
go test ./...
# Build
go build .
# Test against sample project
./go-runtime-compat analyze --project ./testdata/sample --dockerfile ./testdata/DockerfileThis project is licensed under the MIT License - see the LICENSE file for details.
Built with Cobra