diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..f7143369 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +* +!Containerfile* +!Dockerfile +!README.md +!bin/container-entrypoint.sh +!examples/ +!extra/ +!meshtastic/ +!poetry.lock +!protobufs/ +!pyproject.toml diff --git a/.github/workflows/container-build.yaml b/.github/workflows/container-build.yaml new file mode 100644 index 00000000..0e3d14f3 --- /dev/null +++ b/.github/workflows/container-build.yaml @@ -0,0 +1,77 @@ +name: Create and publish Container image + +on: + push: + branches: + - master + tags: + - 'v*' + pull_request: + branches: + - master + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + continue-on-error: true + permissions: + contents: read + packages: write + strategy: + matrix: + include: + - container: Containerfile.debian + autotag: false + suffix: -debian + - container: Containerfile.alpine + autotag: ${{ github.ref == 'refs/heads/master' && 'true' || 'auto' }} + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to Container registry + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + images: | + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=edge + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + flavor: | + latest=${{ matrix.autotag }} + suffix=${{ matrix.suffix }} + + - name: Build and push + uses: docker/build-push-action@v4 + with: + platforms: linux/amd64,linux/386,linux/arm64,linux/arm/v7,linux/arm/v6 + context: . + file: ${{ matrix.container }} + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Containerfile b/Containerfile new file mode 120000 index 00000000..83ac7f48 --- /dev/null +++ b/Containerfile @@ -0,0 +1 @@ +Containerfile.alpine \ No newline at end of file diff --git a/Containerfile.alpine b/Containerfile.alpine new file mode 100644 index 00000000..66463664 --- /dev/null +++ b/Containerfile.alpine @@ -0,0 +1,20 @@ +ARG TARGET_VERSION="3.11-alpine" +ARG TARGET_ARCH="library" + +FROM docker.io/${TARGET_ARCH}/python:${TARGET_VERSION} + +WORKDIR /usr/local/app + +COPY . /usr/local/app + +RUN _poetry_venv_dir="$(mktemp -d -p "${TMPDIR:-/tmp}" 'poetry_venv.XXXXXX')" && \ + python -m 'venv' "${_poetry_venv_dir}" && \ + "${_poetry_venv_dir}/bin/pip" install 'poetry' && \ + "${_poetry_venv_dir}/bin/poetry" config --local virtualenvs.create false && \ + "${_poetry_venv_dir}/bin/poetry" install && \ + rm -f -r "${_poetry_venv_dir}" && \ + rm -f -r "/src" + +COPY "./bin/container-entrypoint.sh" "/init" + +ENTRYPOINT [ "/init" ] diff --git a/Containerfile.debian b/Containerfile.debian new file mode 100644 index 00000000..d67a1b6a --- /dev/null +++ b/Containerfile.debian @@ -0,0 +1,20 @@ +ARG TARGET_VERSION="3.11" +ARG TARGET_ARCH="library" + +FROM docker.io/${TARGET_ARCH}/python:${TARGET_VERSION} + +WORKDIR /usr/local/app + +COPY . /usr/local/app + +RUN _poetry_venv_dir="$(mktemp -d -p "${TMPDIR:-/tmp}" 'poetry_venv.XXXXXX')" && \ + python -m 'venv' "${_poetry_venv_dir}" && \ + "${_poetry_venv_dir}/bin/pip" install 'poetry' && \ + "${_poetry_venv_dir}/bin/poetry" config --local virtualenvs.create false && \ + "${_poetry_venv_dir}/bin/poetry" install --no-directory && \ + rm -f -r "${_poetry_venv_dir}" && \ + rm -f -r "/src" + +COPY "./bin/container-entrypoint.sh" "/init" + +ENTRYPOINT [ "/init" ] diff --git a/Dockerfile b/Dockerfile new file mode 120000 index 00000000..5240dc01 --- /dev/null +++ b/Dockerfile @@ -0,0 +1 @@ +Containerfile \ No newline at end of file diff --git a/bin/container-entrypoint.sh b/bin/container-entrypoint.sh new file mode 100755 index 00000000..4aeb841a --- /dev/null +++ b/bin/container-entrypoint.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-3.0-or-later +# +# Copyright (C) 2025 Olliver Schinagl +# +# A beginning user should be able to docker run image bash (or sh) without +# needing to learn about --entrypoint +# https://github.com/docker-library/official-images#consistency + +set -eu + +bin='meshtastic' + +# run command if it is not starting with a "-" and is an executable in PATH +if [ "${#}" -le 0 ] || \ + [ "${1#-}" != "${1}" ] || \ + [ -d "${1}" ] || \ + ! command -v "${1}" > '/dev/null' 2>&1; then + entrypoint='true' +fi + +exec ${entrypoint:+${bin:?}} "${@}" + +exit 0