diff --git a/.github/workflows/build-cds-containers.yml b/.github/workflows/build-cds-containers.yml new file mode 100644 index 0000000..4ac6d28 --- /dev/null +++ b/.github/workflows/build-cds-containers.yml @@ -0,0 +1,225 @@ +name: Build CDS Containers + +# Only trigger when files in cds-containers/ folder are modified +on: + push: + branches: + - main # Only push images when merging to main + paths: + - 'cds-containers/**' + - '.github/workflows/build-cds-containers.yml' + pull_request: + paths: + - 'cds-containers/**' + - '.github/workflows/build-cds-containers.yml' + workflow_dispatch: # Allow manual trigger + +env: + REGISTRY: ghcr.io + IMAGE_NAMESPACE: nvidia/dsx-github-actions + +permissions: + contents: read + packages: write # Required to push to GHCR + +jobs: + # Job 1: Read version from VERSION.md + get-version: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.extract-version.outputs.version }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Extract version from VERSION + id: extract-version + run: | + VERSION=$(cat cds-containers/VERSION | tr -d '[:space:]') + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "📌 Container version: $VERSION" + + # Job 2: Build and push all container images + build-and-push-images: + runs-on: ubuntu-latest + needs: get-version + strategy: + fail-fast: false + matrix: + image: + - name: cds-tools + path: cds-containers/tools + description: "CDS tools container with Bazel, Terraform, Helm, kubectl, NGC CLI, etc." + - name: cds-grafana-backup-tool + path: cds-containers/grafana-backup-tool + description: "Grafana backup tool container" + - name: cds-go-dev-1.24-alpine + path: cds-containers/go-dev-1.24-alpine + description: "Go 1.24 development container (Alpine-based, minimal size)" + - name: cds-go-dev-1.24-debian + path: cds-containers/go-dev-1.24-debian + description: "Go 1.24 development container (Debian-based, better compatibility)" + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/${{ matrix.image.name }} + tags: | + # Version from VERSION.md: 0.0.1 + type=raw,value=${{ needs.get-version.outputs.version }} + # Major.minor: 0.0.1 → 0.0 + type=raw,value=${{ needs.get-version.outputs.version }},enable=true,suffix=-latest + # Latest tag + type=raw,value=latest + # Commit SHA: dev-abc1234 (for testing specific builds) + type=sha,prefix=dev- + # Branch name (for PR/branch builds) + type=ref,event=branch + type=ref,event=pr + labels: | + org.opencontainers.image.description=${{ matrix.image.description }} + org.opencontainers.image.vendor=NVIDIA + org.opencontainers.image.version=${{ needs.get-version.outputs.version }} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: ./cds-containers + file: ${{ matrix.image.path }}/Dockerfile + # Only push on push events (not PRs) to avoid permission issues + push: ${{ github.event_name == 'push' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Build summary + run: | + if [ "${{ github.event_name }}" = "push" ]; then + echo "✅ Image built and pushed to GHCR:" + echo "${{ steps.meta.outputs.tags }}" | sed 's/^/ - /' + else + echo "✅ Image built successfully (not pushed in PR)" + echo "📦 Tags that would be created:" + echo "${{ steps.meta.outputs.tags }}" | sed 's/^/ - /' + fi + + # Job 3: Test using the built go-dev image + test-go-dev-image: + runs-on: ubuntu-latest + needs: [get-version, build-and-push-images] + # Only run tests when images are pushed (not on PRs) + if: github.event_name == 'push' + + # Use the newly built go-dev container with version tag + container: + image: ghcr.io/nvidia/dsx-github-actions/cds-go-dev-1.24-alpine:${{ needs.get-version.outputs.version }} + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + steps: + - name: Test container tools + run: | + echo "Testing Go development container (v${{ needs.get-version.outputs.version }})..." + go version + golangci-lint --version + goimports -h || true + + echo "" + echo "✅ Go container tools are working!" + + - name: Test building Go code + run: | + # Create a simple Go program to test + cat > hello.go << 'EOF' + package main + import "fmt" + func main() { + fmt.Println("Hello from CDS Go container v${{ needs.get-version.outputs.version }}!") + } + EOF + + go build hello.go + ./hello + + # Job 4: Test using tools container + test-tools-image: + runs-on: ubuntu-latest + needs: [get-version, build-and-push-images] + # Only run tests when images are pushed (not on PRs) + if: github.event_name == 'push' + + container: + image: ghcr.io/nvidia/dsx-github-actions/cds-tools:${{ needs.get-version.outputs.version }} + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + steps: + - name: Test tools container + run: | + echo "Testing CDS tools container (v${{ needs.get-version.outputs.version }})..." + echo "" + + echo "🔧 Tool versions:" + echo " - Bazel (default): $(bazel --version)" + echo " - Bazel 6: $(bazel6 --version)" + echo " - Bazel 8: $(bazel8 --version)" + echo " - Kubectl: $(kubectl version --client --short 2>/dev/null || kubectl version --client)" + echo " - Helm: $(helm version --short)" + echo " - Terraform: $(terraform version -json | jq -r '.terraform_version')" + echo " - Terragrunt: $(terragrunt --version)" + echo " - NGC CLI: $(ngc version --json | jq -r '.version')" + echo " - YQ: $(yq --version)" + echo " - Node.js: $(node --version)" + echo " - Python: $(python3 --version)" + echo " - UV: $(uv --version)" + echo "" + echo "✅ All tools are working!" + + # Job 5: Summary + summary: + runs-on: ubuntu-latest + needs: [get-version, build-and-push-images, test-go-dev-image, test-tools-image] + if: always() + + steps: + - name: Build summary + run: | + echo "## 🎉 CDS Containers Build Summary" + echo "" + echo "📦 Version: ${{ needs.get-version.outputs.version }}" + echo "🔨 Trigger: ${{ github.event_name }}" + echo "📌 Commit: ${{ github.sha }}" + echo "" + echo "✅ Built and pushed 4 container images to GHCR:" + echo " - ghcr.io/nvidia/dsx-github-actions/cds-tools:${{ needs.get-version.outputs.version }}" + echo " - ghcr.io/nvidia/dsx-github-actions/cds-grafana-backup-tool:${{ needs.get-version.outputs.version }}" + echo " - ghcr.io/nvidia/dsx-github-actions/cds-go-dev-1.24-alpine:${{ needs.get-version.outputs.version }}" + echo " - ghcr.io/nvidia/dsx-github-actions/cds-go-dev-1.24-debian:${{ needs.get-version.outputs.version }}" + echo "" + echo "📍 Usage example:" + echo " container:" + echo " image: ghcr.io/nvidia/dsx-github-actions/cds-tools:${{ needs.get-version.outputs.version }}" + echo " credentials:" + echo " username: \${{ github.actor }}" + echo " password: \${{ secrets.GITHUB_TOKEN }}" + echo "" + echo "✅ All tests passed!" diff --git a/cds-containers/.pre-commit-config.yaml b/cds-containers/.pre-commit-config.yaml new file mode 100644 index 0000000..4b11f19 --- /dev/null +++ b/cds-containers/.pre-commit-config.yaml @@ -0,0 +1,12 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: check-merge-conflict + - id: mixed-line-ending + args: [--fix=lf] + - id: end-of-file-fixer + - id: forbid-submodules + - id: trailing-whitespace diff --git a/cds-containers/CHANGELOG.md b/cds-containers/CHANGELOG.md new file mode 100644 index 0000000..08ea516 --- /dev/null +++ b/cds-containers/CHANGELOG.md @@ -0,0 +1,28 @@ +# Changelog + +All notable changes to CDS Containers will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.0.1] - 2026-01-19 + +### Added +- Initial GitHub version of CDS containers +- `cds-tools` container with Bazel 6.5.0 & 8.4.0, kubectl, helm, terraform, terragrunt, NGC CLI +- `cds-go-dev-1.24-alpine` container for Go development (Alpine-based, minimal size) +- `cds-go-dev-1.24-debian` container for Go development (Debian-based, better compatibility) +- `cds-grafana-backup-tool` container for Grafana backups +- GitHub Actions workflow for building and pushing to GHCR +- Version management via VERSION.md file +- Path-filtered pipeline (only triggers on cds-containers/ changes) +- Comprehensive documentation and usage examples + +### Removed +- `nvault` (requires internal URM access, not available on GitHub runners) +- `cds-cli` (requires internal GitLab access, not available on GitHub runners) + +### Changed +- Container registry from GitLab to GitHub Container Registry (GHCR) +- Image naming from `cds/cds-containers/*` to `nvidia/dsx-github-actions/cds-*` +- Version tagging from Git tags to VERSION.md file-based versioning diff --git a/cds-containers/Makefile b/cds-containers/Makefile new file mode 100644 index 0000000..96f098f --- /dev/null +++ b/cds-containers/Makefile @@ -0,0 +1,3 @@ +init: + pip install pre-commit + pre-commit install diff --git a/cds-containers/README.md b/cds-containers/README.md new file mode 100644 index 0000000..e9ab211 --- /dev/null +++ b/cds-containers/README.md @@ -0,0 +1,325 @@ +# CDS Containers for GitHub Actions + +Container images for CDS tooling, optimized for GitHub Actions workflows. These images provide consistent development and CI/CD environments across DSX projects. + +> **Note**: This is the GitHub-compatible version. Internal tools requiring NVIDIA network access (nvault, cds-cli) have been removed. For GitLab with internal tools, see `registry.gitlab-master.nvidia.com/cds/cds-containers`. + +--- + +## 🐳 Available Containers + +### 1. `cds-tools` - CDS Tools Container +Comprehensive tooling for infrastructure automation, CI/CD, and Kubernetes operations. + +**Image**: `ghcr.io/nvidia/dsx-github-actions/cds-tools:latest` + +**Includes**: +- **Bazel** (multiple versions): + - `bazel6` - Bazel 6.5.0 (for KubeVirt compatibility) + - `bazel8` - Bazel 8.4.0 (latest stable) + - `bazel` - Default symlink (→ bazel8) +- **Kubernetes**: kubectl, kubelogin, helm +- **Infrastructure**: terraform, terragrunt +- **NVIDIA**: NGC CLI +- **Container tools**: docker CLI, regctl +- **Dev tools**: Node.js 24, Python 3, git, make, jq, yq, uv (Python package manager) + +**Size**: ~500MB + +### 2. `cds-grafana-backup-tool` +Specialized container for backing up Grafana instances. + +**Image**: `ghcr.io/nvidia/dsx-github-actions/cds-grafana-backup-tool:latest` + +### 3. `cds-go-dev-1.24-alpine` - Go Development (Alpine) +Lightweight Go 1.24 development environment with essential tooling. + +**Image**: `ghcr.io/nvidia/dsx-github-actions/cds-go-dev-1.24-alpine:latest` + +**Includes**: +- Go 1.24.3 (Alpine-based) +- Air (hot reloading) +- Delve (debugging) +- golangci-lint +- goimports +- swag (Swagger documentation) + +**Size**: ~50MB + +**Use when**: You need a minimal, fast container for Go development and CI. + +### 4. `cds-go-dev-1.24-debian` - Go Development (Debian) +Full-featured Go 1.24 environment with better C library compatibility. + +**Image**: `ghcr.io/nvidia/dsx-github-actions/cds-go-dev-1.24-debian:latest` + +**Size**: ~300MB+ + +**Use when**: +- CGO-enabled packages with complex C dependencies +- Specific Debian packages not available in Alpine +- Troubleshooting compatibility issues with musl (Alpine's libc) + +--- + +## 📦 Using Images in GitHub Actions + +### Method 1: Using `container` in Job (Recommended) + +```yaml +jobs: + build: + runs-on: ubuntu-latest + permissions: + packages: read # Required to pull from GHCR + + container: + image: ghcr.io/nvidia/dsx-github-actions/cds-tools:0.0.1 + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build with Bazel + run: bazel build //... + + - name: Deploy with Terraform + run: | + terraform init + terraform plan +``` + +### Method 2: Using Docker Run in Steps + +```yaml +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Run build in container + run: | + docker run --rm \ + -v $PWD:/workspace \ + -w /workspace \ + ghcr.io/nvidia/dsx-github-actions/cds-go-dev-1.24-alpine:latest \ + go build ./... +``` + +### Method 3: Building Custom Image Based on CDS Containers + +```dockerfile +FROM ghcr.io/nvidia/dsx-github-actions/cds-tools:0.0.1 + +# Add your custom tools +RUN apt-get update && apt-get install -y \ + your-custom-package + +WORKDIR /app +``` + +--- + +## 🔒 Private Image Access + +### For repos in the same org (NVIDIA): +- ✅ `GITHUB_TOKEN` automatically has read access to org packages +- ✅ Just add `permissions: packages: read` to your job +- ✅ No extra secrets or PAT needed + +### For cross-org or external repos: +1. Create a Personal Access Token (PAT) with `read:packages` scope +2. Add it as a repository secret: `GHCR_PAT` +3. Use it in credentials: + ```yaml + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GHCR_PAT }} + ``` + +--- + +## 🏗️ Versioning and Updates + +### Current Version +The current version is defined in [`VERSION`](./VERSION): **0.0.1** + +This file contains only the semantic version number (e.g., `0.0.1`). + +### Updating Containers + +When you need to update tools or fix issues: + +1. **Make changes** to Dockerfiles in this folder +2. **Update VERSION**: + - Edit the file to contain only the new version number + - Follow [Semantic Versioning](https://semver.org/) + - Example: `0.1.0` +3. **Commit and push**: + ```bash + git add cds-containers/ + git commit -m "feat: upgrade kubectl to v1.33.0" + git push + ``` +4. **Pipeline auto-triggers** - Only runs when `cds-containers/` files change +5. **Images are tagged** with the version from VERSION.md + +**Version Bumping**: +- **PATCH** (0.0.1 → 0.0.2): Bug fixes, base image updates +- **MINOR** (0.0.1 → 0.1.0): New tools, tool version upgrades +- **MAJOR** (0.0.1 → 1.0.0): Breaking changes, removed tools + +**Example Workflow**: +```bash +# Edit Dockerfile to upgrade a tool +vim cds-containers/tools/Dockerfile + +# Update version (just the semver number) +echo "0.1.0" > cds-containers/VERSION + +# Commit with descriptive message +git add cds-containers/ +git commit -m "feat: upgrade kubectl to v1.33.0 + +Bump version to 0.1.0" +git push + +# Pipeline runs automatically, creates: +# - ghcr.io/nvidia/dsx-github-actions/cds-tools:0.1.0 +# - ghcr.io/nvidia/dsx-github-actions/cds-tools:latest +``` + +--- + +## 🔄 Migration from GitLab + +### GitLab → GitHub URL Mapping + +| GitLab Registry | GitHub GHCR | +|-----------------|-------------| +| `registry.gitlab-master.nvidia.com/cds/cds-containers/tools:latest` | `ghcr.io/nvidia/dsx-github-actions/cds-tools:latest` | +| `registry.gitlab-master.nvidia.com/cds/cds-containers/go-dev-1.24-alpine:1.0.0` | `ghcr.io/nvidia/dsx-github-actions/cds-go-dev-1.24-alpine:0.0.1` | + +### Key Differences + +| Feature | GitLab CI | GitHub Actions | +|---------|-----------|----------------| +| Registry Auth | `CI_REGISTRY_PASSWORD` | `GITHUB_TOKEN` | +| Image URL | `registry.gitlab-master.nvidia.com` | `ghcr.io` | +| Permissions | Inherited from repo | Explicit `permissions: packages: write/read` | +| Job syntax | `image: ` | `container: { image: , credentials: {...} }` | +| Internal tools | ✅ nvault, cds-cli | ❌ Removed (no internal network) | +| Versioning | Git tags | VERSION.md file | + +--- + +## 🛠️ Tools Container - Bazel Multi-Version Support + +The `cds-tools` container includes multiple Bazel versions to support different projects: + +**Usage in pipelines**: +```yaml +steps: + # Use Bazel 6.5.0 for KubeVirt or projects requiring compatibility + - name: Build with Bazel 6 + run: bazel6 build //... + + # Use Bazel 8.4.0 explicitly + - name: Build with Bazel 8 + run: bazel8 build //... + + # Use default (currently Bazel 8.4.0) + - name: Build with default Bazel + run: bazel build //... +``` + +**For projects with Makefiles that call `bazel`**: + +If your Makefile uses `bazel` commands directly, override the default: + +```yaml +jobs: + build: + container: + image: ghcr.io/nvidia/dsx-github-actions/cds-tools:latest + + steps: + - name: Override bazel to use version 6.5.0 + run: | + ln -sf /usr/local/bin/bazel6 /usr/local/bin/bazel + bazel --version # Verify it's 6.5.0 + + - name: Build (uses Bazel 6.5.0) + run: make build +``` + +--- + +## 💰 GHCR Pricing (Private Images) + +- **Storage**: 500 MB free, then $0.008/GB/day (~$0.25/GB/month) +- **Bandwidth**: 1 GB/month free +- **GitHub Actions**: Pulling images in GH Actions **does not count toward bandwidth** ✅ + +**Estimated cost for all 4 images**: ~$0.25/month (very affordable!) + +--- + +## 📚 Contributing + +### Adding a New Container + +1. Create your image directory: `cds-containers/my-new-image/` +2. Add your `Dockerfile` inside +3. Update `.github/workflows/build-cds-containers.yml` to include it in the matrix: + ```yaml + - name: cds-my-new-image + path: cds-containers/my-new-image + description: "Description of your new image" + ``` +4. Update `VERSION.md` (at least MINOR bump) +5. Update this README to document the new image +6. Push changes - pipeline will build and test automatically + +### Local Testing + +```bash +# Build locally +docker build -t test-cds-tools -f cds-containers/tools/Dockerfile ./cds-containers + +# Test locally +docker run --rm -it test-cds-tools bash + +# Test specific tool +docker run --rm test-cds-tools bazel --version +``` + +--- + +## 🔗 Useful Links + +- **GHCR Packages**: https://github.com/orgs/NVIDIA/packages?repo_name=dsx-github-actions +- **GitHub Actions Workflow**: `.github/workflows/build-cds-containers.yml` +- **Version History**: [`VERSION.md`](./VERSION.md) +- **Original GitLab Repo**: https://gitlab-master.nvidia.com/cds/cds-containers + +--- + +## 📝 Notes + +- **No internal tools**: `nvault` and `cds-cli` are not included as GitHub runners cannot reach internal NVIDIA resources +- **For internal use**: Use GitLab version at `registry.gitlab-master.nvidia.com/cds/cds-containers/tools` +- **Version-based tagging**: Images are tagged with versions from `VERSION.md`, not Git tags +- **Path-filtered pipeline**: Only changes to `cds-containers/` folder trigger builds diff --git a/cds-containers/VERSION b/cds-containers/VERSION new file mode 100644 index 0000000..8acdd82 --- /dev/null +++ b/cds-containers/VERSION @@ -0,0 +1 @@ +0.0.1 diff --git a/cds-containers/go-dev-1.24-alpine/Dockerfile b/cds-containers/go-dev-1.24-alpine/Dockerfile new file mode 100644 index 0000000..f0cb855 --- /dev/null +++ b/cds-containers/go-dev-1.24-alpine/Dockerfile @@ -0,0 +1,33 @@ +FROM golang:1.24.3-alpine + +# Set locale for proper terminal support +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +# Install development tools and dependencies +RUN apk add --no-cache \ + git \ + curl \ + wget \ + vim \ + bash \ + build-base \ + procps \ + net-tools \ + ca-certificates + +# Install Air for hot reloading +RUN go install github.com/air-verse/air@v1.62.0 + +# Install Delve for debugging +RUN go install github.com/go-delve/delve/cmd/dlv@v1.25.2 + +# Install other useful development tools +RUN go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.8 +RUN go install golang.org/x/tools/cmd/goimports@v0.37.0 +RUN go install github.com/swaggo/swag/cmd/swag@v1.16.4 + +# Enable CGO for development (allows for better debugging and some dev tools) +ENV CGO_ENABLED=1 + +WORKDIR /go/src/app diff --git a/cds-containers/go-dev-1.24-debian/Dockerfile b/cds-containers/go-dev-1.24-debian/Dockerfile new file mode 100644 index 0000000..71c7f66 --- /dev/null +++ b/cds-containers/go-dev-1.24-debian/Dockerfile @@ -0,0 +1,31 @@ +FROM golang:1.24.3 + +# Set locale for proper terminal support +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +# Install development tools and dependencies +RUN apt-get update && apt-get install -y \ + git \ + curl \ + wget \ + vim \ + procps \ + net-tools \ + && rm -rf /var/lib/apt/lists/* + +# Install Air for hot reloading +RUN go install github.com/air-verse/air@v1.62.0 + +# Install Delve for debugging +RUN go install github.com/go-delve/delve/cmd/dlv@v1.25.2 + +# Install other useful development tools +RUN go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.8 +RUN go install golang.org/x/tools/cmd/goimports@v0.37.0 +RUN go install github.com/swaggo/swag/cmd/swag@v1.16.4 + +# Enable CGO for development (allows for better debugging and some dev tools) +ENV CGO_ENABLED=1 + +WORKDIR /go/src/app diff --git a/cds-containers/grafana-backup-tool/Dockerfile b/cds-containers/grafana-backup-tool/Dockerfile new file mode 100644 index 0000000..e83fdfa --- /dev/null +++ b/cds-containers/grafana-backup-tool/Dockerfile @@ -0,0 +1,6 @@ +FROM ysde/docker-grafana-backup-tool:1.4.2-slim + +USER 0 +RUN apk add --no-cache git + +CMD sh -c 'if [ "$RESTORE" = true ]; then if [ ! -z "$AWS_S3_BUCKET_NAME" ] || [ ! -z "$AZURE_STORAGE_CONTAINER_NAME" ] || [ ! -z "$GCS_BUCKET_NAME" ]; then grafana-backup restore $ARCHIVE_FILE; else grafana-backup restore _OUTPUT_/$ARCHIVE_FILE; fi else grafana-backup save; fi' diff --git a/cds-containers/tools/Dockerfile b/cds-containers/tools/Dockerfile new file mode 100644 index 0000000..4cc2836 --- /dev/null +++ b/cds-containers/tools/Dockerfile @@ -0,0 +1,141 @@ +ARG BASE_IMAGE="nvcr.io/nvidia/base/ubuntu:22.04_20240212" +FROM ${BASE_IMAGE} +RUN apt-get update \ + && apt-get install --no-install-recommends -y \ + build-essential \ + ca-certificates \ + curl \ + git \ + git-lfs \ + gnupg \ + jq \ + lsb-release \ + make \ + python3 \ + python3-pip \ + python3-dev \ + software-properties-common \ + unzip \ + && apt-get autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Node.js 24 LTS +RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \ + && apt-get update \ + && apt-get install --no-install-recommends -y nodejs \ + && node --version \ + && npm --version + +# Note: nvault is not included as GitHub runners cannot reach internal URM +# For internal GitLab runners, use the GitLab version of this container + +# kubectl (latest version: curl -sSL https://dl.k8s.io/release/stable.txt) +ARG KUBECTL_VERSION="1.32.1" +RUN curl -fsSL -o kubectl "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl" \ + && mv ./kubectl /usr/local/bin/kubectl \ + && chmod +x /usr/local/bin/kubectl \ + && kubectl version --client + +# kubelogin +ARG KUBELOGIN_VERSION="0.1.7" +RUN curl -fsSL -o kubelogin.zip "https://github.com/Azure/kubelogin/releases/download/v${KUBELOGIN_VERSION}/kubelogin-linux-amd64.zip" \ + && unzip -j kubelogin.zip \ + && mv kubelogin /usr/local/bin/kubelogin \ + && kubelogin --version + +# yq +ARG YQ_VERSION="4.45.1" +RUN curl -fsSL -o yq "https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/yq_linux_amd64" \ + && mv ./yq /usr/local/bin/yq \ + && chmod +x /usr/local/bin/yq \ + && yq --version + +# ngccli +ARG NGCCLI_VERSION="4.8.2" +RUN curl -sSL -O "https://api.ngc.nvidia.com/v2/resources/nvidia/ngc-apps/ngc_cli/versions/${NGCCLI_VERSION}/files/ngccli_linux.zip" \ + && unzip ngccli_linux.zip \ + && rm ngccli_linux.zip \ + && ln -s /ngc-cli/ngc /usr/local/bin/ngc \ + && ngc version info + +# NGC CLI - disable trace +# https://nvidia.slack.com/archives/C7VGNG1V3/p1738003396389109 +# Transient error StatusCode.DEADLINE_EXCEEDED encountered while exporting traces to prod.otel.kaizen.nvidia.com:8282, retrying in 1s. +ENV NGC_CLI_TRACE_DISABLE=true + +# docker +RUN curl -sSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc \ + && echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \ + tee /etc/apt/sources.list.d/docker.list > /dev/null \ + && apt-get update \ + && apt-get install --no-install-recommends -y \ + # docker-ce \ + # containerd.io \ + docker-ce-cli \ + docker-buildx-plugin \ + docker-compose-plugin \ + && apt-get autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && docker --version + +# regctl +ARG REGCTL_VERSION="0.9.2" +RUN curl -fsSL -o regctl "https://github.com/regclient/regclient/releases/download/v${REGCTL_VERSION}/regctl-linux-amd64" \ + && mv ./regctl /usr/local/bin/regctl \ + && chmod +x /usr/local/bin/regctl \ + && regctl version + +# helm +ENV VERIFY_CHECKSUM=true \ + VERIFY_SIGNATURES=true +RUN curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash \ + && helm version + +# terraform +ARG TERRAFORM_VERSION="1.13.3" +RUN curl -fsSL -o terraform.zip "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" && \ + unzip terraform.zip && \ + rm terraform.zip && \ + mv ./terraform /usr/local/bin/terraform \ + && terraform --version + +# terragrunt +ARG TERRAGRUNT_VERSION="0.72.6" +RUN curl -fsSL -o terragrunt "https://github.com/gruntwork-io/terragrunt/releases/download/v${TERRAGRUNT_VERSION}/terragrunt_linux_amd64" \ + && mv ./terragrunt /usr/local/bin/terragrunt \ + && chmod +x /usr/local/bin/terragrunt \ + && terragrunt --version + +# bazel - multiple versions for different projects +# Install Bazel 6.5.0 (required for KubeVirt - VMAAS-708, NID-8024) +ARG BAZEL6_VERSION="6.5.0" +RUN curl -fsSL -o bazel6 "https://github.com/bazelbuild/bazel/releases/download/${BAZEL6_VERSION}/bazel-${BAZEL6_VERSION}-linux-x86_64" \ + && mv ./bazel6 /usr/local/bin/bazel-${BAZEL6_VERSION} \ + && chmod +x /usr/local/bin/bazel-${BAZEL6_VERSION} \ + && ln -s /usr/local/bin/bazel-${BAZEL6_VERSION} /usr/local/bin/bazel6 \ + && bazel6 --version + +# Install Bazel 8.4.0 (latest stable for other projects) +ARG BAZEL8_VERSION="8.4.0" +RUN curl -fsSL -o bazel8 "https://github.com/bazelbuild/bazel/releases/download/${BAZEL8_VERSION}/bazel-${BAZEL8_VERSION}-linux-x86_64" \ + && mv ./bazel8 /usr/local/bin/bazel-${BAZEL8_VERSION} \ + && chmod +x /usr/local/bin/bazel-${BAZEL8_VERSION} \ + && ln -s /usr/local/bin/bazel-${BAZEL8_VERSION} /usr/local/bin/bazel8 \ + && bazel8 --version + +# Default bazel points to version 8 (latest) +RUN ln -s /usr/local/bin/bazel8 /usr/local/bin/bazel \ + && echo "Installed Bazel versions:" \ + && bazel6 --version \ + && bazel8 --version \ + && bazel --version + +# uv (latest version: 0.9.7) +COPY --from=ghcr.io/astral-sh/uv:0.9.7 /uv /uvx /usr/local/bin/ +RUN uv self version + +# Note: CDS CLI is not included as GitHub runners cannot reach internal GitLab +# For internal GitLab runners, use the GitLab version of this container