diff --git a/.github/workflows/publish-examples.yml b/.github/workflows/publish-examples.yml index 1431f30..b6620de 100644 --- a/.github/workflows/publish-examples.yml +++ b/.github/workflows/publish-examples.yml @@ -7,6 +7,7 @@ on: tags: ['v*'] paths: - 'examples/**' + - 'host/**' - 'runtimes/**' - '.github/workflows/publish-examples.yml' @@ -230,6 +231,37 @@ jobs: docker push $VERSION_TAG fi + # Publish a runnable pyhl container image (pyhl + kernel + initrd). + # Designed for the hyperlight-on-kubernetes device plugin — the pod + # gets /dev/kvm and pyhl handles VM lifecycle internally. + publish-pyhl: + needs: [publish-pyhl-initrd, publish-kernels] + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v4 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push pyhl image + run: | + IMAGE=${{ env.IMAGE_BASE }}/pyhl:latest + docker build --platform linux/amd64 \ + -f host/pyhl.Dockerfile -t $IMAGE . + docker push $IMAGE + if [[ "${{ github.ref_type }}" == "tag" ]]; then + VERSION_TAG=${{ env.IMAGE_BASE }}/pyhl:${{ github.ref_name }} + docker tag $IMAGE $VERSION_TAG + docker push $VERSION_TAG + fi + # Publish the python-agent-driver rootfs CPIO as its own image so # `pyhl setup` can pull the initrd (and kernel, above) from GHCR # without having to build the driver image locally. diff --git a/host/pyhl-entrypoint.sh b/host/pyhl-entrypoint.sh new file mode 100644 index 0000000..35c3fff --- /dev/null +++ b/host/pyhl-entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -e + +if [ ! -f "$PYHL_HOME/snapshot/index.json" ]; then + staging=$(mktemp -d) + trap 'rm -rf "$staging"' EXIT + mkdir -p "$staging/.unikraft/build" + ln -s "$PYHL_HOME/kernel" "$staging/.unikraft/build/driver_hyperlight-x86_64" + ln -s "$PYHL_HOME/initrd.cpio" "$staging/driver-initrd.cpio" + pyhl setup --dest "$PYHL_HOME" --from "$staging" --net --force +fi + +if [ "$1" = "--setup-only" ]; then + exit 0 +fi + +exec pyhl run --dest "$PYHL_HOME" --net "$@" diff --git a/host/pyhl.Dockerfile b/host/pyhl.Dockerfile new file mode 100644 index 0000000..a6f5978 --- /dev/null +++ b/host/pyhl.Dockerfile @@ -0,0 +1,33 @@ +# pyhl container image — runs Python scripts in Hyperlight micro-VMs. +# +# Bundles the pyhl CLI, the python-agent-driver kernel, and its initrd +# into a single runnable container. Designed for the +# hyperlight-on-kubernetes device plugin: the pod gets /dev/kvm via +# `hyperlight.dev/hypervisor: "1"` and pyhl handles the rest. +# +# Build (from repo root): +# docker build -f host/pyhl.Dockerfile -t pyhl . +# +# Run: +# docker run --rm --device /dev/kvm pyhl /path/to/script.py +# echo 'print("hi")' | docker run --rm -i --device /dev/kvm pyhl - + +FROM rust:1.87-bookworm AS builder +COPY host/ /src/host/ +WORKDIR /src/host +RUN cargo build --release --bin pyhl + +FROM ghcr.io/hyperlight-dev/hyperlight-unikraft/python-agent-driver-kernel:latest AS kernel +FROM ghcr.io/hyperlight-dev/hyperlight-unikraft/python-agent-driver-initrd:latest AS initrd + +FROM debian:bookworm-slim +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \ + && rm -rf /var/lib/apt/lists/* +COPY --from=builder /src/host/target/release/pyhl /usr/local/bin/ +COPY --from=kernel /kernel /opt/pyhl/kernel +COPY --from=initrd /initrd.cpio /opt/pyhl/initrd.cpio +COPY host/pyhl-entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh && chown -R 65534:65534 /opt/pyhl +ENV PYHL_HOME=/opt/pyhl +USER 65534 +ENTRYPOINT ["/entrypoint.sh"]