diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2b93aaa --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.git/ +.github/ +.idea/ +data/ +build/ +compose.override.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d7ac640 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + + # Maintain Docker image dependencies + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "monthly" \ No newline at end of file diff --git a/.github/workflows/image.yml b/.github/workflows/image.yml new file mode 100644 index 0000000..07ac832 --- /dev/null +++ b/.github/workflows/image.yml @@ -0,0 +1,53 @@ +name: Build docker image + +on: + workflow_dispatch: + schedule: + - cron: "0 5 * * */7" + push: + branches: master + paths: + - .github/workflows/image.yml + - .dockerignore + - Dockerfile + - hack/docker-bake.hcl + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: checkout code + uses: actions/checkout@v6 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Export image repository name + run: | + echo "IMAGE_REPOSITORY=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV + env: + GITHUB_REPOSITORY: ${{ github.repository }} + + - name: Build and push images + uses: docker/bake-action@v6.10.0 + with: + files: hack/docker-bake.hcl + push: true + env: + GIT_SHA: ${{ github.sha }} + GITHUB_REPOSITORY: ${{ github.repository }} + IMAGE_NAME: ghcr.io/${{ env.IMAGE_REPOSITORY }} + REGISTRY_CACHE: ghcr.io/${{ env.IMAGE_REPOSITORY }}-cache \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..534f94c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,43 @@ +ARG BBKCLI_VERSION=1.0 + +FROM alpine:3.23 AS bbkcli + +# See: http://www.bredbandskollen.se/bredbandskollen-cli/ +ARG BBKCLI_VERSION +ARG TARGETPLATFORM +RUN case ${TARGETPLATFORM} in \ + "linux/amd64") BBKCLI_ARCH=amd64 ;; \ + "linux/arm64") BBKCLI_ARCH=aarch64 ;; \ + "linux/arm/v7") BBKCLI_ARCH=armhf ;; \ + "linux/386") BBKCLI_ARCH=i386 ;; \ + esac \ + && echo "Fetch: https://frontend.bredbandskollen.se/download/bbk_cli_linux_${BBKCLI_ARCH:-amd64}-${BBKCLI_VERSION}" \ + && wget -q https://frontend.bredbandskollen.se/download/bbk_cli_linux_${BBKCLI_ARCH:-amd64}-${BBKCLI_VERSION} -O /bbk_cli + +COPY ["./LICENSE", "/bbk_cli_license"] + + + +# Main image +FROM alpine:3.23 + +RUN apk add --update --no-cache gcompat libstdc++ tzdata \ + && ln -sf /usr/local/bin/bbk_cli /usr/local/bin/bbk + +COPY --from=bbkcli --chmod=0775 ["/bbk_cli", "/usr/local/bin/"] +COPY --from=bbkcli --chmod=0755 ["/bbk_cli_license", "/usr/local/src/bbk/LICENSE.txt"] + +ARG BBKCLI_VERSION +ARG TARGETPLATFORM +ENV BBKCLI_VERSION=${BBKCLI_VERSION} +ENV PLATFORM_ARCH=${TARGETPLATFORM} +ENV TZ=Europe/Stockholm + +LABEL org.opencontainers.image.title="Bredbandskollen CLI" \ + org.opencontainers.image.description="Bredbandskollen CLI, a bandwidth measurement tool" \ + org.opencontainers.image.authors="The Swedish Internet Foundation " \ + org.opencontainers.image.vendor="The Swedish Internet Foundation" \ + org.opencontainers.image.url="https://www.bredbandskollen.se/om/mer-om-bbk/bredbandskollen-cli/" \ + org.opencontainers.image.licenses="MIT" + +ENTRYPOINT [ "/usr/local/bin/bbk_cli" ] diff --git a/README.md b/README.md index da10df6..adf1fb1 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,23 @@ For more information, see "Platform Notes" below. # How to run the CLI client -To perform a mesurement, simply run the executable program that was built using -the above steps. For more information, run it with the --help argument or read +To perform a measurement, simply run the executable program that was built using +the above steps or use one of our prebuilt lightweight docker images. For more information, run it with the --help argument or read https://frontend.bredbandskollen.se/download/README.txt +## Run with docker + +### To print help statement: + docker run --init --rm -it ghcr.io/dotse/bbk:1.2.2 --help + +### Run measurement: + docker run --init --rm --net=host -it ghcr.io/dotse/bbk:1.2.2 + +Alternatively, you can use bridge network, but measurement might be inaccurate due to bridge / NAT overhead: + + docker run --init --rm -it ghcr.io/dotse/bbk:1.2.2 + # About the source code The directories framework and http contain a basic C++ network programming diff --git a/hack/docker-bake.hcl b/hack/docker-bake.hcl new file mode 100644 index 0000000..660cb74 --- /dev/null +++ b/hack/docker-bake.hcl @@ -0,0 +1,105 @@ +group "default" { + targets = ["regular"] +} + +variable "IMAGE_NAME" { + default = "ghcr.io/dotse/bbk" +} + +variable "REGISTRY_CACHE" { + default = "ghcr.io/dotse/bbk-cache" +} + +variable "GIT_SHA" { + default = "local-dev" +} + +variable "GITHUB_REPOSITORY" { + default = "dotse/bbk" +} + +variable "BBKCLI_VERSIONS" { + default = { + "1.0.0" = { + version = "1.0" + extra_tags = ["1.0.0"] + } + "1.2.2" = { + version = "1.2.2" + extra_tags = ["1", "1.2", "latest"] + } + } +} + +target "build-dockerfile" { + dockerfile = "Dockerfile" +} + +target "build-platforms" { + platforms = ["linux/amd64", "linux/arm64"] +} + +target "build-common" { + pull = true +} + +# Get the arguments for the build +function "get-args" { + params = [bbkcli_version] + result = { + BBKCLI_VERSION = bbkcli_version + } +} + +# Get the cache-from configuration +function "get-cache-from" { + params = [version] + result = [ + "type=registry,ref=${REGISTRY_CACHE}:${sha1("${version}-${BAKE_LOCAL_PLATFORM}")}", + "type=registry,ref=${REGISTRY_CACHE}:${sha1("master-${BAKE_LOCAL_PLATFORM}")}" + ] +} + +# Get the cache-to configuration +function "get-cache-to" { + params = [version] + result = [ + "type=registry,mode=max,ref=${REGISTRY_CACHE}:${sha1("${version}-${BAKE_LOCAL_PLATFORM}")}", + "type=registry,mode=max,ref=${REGISTRY_CACHE}:${sha1("master-${BAKE_LOCAL_PLATFORM}")}" + ] +} + +# Get list of image tags and registries +function "get-tags" { + params = [version, extra_versions] + result = concat( + [ + "${IMAGE_NAME}:${version}" + ], + flatten([ + for extra_version in extra_versions : [ + "${IMAGE_NAME}:${extra_version}" + ] + ]) + ) +} + +target "regular" { + inherits = ["build-dockerfile", "build-platforms", "build-common"] + matrix = { + version = keys(BBKCLI_VERSIONS) + } + + name = replace(version, ".", "_") + args = get-args(BBKCLI_VERSIONS[version].version) + tags = get-tags(version, BBKCLI_VERSIONS[version].extra_tags) + cache-from = get-cache-from(version) + cache-to = get-cache-to(version) + labels = { + "org.opencontainers.image.created" = "${timestamp()}" + "org.opencontainers.image.version" = BBKCLI_VERSIONS[version].version + "org.opencontainers.image.revision" = GIT_SHA + "org.opencontainers.image.source" = "https://github.com/${GITHUB_REPOSITORY}" + "org.opencontainers.image.documentation" = "https://github.com/${GITHUB_REPOSITORY}/blob/master/README.md" + } +} \ No newline at end of file