Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 38 additions & 6 deletions .github/workflows/build-cicd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ jobs:
echo "TAG=${BRANCH_NAME}" >> $GITHUB_OUTPUT
fi

- name: Build Docker image (no push)
# Build standard Ubuntu-based image
- name: Build Docker image (standard)
uses: docker/build-push-action@v5
with:
context: .
Expand All @@ -40,22 +41,42 @@ jobs:
push: false
load: true

# Build minimal Chainguard static image
- name: Build Docker image (Chainguard)
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile.chainguard
platforms: linux/amd64
tags: cbaugus/rust_loadtest:${{ steps.docker_meta.outputs.TAG }}-Chainguard
push: false
load: true

- name: Install Syft
run: |
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

- name: Generate SBOM with Syft
# Generate SBOM for standard image
- name: Generate SBOM with Syft (standard)
run: |
syft --version
syft "docker:cbaugus/rust_loadtest:${{ steps.docker_meta.outputs.TAG }}" -o cyclonedx-json > sbom.cyclonedx.json
syft "docker:cbaugus/rust_loadtest:${{ steps.docker_meta.outputs.TAG }}" -o cyclonedx-json > sbom-standard.cyclonedx.json

# Generate SBOM for Chainguard image
- name: Generate SBOM with Syft (Chainguard)
run: |
syft "docker:cbaugus/rust_loadtest:${{ steps.docker_meta.outputs.TAG }}-Chainguard" -o cyclonedx-json > sbom-chainguard.cyclonedx.json

- name: Upload SBOM artifact
- name: Upload SBOM artifacts
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.cyclonedx.json
path: |
sbom-standard.cyclonedx.json
sbom-chainguard.cyclonedx.json

- name: Push Docker image
# Push standard Ubuntu image
- name: Push Docker image (standard)
uses: docker/build-push-action@v5
with:
context: .
Expand All @@ -65,3 +86,14 @@ jobs:
provenance: true
push: true

# Push minimal Chainguard image
- name: Push Docker image (chainguard)
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile.chainguard
platforms: linux/amd64
tags: cbaugus/rust_loadtest:${{ steps.docker_meta.outputs.TAG }}-Chainguard
provenance: true
push: true

38 changes: 38 additions & 0 deletions Dockerfile.chainguard
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Multi-stage build for static binary with Chainguard
# This produces a minimal, secure image (~10-15 MB) with zero CVEs

# --- Stage 1: Build static binary with musl ---
FROM rust:alpine AS builder

WORKDIR /usr/src/app

# Install musl development tools for static linking
RUN apk add --no-cache musl-dev

# Copy source code
COPY . .

# Add musl target for Rust
RUN rustup target add x86_64-unknown-linux-musl

# Build static binary with all dependencies compiled in
# Using release profile for optimizations
RUN cargo build --release --target x86_64-unknown-linux-musl

# --- Stage 2: Ultra-minimal Chainguard static runtime ---
# This image contains only: filesystem structure, CA certs, timezone data
# Size: ~2-5 MB base
# CVEs: Typically 0
FROM cgr.dev/chainguard/static:latest

# Copy the static binary from builder
COPY --from=builder /usr/src/app/target/x86_64-unknown-linux-musl/release/rust_loadtest /usr/local/bin/rust_loadtest

# Expose Prometheus metrics port
EXPOSE 9090

# Chainguard images run as non-root user by default (UID 65532)
# No shell available in this image - maximum security

# Run the application
ENTRYPOINT ["/usr/local/bin/rust_loadtest"]
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,46 @@ Before you begin, ensure you have the following installed:
* [**Rust**](https://www.rust-lang.org/tools/install): Rust toolchain (version 1.77 or newer recommended).
* [**Docker**](https://docs.docker.com/get-docker/): Docker Engine to build and run the containerized application.

## Available Docker Images

This tool is available in two image variants to suit different deployment scenarios:

### Standard Image (Ubuntu-based)
**Tag:** `cbaugus/rust-loadtester:latest` or `cbaugus/rust-loadtester:<branch>`

- **Base:** Ubuntu latest
- **Size:** ~80-100 MB
- **Use case:** Development, testing, debugging in lab environments
- **Features:**
- Full shell access for troubleshooting
- Standard system utilities available
- Easy to debug and inspect
- **Build:** `Dockerfile`

### Static Image (Chainguard-based)
**Tag:** `cbaugus/rust-loadtester:latest-Chainguard` or `cbaugus/rust-loadtester:<branch>-Chainguard`

- **Base:** Chainguard static (distroless)
- **Size:** ~10-15 MB (75% smaller)
- **Use case:** Production, secure environments, minimal attack surface
- **Features:**
- Zero to minimal CVEs (typically 0-2)
- No shell or unnecessary binaries
- Static binary with all dependencies compiled in
- Maximum security posture
- **Build:** `Dockerfile.static`

**Recommendation:** Use the **static image** for production deployments in secure environments. Use the **standard image** for development and troubleshooting.

## Project Structure

```
.
├── Cargo.toml
├── src
│ └── main.rs
└── Dockerfile
├── Dockerfile # Standard Ubuntu-based build
└── Dockerfile.static # Minimal Chainguard static build
```


Expand Down