multiplatform build

This commit is contained in:
DasMoorhuhn 2024-06-29 03:32:54 +02:00
parent 345666cb2e
commit 5029e46359
11 changed files with 235 additions and 38 deletions

4
.gitignore vendored
View File

@ -1,4 +1,6 @@
__pycache__ __pycache__
devices.yml devices.yml
history.* history.*
data/ data/
*.iso
*.cow

View File

@ -1,4 +1,7 @@
FROM python:3.12-alpine3.20 AS build_bluepy # This is the build stage for getting all python libs. Mainly it's for reducing the final image size because for building and installing the pips, many tools are needed which are just bloat to the final image.
FROM python:3.12-alpine3.20 AS pip_build_stage
COPY ./python/requierements.txt /
RUN apk add \ RUN apk add \
make \ make \
@ -8,17 +11,32 @@ RUN apk add \
build-base \ build-base \
freetype-dev \ freetype-dev \
libpng-dev \ libpng-dev \
openblas-dev openblas-dev \
libxml2-dev \
libxslt-dev
# BluePy needs to be build here... idk why but pip install fails on alpine somehow
RUN git clone https://github.com/IanHarvey/bluepy.git && \ RUN git clone https://github.com/IanHarvey/bluepy.git && \
cd bluepy && \ cd bluepy && \
python3.12 setup.py build && \ python3.12 setup.py build && \
python3.12 setup.py install python3.12 setup.py install && \
cd /
# Normal pip install for pyyaml failed on RPI4, so I build it here
RUN git clone https://github.com/yaml/pyyaml.git && \
cd pyyaml && \
python3.12 setup.py build && \
python3.12 setup.py install && \
cd /
RUN pip3.12 install -r requierements.txt
# This is the stage for the final image
FROM python:3.12-alpine3.20 FROM python:3.12-alpine3.20
WORKDIR /src WORKDIR /src
COPY ./python/src/ . COPY ./python/src/ .
COPY ./python/requierements.txt .
COPY ./python/docker_entrypoint.sh / COPY ./python/docker_entrypoint.sh /
RUN mkdir data RUN mkdir data
RUN touch DOCKER RUN touch DOCKER
@ -26,12 +44,10 @@ VOLUME /src/data
RUN apk add --no-cache sudo bluez tzdata RUN apk add --no-cache sudo bluez tzdata
ENV TZ=Europe/Berlin ENV TZ=Europe/Berlin
ENV DOCKER=TRUE
# Copy bluepy from the bluepy build stage # Copy pips from the pip build stage
COPY --from=build_bluepy /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages COPY --from=pip_build_stage /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=build_bluepy /usr/local/bin /usr/local/bin COPY --from=pip_build_stage /usr/local/bin /usr/local/bin
RUN pip3.12 install -r requierements.txt && rm requierements.txt ENTRYPOINT sh /docker_entrypoint.sh
# RUN echo '@reboot root python3.12 /src/serve_json.py' >> /etc/crontab
ENTRYPOINT sh /docker_entrypoint.sh

35
build_docker.sh Normal file
View File

@ -0,0 +1,35 @@
ARCH=linux/arm/v6
#ARCH=linux/amd64
TAG=develop
HELP="USAGE: sh build_docker.sh \n
[ -a | --architecture ] Select a architecture. Default is auto\n
[ -t | --tag ] Set a docker tag. Default is develop \n
[ -h | --help ] Get this dialog"
docker_build(){
docker build --build-arg TARGETPLATFORM=$ARCH --platform $ARCH --tag dasmoorhuhn/atc-mithermometer-gateway:$TAG .
}
while [ "$1" != "" ]; do
case $1 in
-a | --architecture )
shift
ARCH=$1
shift
;;
-t | --tag )
shift
TAG=$1
shift
;;
-h | --help )
echo $HELP
exit
;;
* )
echo $HELP
exit 1
esac
done
docker_build

View File

@ -0,0 +1,10 @@
TAG=develop
set e
docker buildx version
unset e
docker buildx create --name builder
docker buildx use builder
docker buildx build --tag dasmoorhuhn/atc-mithermometer-gateway:$TAG --platform=linux/amd64,linux/arm64,linux/arm --push .

View File

@ -1,4 +1,10 @@
#!/bin/sh #!/bin/sh
python3.12 api_endpoints.py & env > .env
if [ "$API" = true ]; then
python3.12 api_endpoints.py &
sleep 1
fi
sudo python3.12 main.py sudo python3.12 main.py

View File

@ -1,6 +1,5 @@
pyyaml pyyaml
bs4 bs4
lxml
requests requests
flask flask
flask_cors flask_cors

View File

@ -49,7 +49,7 @@ def cleanup():
devices = [] devices = []
def start_discovery(timeout=20.0): def start_discovery(timeout=20):
cleanup() cleanup()
global devices global devices
print(f'Start discovery with timout {timeout}s...') print(f'Start discovery with timout {timeout}s...')

16
python/src/load_env.py Normal file
View File

@ -0,0 +1,16 @@
# This is a quick and dirty hack since the ENVs from the docker run command won't show up in the main.py
# I echo the output from the env command of a .env file, read and load it here into the os.environ.
# https://stackoverflow.com/questions/78684481/python-wont-find-the-env-in-my-docker-container
import os
def load_env():
if 'DOCKER' not in os.listdir('.'): return False
with open(file='.env', mode='r') as file: ENV = file.readlines()
for env in ENV:
env = env.strip()
key, value = env.split('=')
os.environ[key] = value
return True

View File

@ -3,8 +3,9 @@ from log_data import log_to_json
from discovery import start_discovery from discovery import start_discovery
def start_loop(interval=60): def start_loop(interval=40, timeout=20):
print(f"Starting loop with interval {interval}s")
while True: while True:
devices = start_discovery() devices = start_discovery(timeout=timeout)
log_to_json(devices) log_to_json(devices)
sleep(interval) sleep(interval)

View File

@ -1,9 +1,25 @@
import os
from discovery import start_discovery from discovery import start_discovery
from log_data import log_to_json from log_data import log_to_json
from loop import start_loop from loop import start_loop
from load_env import load_env
DOCKER = load_env()
INTERVAL = 40
TIMEOUT = 20
# devices = start_discovery() if DOCKER:
# log_to_json(devices) print("Running in docker")
interval = os.getenv('LOOP')
timeout = os.getenv('TIMEOUT')
start_loop() try:INTERVAL = int(interval)
except:pass
try:TIMEOUT = int(timeout)
except:pass
start_loop(INTERVAL, TIMEOUT)
else:
start_loop(interval=40)

View File

@ -1,21 +1,117 @@
TAG=develop-alpine TAG=develop
CONTAINER=dasmoorhuhn/atc-mithermometer-gateway:$TAG CONTAINER=dasmoorhuhn/atc-mithermometer-gateway:$TAG
CONTAINER_NAME=ATC_MiThermometer_Gateway
VOLUME=YOUR_VOLUME
sudo killall -9 bluetoothd > /dev/null 2>&1 D=""
# docker stop $CONTAINER > /dev/null 2>&1 TIME_ZONE="Europe/Berlin"
sh stop_docker.sh INTERACTIVE=false
docker container rm ATC_MiThermometer_Gateway > /dev/null 2>&1 BUILD=false
echo Start container... API=false
docker run \ LOOP="0"
--cap-add=SYS_ADMIN \ TIMEOUT="0"
--cap-add=NET_ADMIN \
--net=host \ HELP="USAGE: sh run_docker.sh [OPTIONS] \n
--name=ATC_MiThermometer_Gateway \ [ -d ] Run in Backgrund \n
--restart unless-stopped \ [ -t | --tag ] Set a docker tag \n
--tty \ [ -b | --build ] Build the image before running the container \n
-ti \ [ -l | --loop ] Start the gateway in looping mode. e.g.: --loop 40 will set the interval of the loop to 40s. Default is single run mode \n
-v /var/run/dbus/:/var/run/dbus/ \ [ -a | --api ] Start with the API \n
-v ./data:/src/data \ [ -tz | --timezone ] Set the timezone. Default is Europe/Berlin \n
$CONTAINER \ [ -to | --timeout ] Set the timeout for the bluetooth scan. default is 20s \n
[ -h | --help ] Get this dialog"
docker_run() {
sudo killall -9 bluetoothd > /dev/null 2>&1
echo Killing old container...
docker stop $CONTAINER_NAME
docker container rm $CONTAINER_NAME > /dev/null 2>&1
COMMAND="docker run $D"
COMMAND="$COMMAND --cap-add=SYS_ADMIN"
COMMAND="$COMMAND --cap-add=NET_ADMIN"
COMMAND="$COMMAND --net=host"
COMMAND="$COMMAND --env TZ=$TIME_ZONE"
COMMAND="$COMMAND --env API=$API"
COMMAND="$COMMAND --name=$CONTAINER_NAME"
COMMAND="$COMMAND --restart=on-failure"
COMMAND="$COMMAND --volume=/var/run/dbus/:/var/run/dbus/"
COMMAND="$COMMAND --volume=$VOLUME:/src/data"
if [ "$INTERACTIVE" = true ]; then
COMMAND="$COMMAND --interactive"
COMMAND="$COMMAND --tty"
COMMAND="$COMMAND --attach=stdout"
COMMAND="$COMMAND --attach=stdin"
fi
if [ "$LOOP" != "0" ]; then
COMMAND="$COMMAND --env LOOP=$LOOP"
fi
if [ "$TIMEOUT" != "0" ]; then
COMMAND="$COMMAND --env TIMEOUT=$TIMEOUT"
fi
if [ "$BUILD" = true ]; then
sh build_docker.sh --tag $TAG
fi
echo $COMMAND
echo Start container...
echo
$COMMAND $CONTAINER
docker container rm $CONTAINER_NAME > /dev/null 2>&1
}
while [ "$1" != "" ]; do
case $1 in
-d )
D="-d"
shift
;;
-a | --api)
API=true
shift
;;
-b | --build )
BUILD=true
shift
;;
-tz | --timezone )
shift
TIME_ZONE=$1
shift
;;
-to | --timeout )
shift
TIMEOUT=$1
shift
;;
-t | --tag )
shift
TAG=$1
shift
;;
-l | --loop )
shift
LOOP=$1
shift
;;
-i | --interactive )
INTERACTIVE=true
shift
;;
-h | --help )
echo $HELP
exit
;;
* )
echo $HELP
exit 1
esac
done
docker_run
docker container rm ATC_MiThermometer_Gateway > /dev/null 2>&1