diff --git a/.github/workflows/build_cross.yml b/.github/workflows/build_cross.yml index 2848293f5..678a9be59 100644 --- a/.github/workflows/build_cross.yml +++ b/.github/workflows/build_cross.yml @@ -220,3 +220,121 @@ jobs: name: pktvisor-cli-${{matrix.os}}-${{matrix.arch}} path: pktvisor-cli retention-days: 7 + + package-alpine: + name: alpine-${{matrix.arch}} + needs: pkvisor + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/develop' + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + docker_platform: linux/amd64 + goarch: amd64 + - arch: aarch64 + docker_platform: linux/arm64 + goarch: arm64 + steps: + - uses: actions/checkout@v6 + + - name: Download pktvisord + uses: actions/download-artifact@v8 + with: + name: pktvisord-linux-${{matrix.arch}}-static + path: ./ + + - name: Download pktvisor-reader + uses: actions/download-artifact@v8 + with: + name: pktvisor-reader-linux-${{matrix.arch}}-static + path: ./ + + - name: Configure CMake to generate version.go + shell: bash + run: VERSION_ONLY=1 cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Release -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./cmake/conan_provider.cmake + + - name: Stage pktvisor sources for go build + run: | + mv src pktvisor-src + cp -rpf golang/pkg/client/version.go . + + - name: Build pktvisor-cli + uses: ./.github/actions/build-go + with: + context: "." + file: "./Dockerfile" + goos: "linux" + goarch: "${{matrix.goarch}}" + + - name: Stage IANA CSV + run: cp pktvisor-src/tests/fixtures/pktvisor-port-service-names.csv ./custom-iana.csv + + - name: Login to Docker Hub + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0 + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0 + + - name: Build + push pktvisor-alpine + id: docker_build + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0 + with: + builder: ${{ steps.buildx.outputs.name }} + context: . + file: ./docker/Dockerfile.alpine + platforms: ${{matrix.docker_platform}} + outputs: type=image,"name=netboxlabs/pktvisor",push-by-digest=true,name-canonical=true,push=true + + - name: Export digest + run: | + mkdir -p /tmp/digests + digest="${{ steps.docker_build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v7 + with: + name: digests-alpine-${{matrix.arch}} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge-alpine: + needs: package-alpine + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/develop' + steps: + - name: Download digests + uses: actions/download-artifact@v8 + with: + path: /tmp/digests + pattern: digests-alpine-* + merge-multiple: true + + - name: Login to Docker Hub + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0 + + - name: Create manifest list and push + working-directory: /tmp/digests + run: | + docker buildx imagetools create \ + -t netboxlabs/pktvisor:develop-alpine \ + $(printf 'netboxlabs/pktvisor@sha256:%s ' *) + + - name: Inspect image + run: docker buildx imagetools inspect netboxlabs/pktvisor:develop-alpine diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine new file mode 100644 index 000000000..ccd029bf3 --- /dev/null +++ b/docker/Dockerfile.alpine @@ -0,0 +1,23 @@ +FROM alpine:3.21 + +RUN apk add --no-cache ca-certificates curl wget gzip + +COPY ./pktvisord /usr/local/sbin/pktvisord +COPY ./pktvisor-reader /usr/local/sbin/pktvisor-reader +COPY ./pktvisor-cli /usr/local/bin/pktvisor-cli +COPY ./docker/alpine/entry.sh /entry.sh +COPY ./docker/alpine/run.sh /run.sh + +RUN mkdir /geo-db \ + && wget -q -O /geo-db/asn.mmdb.gz https://github.com/orb-community/geo-asn-database/raw/main/asn.mmdb.gz \ + && wget -q -O /geo-db/city.mmdb.gz https://github.com/orb-community/geo-asn-database/raw/main/city.mmdb.gz + +RUN mkdir /iana +COPY ./custom-iana.csv /iana/custom-iana.csv + +RUN chmod a+x /usr/local/sbin/pktvisord \ + /usr/local/sbin/pktvisor-reader \ + /usr/local/bin/pktvisor-cli \ + /entry.sh /run.sh + +ENTRYPOINT [ "/entry.sh" ] diff --git a/docker/alpine/entry.sh b/docker/alpine/entry.sh new file mode 100644 index 000000000..ccadde521 --- /dev/null +++ b/docker/alpine/entry.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# Entry point for the Alpine-based pktvisor image. POSIX sh (no bash) and +# no crashpad — the static musl binaries are built without crashpad support. +set -e + +export PATH=$PATH:/usr/local/bin/:/usr/local/sbin/ + +trapeze() { + printf "\rFinishing container.." + exit 0 +} +trap trapeze INT + +if [ $# -eq 0 ]; then + echo "No arguments provided: specify either 'pktvisor-cli', 'pktvisor-reader' or 'pktvisord'. Try:" + echo "docker run netboxlabs/pktvisor:develop-alpine pktvisor-cli -h" + echo "docker run netboxlabs/pktvisor:develop-alpine pktvisor-reader --help" + echo "docker run netboxlabs/pktvisor:develop-alpine pktvisord --help" + exit 1 +fi + +BINARY="$1" +if [ "$BINARY" = 'pktvisor' ]; then + BINARY='pktvisor-cli' +fi +if [ "$BINARY" = 'pktvisor-pcap' ]; then + BINARY='pktvisor-reader' +fi + +if [ "$BINARY" = 'pktvisor-cli' ]; then + sleep 1 +fi + +if [ "$BINARY" = 'pktvisord' ]; then + cd /geo-db/ + if [ -f "asn.mmdb.gz" ]; then + gzip -d asn.mmdb.gz + gzip -d city.mmdb.gz + fi + cd / + while true; do + if [ ! -f "/var/run/pktvisord.pid" ]; then + nohup /run.sh "$@" & + sleep 2 + if [ -d "/nohup.out" ]; then + tail -f /nohup.out & + fi + else + PID=$(cat /var/run/pktvisord.pid) + if [ ! -d "/proc/$PID" ]; then + echo "$PID is not running" + rm /var/run/pktvisord.pid + exit 1 + fi + sleep 10 + fi + done +else + shift + exec "$BINARY" "$@" +fi diff --git a/docker/alpine/run.sh b/docker/alpine/run.sh new file mode 100644 index 000000000..a68be3186 --- /dev/null +++ b/docker/alpine/run.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# Runtime launcher for pktvisord in the Alpine image. The static musl +# build excludes crashpad, so no --cp-* flags are passed. +shift +pktvisord \ + --default-geo-city "/geo-db/city.mmdb" \ + --default-geo-asn "/geo-db/asn.mmdb" \ + --default-service-registry "/iana/custom-iana.csv" \ + "$@" & +echo $! > /var/run/pktvisord.pid