diff --git a/.github/workflows/docker-latest-image.yml b/.github/workflows/docker-latest-image.yml new file mode 100644 index 00000000..6bde4676 --- /dev/null +++ b/.github/workflows/docker-latest-image.yml @@ -0,0 +1,103 @@ +name: docker-latest-image + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +on: + workflow_dispatch: + push: + branches: + - 'master' + - 'docker-image' + +env: + # Use docker.io for Docker Hub if empty + REGISTRY: quay.io + # github.repository as / + IMAGE_NAME: 'ptcpdump/ptcpdump' + + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + with: + fetch-depth: '100' + fetch-tags: 'true' + + # Set up BuildKit Docker container builder to be able to build + # multi-platform images and export cache + # https://github.com/docker/setup-buildx-action + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1 + with: + platforms: linux/amd64,linux/arm64 + + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + if: github.event_name != 'pull_request' + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.QUAY_USER }} + password: ${{ secrets.QUAY_PASSWD }} + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: generate tag name + run: | + echo "TAG_NAME=$(git describe --always)" >> $GITHUB_ENV + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image (no latest tag) + id: build-and-push + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 + with: + context: . + file: Dockerfile + platforms: linux/amd64,linux/arm64 + # platforms: linux/amd64 + push: ${{ github.event_name != 'pull_request' }} + tags: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG_NAME }}' + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: test image + run: | + set -xe + + IMAGE='${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.TAG_NAME }}' + bash testdata/test_run_with_docker.sh ${IMAGE} + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image (latest tag) + id: build-and-push-latest + uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0 + with: + context: . + file: Dockerfile + platforms: linux/amd64,linux/arm64 + # platforms: linux/amd64 + push: ${{ github.event_name != 'pull_request' }} + tags: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest' + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..045d05de --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +# .github/build.Dockerfile +FROM quay.io/ptcpdump/develop:latest as build +WORKDIR /app +COPY . . +RUN make build + +FROM busybox:latest +WORKDIR /ptcpdump +COPY --from=build /app/ptcpdump /usr/local/bin/ diff --git a/Makefile b/Makefile index 61946fa3..8e678352 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,8 @@ CARCH ?= $(shell uname -m) LIBPCAP_ARCH = $(CARCH)-unknown-linux-gnu LIBPCAP_CC ?= gcc -IMAGE_BUILD ?= quay.io/ptcpdump/develop:latest +IMAGE_DEV ?= quay.io/ptcpdump/develop:latest +IMAGE_BIN ?= quay.io/ptcpdump/ptcpdump:latest .PHONY: libpcap libpcap: $(LIBPCAP_OBJ) @@ -76,12 +77,12 @@ build-bpf: .PHONY: build-bpf-via-docker build-bpf-via-docker: - docker run --rm -v `pwd`:/app quay.io/ptcpdump/develop:latest make build-bpf + docker run --rm -v `pwd`:/app $(IMAGE_DEV) make build-bpf .PHONY: build-via-docker build-via-docker: - docker run --rm -v `pwd`:/app quay.io/ptcpdump/develop:latest make build + docker run --rm -v `pwd`:/app $(IMAGE_DEV) make build .PHONY: lint diff --git a/README.md b/README.md index cde4fab6..3b7ecdd1 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,20 @@ With `-X`:

🔝

+### Running with Docker + +Docker images for `ptcpdump` are published at https://quay.io/repository/ptcpdump/ptcpdump. + +``` +docker run --privileged --rm -t --net=host --pid=host \ + -v /sys/kernel/debug/:/sys/kernel/debug/ \ + -v /run/netns/:/run/netns/ \ + -v `pwd`:/ptcpdump quay.io/ptcpdump/ptcpdump:latest ptcpdump -i any tcp +``` + +

🔝

+ + ### Flags diff --git a/testdata/run_with_docker.sh b/testdata/run_with_docker.sh new file mode 100644 index 00000000..89909eed --- /dev/null +++ b/testdata/run_with_docker.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -ex + +IMAGE="$1" +TMP=${TMP:-/tmp/} +shift + +docker run --privileged --rm -t --net=host --pid=host \ + -v /sys/kernel/debug/:/sys/kernel/debug/ \ + -v /run/netns/:/run/netns/ \ + -v ${TMP}:/tmp/ \ + -v `pwd`:/ptcpdump "${IMAGE}" ptcpdump $@ diff --git a/testdata/test_run_with_docker.sh b/testdata/test_run_with_docker.sh new file mode 100644 index 00000000..df1278e6 --- /dev/null +++ b/testdata/test_run_with_docker.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +set -ex + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )" + +IMAGE="$1" +CMD="bash ${SCRIPT_DIR}/run_with_docker.sh ${IMAGE}" +FILE_PREFIX="/tmp/ptcpdump" +FNAME="${FILE_PREFIX}_run_with_docker_base.pcapng" +LNAME="${FILE_PREFIX}_run_with_docker_base.log" +RNAME="${FILE_PREFIX}_run_with_docker_base.read.txt" +export TMP="/tmp/" + + +function test_ptcpdump() { + timeout 30s ${CMD} -c 1 -v -i any --print -w "${FNAME}" \ + 'dst host 1.1.1.1 and tcp[tcpflags] = tcp-syn' | tee "${LNAME}" & + sleep 10 + curl -m 10 1.1.1.1 &>/dev/null || true + wait + + cat "${LNAME}" + cat "${LNAME}" | grep '/usr/bin/curl' + cat "${LNAME}" | grep -F ' > 1.1.1.1.80: Flags [S],' # SYN +} + +function test_tcpdump_read() { + which tcpdump || (apt update || true && apt install -y tcpdump) + tcpdump -nr "${FNAME}" + tcpdump -nr "${FNAME}" | grep -F ' > 1.1.1.1.80: Flags [S],' # SYN +} + +function test_ptcpdump_read() { + EXPECT_NAME="${LNAME}.read.expect" + cat "${LNAME}" |grep -v packets |grep -v WARN > "${EXPECT_NAME}" + timeout 30s ${CMD} -v -r "${FNAME}" |tee "${RNAME}" + diff "${EXPECT_NAME}" "${RNAME}" +} + +function main() { + test_ptcpdump + test_tcpdump_read + test_ptcpdump_read +} + +main