diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..65203fb --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +.git +.github +.claude +.DS_Store +.gitignore +.dockerignore +LICENSE +README.md +*.tar +*.tar.gz diff --git a/.github/workflows/build-base.yaml b/.github/workflows/build-base.yaml deleted file mode 100644 index 2c267b8..0000000 --- a/.github/workflows/build-base.yaml +++ /dev/null @@ -1,43 +0,0 @@ -name: Build base image - -on: - workflow_dispatch: - push: - branches: - - main - schedule: - - cron: "0 19 * * *" - -permissions: - id-token: write - contents: read - -jobs: - build-images: - runs-on: ubuntu-latest - strategy: - matrix: - platform: [linux/amd64, linux/arm64, macOS/arm64, macOS/amd64, windows/amd64, windows/arm64, linux/arm64/v8] - steps: - - name: "Checkout GitHub Action" - uses: actions/checkout@v4 - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ secrets.REGISTRY_USERNAME }} - password: ${{ secrets.REGISTRY_PASSWORD }} - - - name: Set platform tag - id: platform_tag - run: echo "PLATFORM_TAG=${{ matrix.platform }}" | sed 's/\//-/g' >> $GITHUB_ENV - - - name: Build and push - uses: docker/build-push-action@v6 - with: - platform: ${{ matrix.platform }} - context: . - push: true - tags: | - ghcr.io/${{ github.repository_owner }}/builder:${{ env.PLATFORM_TAG }} diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..c6a269a --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,157 @@ +name: Build, scan, and publish + +on: + push: + branches: [main] + tags: ["v*"] + pull_request: + branches: [main] + schedule: + - cron: "0 6 * * 1" # weekly Monday 06:00 UTC + workflow_dispatch: + +permissions: + contents: read + packages: write + security-events: write + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + # ------------------------------------------------------------------- + # Lint — hadolint Dockerfile linting + # ------------------------------------------------------------------- + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Lint Dockerfile + uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: Dockerfile + + # ------------------------------------------------------------------- + # Build — multi-platform image, push to GHCR + # ------------------------------------------------------------------- + build: + runs-on: ubuntu-latest + needs: lint + outputs: + digest: ${{ steps.build-push.outputs.digest }} + steps: + - uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata for tags and labels + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=raw,value={{date 'YYYYMMDD'}},enable={{is_default_branch}} + type=raw,value=latest,enable={{is_default_branch}} + type=sha,prefix= + + - name: Build and push + id: build-push + uses: docker/build-push-action@v6 + with: + context: . + # Multi-platform on push; single platform on PR (--load does not + # support manifest lists, so we build only the runner's native arch) + platforms: ${{ github.event_name != 'pull_request' && 'linux/amd64,linux/arm64' || 'linux/amd64' }} + push: ${{ github.event_name != 'pull_request' }} + load: ${{ github.event_name == 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # ------------------------------------------------------------------- + # Scan — Trivy vulnerability scanning with SARIF upload + # ------------------------------------------------------------------- + scan: + runs-on: ubuntu-latest + needs: build + if: github.event_name != 'pull_request' + steps: + - uses: actions/checkout@v4 + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@0.28.0 + with: + image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build.outputs.digest }} + format: sarif + output: trivy-results.sarif + severity: CRITICAL,HIGH + + - name: Upload Trivy SARIF to GitHub Security + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: trivy-results.sarif + + # ------------------------------------------------------------------- + # Test — run validate-tools.sh inside the built image + # ------------------------------------------------------------------- + test: + runs-on: ubuntu-latest + needs: build + if: github.event_name != 'pull_request' + steps: + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Pull and validate tools + run: | + docker pull "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build.outputs.digest }}" + docker run --rm "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build.outputs.digest }}" \ + /usr/local/bin/validate-tools.sh + + # ------------------------------------------------------------------- + # Size report — output image size to step summary + # ------------------------------------------------------------------- + size-report: + runs-on: ubuntu-latest + needs: build + if: github.event_name != 'pull_request' + steps: + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Report image size + run: | + docker pull "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build.outputs.digest }}" + SIZE=$(docker image inspect "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build.outputs.digest }}" --format '{{.Size}}') + SIZE_MB=$((SIZE / 1024 / 1024)) + echo "## Image Size Report" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "| Metric | Value |" >> "$GITHUB_STEP_SUMMARY" + echo "|--------|-------|" >> "$GITHUB_STEP_SUMMARY" + echo "| Raw size | ${SIZE_MB} MB |" >> "$GITHUB_STEP_SUMMARY" + echo "| Digest | \`${{ needs.build.outputs.digest }}\` |" >> "$GITHUB_STEP_SUMMARY" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..99f2536 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# OS +.DS_Store +Thumbs.db + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# Docker artifacts +*.tar +*.tar.gz + +# Claude +.claude/ diff --git a/.hadolint.yaml b/.hadolint.yaml new file mode 100644 index 0000000..84ddffb --- /dev/null +++ b/.hadolint.yaml @@ -0,0 +1,6 @@ +# DL3008: Pin versions in apt-get install +# Ignored because system packages receive security patches via the weekly +# scheduled rebuild. Pinning apt versions across amd64/arm64 is fragile +# and defeats the purpose of automatic security updates. +ignored: + - DL3008 diff --git a/Dockerfile b/Dockerfile index 8b3a448..2f5f46f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,84 +1,201 @@ -# Stage 1: Build stage -FROM ubuntu as builder - -# Install dependencies -RUN apt-get update && apt-get install -y \ - curl \ - unzip \ - gnupg \ - software-properties-common \ - apt-transport-https \ - ca-certificates \ - lsb-release \ - jq \ - vim \ +# syntax=docker/dockerfile:1 +# ============================================================================ +# Builder — pre-configured dev environment for debugging and building images +# ============================================================================ + +# --------------------------------------------------------------------------- +# Pinned tool versions — update these ARGs to bump versions +# --------------------------------------------------------------------------- +ARG UBUNTU_VERSION=24.04 + +ARG AWSCLI_VERSION=2.24.4 +ARG GCLOUD_VERSION=514.0.0 +ARG VAULT_VERSION=1.18.4 +ARG GO_VERSION=1.23.5 +ARG NODE_MAJOR=22 +ARG KUBECTL_VERSION=1.32.1 +ARG HELM_VERSION=3.17.0 +ARG TERRAFORM_VERSION=1.10.5 +ARG TRIVY_VERSION=0.69.2 +ARG HADOLINT_VERSION=2.12.0 +ARG DIVE_VERSION=0.12.0 +ARG YQ_VERSION=4.45.1 + +# ============================================================================ +# Stage 1: downloader — fetch and extract standalone binaries +# ============================================================================ +FROM ubuntu:${UBUNTU_VERSION} AS downloader + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +ARG TARGETARCH + +ARG AWSCLI_VERSION +ARG GCLOUD_VERSION +ARG VAULT_VERSION +ARG GO_VERSION +ARG KUBECTL_VERSION +ARG HELM_VERSION +ARG TERRAFORM_VERSION +ARG TRIVY_VERSION +ARG HADOLINT_VERSION +ARG DIVE_VERSION +ARG YQ_VERSION + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + unzip \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /staging + +# --- AWS CLI v2 --- +RUN ARCH_SUFFIX=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "x86_64") \ + && curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-${ARCH_SUFFIX}-${AWSCLI_VERSION}.zip" -o awscli.zip \ + && unzip -oq awscli.zip \ + && ./aws/install --install-dir /opt/aws-cli --bin-dir /usr/local/bin \ + && rm -rf awscli.zip aws/ + +# --- Google Cloud CLI --- +RUN ARCH_SUFFIX=$([ "$TARGETARCH" = "arm64" ] && echo "arm" || echo "x86_64") \ + && curl -fsSL "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-${GCLOUD_VERSION}-linux-${ARCH_SUFFIX}.tar.gz" \ + | tar -xz -C /opt \ + && /opt/google-cloud-sdk/install.sh --quiet --path-update=false + +# --- HashiCorp Vault --- +RUN curl -fsSL "https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_${TARGETARCH}.zip" -o vault.zip \ + && unzip -oq vault.zip -d /usr/local/bin \ + && rm vault.zip + +# --- Go --- +RUN curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" \ + | tar -xz -C /usr/local + +# --- kubectl --- +RUN curl -fsSL "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/${TARGETARCH}/kubectl" \ + -o /usr/local/bin/kubectl \ + && chmod +x /usr/local/bin/kubectl + +# --- Helm --- +RUN curl -fsSL "https://get.helm.sh/helm-v${HELM_VERSION}-linux-${TARGETARCH}.tar.gz" \ + | tar -xz --strip-components=1 -C /usr/local/bin linux-${TARGETARCH}/helm + +# --- Terraform --- +RUN curl -fsSL "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_${TARGETARCH}.zip" -o terraform.zip \ + && unzip -oq terraform.zip -d /usr/local/bin \ + && rm terraform.zip + +# --- Trivy --- +RUN ARCH_SUFFIX=$([ "$TARGETARCH" = "arm64" ] && echo "ARM64" || echo "64bit") \ + && curl -fsSL "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-${ARCH_SUFFIX}.tar.gz" \ + | tar -xz -C /usr/local/bin trivy + +# --- hadolint --- +RUN ARCH_SUFFIX=$([ "$TARGETARCH" = "arm64" ] && echo "arm64" || echo "x86_64") \ + && curl -fsSL "https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-Linux-${ARCH_SUFFIX}" \ + -o /usr/local/bin/hadolint \ + && chmod +x /usr/local/bin/hadolint + +# --- dive --- +RUN ARCH_SUFFIX=$([ "$TARGETARCH" = "arm64" ] && echo "arm64" || echo "amd64") \ + && curl -fsSL "https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_${ARCH_SUFFIX}.tar.gz" \ + | tar -xz -C /usr/local/bin dive + +# --- yq --- +RUN ARCH_SUFFIX=$([ "$TARGETARCH" = "arm64" ] && echo "arm64" || echo "amd64") \ + && curl -fsSL "https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/yq_linux_${ARCH_SUFFIX}" \ + -o /usr/local/bin/yq \ + && chmod +x /usr/local/bin/yq + + +# ============================================================================ +# Stage 2: final — assemble the runtime image +# ============================================================================ +FROM ubuntu:${UBUNTU_VERSION} AS final + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +ARG NODE_MAJOR +ARG TARGETARCH + +ENV DEBIAN_FRONTEND=noninteractive +ENV PATH="/opt/google-cloud-sdk/bin:/usr/local/go/bin:${PATH}" + +# --- System packages, debugging tools, and build utilities --- +RUN apt-get update && apt-get install -y --no-install-recommends \ + # core utilities + ca-certificates \ + curl \ + gnupg \ + unzip \ + jq \ + vim \ + git \ + make \ + wget \ + shellcheck \ + # debugging + strace \ + ltrace \ + tcpdump \ + net-tools \ + dnsutils \ + htop \ + # python + python3 \ + python3-pip \ + python3-venv \ + && rm -rf /var/lib/apt/lists/* + +# --- Azure CLI via pip in a venv (no piped scripts) --- +RUN python3 -m venv /opt/azure-cli \ + && /opt/azure-cli/bin/pip install --no-cache-dir azure-cli \ + && ln -s /opt/azure-cli/bin/az /usr/local/bin/az + +# --- Node.js via NodeSource (pinned major version) --- +RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ + | gpg --dearmor -o /usr/share/keyrings/nodesource.gpg \ + && echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODE_MAJOR}.x nodistro main" \ + > /etc/apt/sources.list.d/nodesource.list \ + && apt-get update && apt-get install -y --no-install-recommends nodejs \ && rm -rf /var/lib/apt/lists/* -# Install AWS CLI -RUN ARCH=$(dpkg --print-architecture) && \ - if [ "$ARCH" = "amd64" ]; then \ - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"; \ - elif [ "$ARCH" = "arm64" ]; then \ - curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "awscliv2.zip"; \ - else \ - echo "Unsupported architecture: $ARCH"; exit 1; \ - fi && \ - unzip awscliv2.zip && \ - ./aws/install - -# Install gcloud CLI -RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \ - && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - \ - && apt-get update && apt-get install -y google-cloud-sdk - -# Install HashiCorp Vault -RUN curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add - \ - && apt-add-repository "deb [arch=$(dpkg --print-architecture)] https://apt.releases.hashicorp.com $(lsb_release -cs) main" \ - && apt-get update && apt-get install -y vault - -# Bug found here -> https://github.com/hashicorp/vault/issues/10924 -RUN setcap -r /usr/bin/vault - -# Install Azure CLI -RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash - -# Install programming languages -RUN apt-get update --fix-missing && apt-get install -y \ - openjdk-11-jdk \ - openjdk-11-jre-headless \ - golang-go \ - python3 \ - python3-pip \ - nodejs \ - npm \ - ruby \ +# --- Docker CLI + buildx from official Docker apt repo --- +RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ + | gpg --dearmor -o /usr/share/keyrings/docker.gpg \ + && echo "deb [arch=${TARGETARCH} signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable" \ + > /etc/apt/sources.list.d/docker.list \ + && apt-get update && apt-get install -y --no-install-recommends \ + docker-ce-cli \ + docker-buildx-plugin \ && rm -rf /var/lib/apt/lists/* -# Install Rust -RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - -# Set python3 as default python -RUN export python=python3 && export pip=pip3 - -# Set PATH for AWS CLI and Rust -ENV PATH="/usr/local/aws-cli/v2/current/bin:$PATH" -ENV PATH="/root/.cargo/bin:$PATH" - -# Verify installations -RUN aws --version \ - && gcloud --version \ - && vault --version \ - && az --version \ - && jq --version \ - && java -version \ - && go version \ - && python3 --version \ - && node --version \ - && npm --version \ - && ruby --version \ - && rustc --version - -# Clean up unnecessary files -RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +# --- Copy binaries from downloader stage --- +COPY --from=downloader /opt/aws-cli /opt/aws-cli +COPY --from=downloader /usr/local/bin/aws /usr/local/bin/aws +COPY --from=downloader /usr/local/bin/aws_completer /usr/local/bin/aws_completer +COPY --from=downloader /opt/google-cloud-sdk /opt/google-cloud-sdk +COPY --from=downloader /usr/local/bin/vault /usr/local/bin/vault +COPY --from=downloader /usr/local/go /usr/local/go +COPY --from=downloader /usr/local/bin/kubectl /usr/local/bin/kubectl +COPY --from=downloader /usr/local/bin/helm /usr/local/bin/helm +COPY --from=downloader /usr/local/bin/terraform /usr/local/bin/terraform +COPY --from=downloader /usr/local/bin/trivy /usr/local/bin/trivy +COPY --from=downloader /usr/local/bin/hadolint /usr/local/bin/hadolint +COPY --from=downloader /usr/local/bin/dive /usr/local/bin/dive +COPY --from=downloader /usr/local/bin/yq /usr/local/bin/yq + +# --- Vault capability fix (https://github.com/hashicorp/vault/issues/10924) --- +RUN setcap -r /usr/local/bin/vault || true + +# --- Validation script --- +COPY scripts/validate-tools.sh /usr/local/bin/validate-tools.sh + +# --- OCI labels --- +LABEL org.opencontainers.image.title="builder" \ + org.opencontainers.image.description="Pre-configured dev environment for debugging and building images" \ + org.opencontainers.image.source="https://github.com/decima-cloud/builder" \ + org.opencontainers.image.licenses="MIT" CMD ["bash"] diff --git a/README.md b/README.md index 8fe0016..94d8d20 100644 --- a/README.md +++ b/README.md @@ -1,91 +1,151 @@ # Builder -Builder is a base Dockerfile designed to streamline the development process by providing a pre-configured environment with commonly used tools and programming languages. This Dockerfile is intended for the community to help get things done faster and more efficiently. - -## Features - -One of the best/worst feature of this project is that the images are rebuilt every day at midnight so they will always have security patches built in. - -- **Multi-architecture support**: Supports both `amd64` and `arm64` architectures. -- **Pre-installed tools**: - - AWS CLI - - Google Cloud SDK (gcloud CLI) - - Azure CLI - - HashiCorp Vault - - jq -- **Pre-installed programming languages**: - - Java (OpenJDK 11) - - Go - - Python 3 - - Node.js and npm - - Ruby - - Rust -- **Optimized for size**: Uses multi-stage builds to minimize the final image size. +![Validation](https://img.shields.io/github/actions/workflow/status/decima-cloud/builder/build.yaml?branch=main&label=build) -## Supported Platforms - -You would download this by doing something like `docker pull ghcr.io/decima-cloud/builder:macOS-amd64`. where the tag could be any supported platform -Builder supports the following platforms: - -- **macOS**: - - amd64 - - arm64 -- **Windows**: - - amd64 - - arm64 -- **Linux**: - - amd64 - - arm64 - - arm64-v8 +Pre-configured Docker image for debugging, building other images, and working with cloud infrastructure. Ships with pinned versions of cloud CLIs, container tools, languages, and debugging utilities. -### Building the Docker Image Locally - -To build the Docker image, run the following command: +## Quick Start ```sh -docker build -t builder:latest . +docker pull ghcr.io/decima-cloud/builder:latest +docker run --rm -it ghcr.io/decima-cloud/builder:latest ``` -## Customization - -If you need to customize the Dockerfile to include additional tools or dependencies, you can modify the `Dockerfile` directly. Here are some common customizations: +## Supported Platforms -### Adding New Tools +| OS | Architecture | +|-------|-------------| +| Linux | amd64 | +| Linux | arm64 | + +## Tool Inventory + +All versions are pinned via `ARG` in the Dockerfile for reproducibility. + +### Cloud CLIs + +| Tool | Version | Purpose | +|-----------|---------|--------------------| +| AWS CLI | 2.24.4 | AWS management | +| gcloud | 514.0.0 | GCP management | +| Azure CLI | latest | Azure management | +| Vault | 1.18.4 | Secrets management | + +### Languages & Runtimes + +| Tool | Version | Purpose | +|---------|---------|------------------| +| Go | 1.23.5 | Go development | +| Python | 3.x | Python scripting | +| Node.js | 22.x | JS runtime | +| pip | latest | Python packages | + +### Container & Image Tools + +| Tool | Version | Purpose | +|----------|---------|-----------------------| +| Docker | latest | Container CLI | +| buildx | latest | Multi-platform builds | +| Trivy | 0.69.2 | Vulnerability scanner | +| hadolint | 2.12.0 | Dockerfile linter | +| dive | 0.12.0 | Image layer explorer | + +### Kubernetes & IaC + +| Tool | Version | Purpose | +|-----------|---------|----------------------| +| kubectl | 1.32.1 | Cluster management | +| Helm | 3.17.0 | Chart management | +| Terraform | 1.10.5 | Infrastructure as code | + +### Debugging + +| Tool | Purpose | +|----------|--------------------------| +| strace | System call tracing | +| ltrace | Library call tracing | +| tcpdump | Packet capture | +| net-tools| netstat, ifconfig, etc. | +| dnsutils | dig, nslookup | +| htop | Process monitoring | + +### Build & Dev Utilities + +| Tool | Purpose | +|------------|------------------------| +| git | Version control | +| make | Build automation | +| curl | HTTP client | +| wget | File downloads | +| jq | JSON processing | +| yq | YAML processing | +| vim | Text editor | +| shellcheck | Shell script linter | +| unzip | Archive extraction | + +## Usage Examples + +### CI Pipeline Base Image + +```yaml +jobs: + deploy: + container: + image: ghcr.io/decima-cloud/builder:latest + steps: + - run: terraform init && terraform apply -auto-approve +``` -To add a new tool, you can include the installation commands in the build stage of the Dockerfile. For example, to add `wget`, you can modify the `Dockerfile` as follows: +### Debugging a Running Container -```dockerfile -# Install wget -RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/* +```sh +docker run --rm -it \ + --pid=host --net=host \ + ghcr.io/decima-cloud/builder:latest ``` -### Adding New Programming Languages - -To add a new programming language, you can include the installation commands in the build stage of the Dockerfile. For example, to add Ruby, you can modify the `Dockerfile` as follows(this is just an example ruby is installed already): +### Building and Scanning Images -```dockerfile -# Install Ruby -RUN apt-get update && apt-get install -y ruby && rm -rf /var/lib/apt/lists/* +```sh +docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + ghcr.io/decima-cloud/builder:latest \ + sh -c "docker build -t myapp . && trivy image myapp" ``` -## Contributing +### Linting Dockerfiles + +```sh +docker run --rm -v "$(pwd)":/work -w /work \ + ghcr.io/decima-cloud/builder:latest \ + hadolint Dockerfile +``` -We welcome contributions from the community! If you have any improvements or new features to add, please follow these steps: +## Image Tags -1. Fork the repository. -2. Create a new branch for your feature or bugfix. -3. Make your changes and commit them with a descriptive message. -4. Push your changes to your forked repository. -5. Create a pull request to the main repository. +| Tag Format | Example | Description | +|-------------|------------------|---------------------------------| +| `latest` | `latest` | Latest build from main | +| `YYYYMMDD` | `20260301` | Date-stamped build | +| `vX.Y.Z` | `v1.0.0` | Semantic version release | +| `vX.Y` | `v1.0` | Minor version (tracks patches) | +| `` | `a1b2c3d` | Specific commit | -## License +## Image Size -This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details. +Target: ~1 GB (down from 3.5-5.5 GB). Achieved through: +- Multi-stage build (download stage discarded) +- Removed unused languages (Java 11, Ruby, Rust) +- `--no-install-recommends` on all apt installs +- Apt lists cleaned in the same layer as installs -## Acknowledgements +## Contributing -We would like to thank the open-source community for their contributions and support. +1. Fork the repository +2. Create a feature branch +3. Update tool versions by changing the `ARG` values in the Dockerfile +4. Run validation locally: `docker build -t builder:test . && docker run --rm builder:test validate-tools.sh` +5. Open a pull request — CI will lint, build, scan, and test automatically -## Contact +## License -If you have any questions or need further assistance, please open an issue in the repository or contact the maintainers. +MIT. See [LICENSE](LICENSE). diff --git a/scripts/validate-tools.sh b/scripts/validate-tools.sh new file mode 100755 index 0000000..b0f515c --- /dev/null +++ b/scripts/validate-tools.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +# validate-tools.sh — verify every tool installed in the builder image. +# Exits non-zero if any tool is missing or fails its version check. +set -euo pipefail + +PASS=0 +FAIL=0 +FAILED_TOOLS="" + +check() { + local name="$1" + shift + if "$@" > /dev/null 2>&1; then + printf " %-20s OK\n" "$name" + PASS=$((PASS + 1)) + else + printf " %-20s FAIL\n" "$name" + FAIL=$((FAIL + 1)) + FAILED_TOOLS="${FAILED_TOOLS} ${name}" + fi +} + +echo "=== Cloud CLIs ===" +check "aws" aws --version +check "gcloud" gcloud --version +check "az" az --version +check "vault" vault --version + +echo "" +echo "=== Languages & Runtimes ===" +check "go" go version +check "python3" python3 --version +check "pip3" pip3 --version +check "node" node --version +check "npm" npm --version + +echo "" +echo "=== Container & Image Tools ===" +check "docker" docker --version +check "buildx" docker buildx version +check "trivy" trivy --version +check "hadolint" hadolint --version +check "dive" dive --version + +echo "" +echo "=== Kubernetes & IaC ===" +check "kubectl" kubectl version --client +check "helm" helm version --short +check "terraform" terraform --version + +echo "" +echo "=== Debugging ===" +check "strace" strace -V +check "ltrace" ltrace -V +check "tcpdump" tcpdump --version +check "netstat" netstat --version +check "dig" dig -v +check "htop" htop --version + +echo "" +echo "=== Build & Dev Utilities ===" +check "git" git --version +check "make" make --version +check "curl" curl --version +check "wget" wget --version +check "jq" jq --version +check "yq" yq --version +check "vim" vim --version +check "unzip" unzip -v +check "shellcheck" shellcheck --version + +echo "" +echo "===============================" +printf "PASS: %d FAIL: %d\n" "$PASS" "$FAIL" + +if [ "$FAIL" -gt 0 ]; then + echo "FAILED TOOLS:${FAILED_TOOLS}" + exit 1 +fi + +echo "All tools validated successfully." +exit 0