Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
hooks
Dockerfile
README.md
img/
15 changes: 13 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
FROM alpine:latest
LABEL maintainer "Andrew <me@duck.me.uk>"
# see hooks/build and hooks/.config
ARG BASE_IMAGE_PREFIX
FROM ${BASE_IMAGE_PREFIX}alpine

# see hooks/post_checkout
ARG ARCH
COPY qemu-${ARCH}-static /usr/bin

RUN uname -ar > /uname.build
RUN apk --update add file

LABEL maintainer "Matt Hilton <matthilton2005@gmail.com>"

RUN apk add --no-cache python3 \
libusb \
Expand All @@ -22,6 +32,7 @@ RUN pip3 install \
oauth2 \
tzlocal \
pycrypto \
paho-mqtt \
pywws

VOLUME ["/var/data"]
28 changes: 24 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# pywws-docker
[Docker Hub](https://hub.docker.com/r/duckfullstop/pywws-docker/)
[Docker Hub](https://hub.docker.com/r/matt2005/pywws/)

Provides a Docker image for pywws. Find out more about pywws here: https://github.com/jim-easterbrook/pywws

Expand All @@ -8,9 +8,29 @@ Based on Alpine Linux, which provides far leaner images (sub-100mb!)
Use `--privileged` to give access to USB devices (you should also be able to directly pipe your weather station's HID device into the container with `--device`, but it's untested!)

Test the connection like this:

docker run –-privileged duckfullstop/pywws pywws-testweatherstation
```bash
docker run –-privileged matt2005/pywws pywws-testweatherstation
```

Following Jim's example using ~/weather/data, you can gather data onto your local file system like this:
```bash
docker run -–privileged -v ~/weather/data:/var/data matt2005/pywws pywws-livelog /var/data
```

Docker-compose example
```docker
version: "3"

docker run -–privileged -v ~/weather/data:/var/data duckfullstop/pywws-docker pywws-livelog /var/data
services:
pywws:
container_name: pywws
image: matt2005/pywws:latest
privileged: true
command: ["pywws-livelog", "/var/data"]
volumes:
- '/etc/localtime:/etc/localtime:ro'
- './pywws/weather/data:/var/data'
devices:
- '/dev/bus/usb/005/002'
restart: unless-stopped
```
17 changes: 17 additions & 0 deletions hooks/.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export PATH="$PWD/docker:$PATH"

# =>
# https://hub.docker.com/u/arm64v8/
# https://hub.docker.com/u/arm32v7/
# https://hub.docker.com/u/arm32v6/
declare -A base_image_prefix_map=( ["aarch64"]="arm64v8/" ["arm"]="arm32v6/" ["amd64"]="")

# => dpkg -L qemu-user-static | grep /usr/bin/
declare -A docker_qemu_arch_map=( ["aarch64"]="aarch64" ["arm"]="arm" ["amd64"]="x86_64")

# => https://github.com/docker/docker-ce/blob/76ac3a4952a9c03f04f26fc88d3160acd51d1702/components/cli/cli/command/manifest/util.go#L22
declare -A docker_to_manifest_map=( ["aarch64"]="arm64" ["arm"]="arm" ["amd64"]="amd64")

build_architectures=(amd64 aarch64 arm)

docker -v
54 changes: 54 additions & 0 deletions hooks/build
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/bin/bash
set -eu

echo "🔵 build"
source hooks/.config

for arch in ${build_architectures[@]}; do
echo "✅ building $arch"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"

BASE_IMAGE_PREFIX="${base_image_prefix_map[${arch}]}"
docker build \
--build-arg BASE_IMAGE_PREFIX=${BASE_IMAGE_PREFIX} \
--build-arg ARCH=${arch} \
--file $DOCKERFILE_PATH \
--tag "${IMAGE_NAME}-${arch}" \
.
done

echo "✅ images built:"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"
docker image ls

# https://github.com/moby/moby/issues/36552
#
tempdir=$(mktemp -d -t yolo.XXXXXXXX)
cd $tempdir

for arch in ${build_architectures[@]}; do
echo "✅ yolo fixing platform $arch"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"

manifest_arch=${docker_to_manifest_map[${arch}]}
docker save "${IMAGE_NAME}-${arch}" | tar xv

for filename in */json; do
[ -e "$filename" ] || continue
jq --compact-output 'del(.architecture)' < "$filename" | sponge "$filename"
done

for filename in *.json; do
[ -e "$filename" ] || continue
! [ $filename = "manifest.json" ] || continue

jq --arg architecture "$manifest_arch" \
--compact-output '.architecture=$architecture' < "$filename" | sponge "$filename"
done

tar cv . | docker load
rm -rf $tempdir/*
done

trap "exit 1" HUP INT PIPE QUIT TERM
trap "rm -rf $tempdir" EXIT
48 changes: 48 additions & 0 deletions hooks/post_checkout
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash
set -eu

echo "🔵 post_checkout"
source hooks/.config

echo "✅ Install qemu + binfmt support"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"
# it's an Ubuntu VM and you can install stuff.
apt-get update
apt-get install -y curl qemu-user-static binfmt-support jq moreutils

# Sadly docker itself uses Docker EE 17.06 on Dockerhub which does not support
# manifests.
echo "✅ Install a fresh docker cli binary"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"

curl https://download.docker.com/linux/static/stable/x86_64/docker-18.09.1.tgz | \
tar xvz docker/docker

echo "✅ Build a usable config.json file"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"
# Manifests are still experimental and enabled by a config file flag.
# Interestingly, there is no config file and the credential parts to push
# images is available in an environment variable. Let's create a config file to
# combine the two things:
#
mkdir -p ~/.docker
jq --null-input --argjson auths "$DOCKERCFG" '. + {auths: $auths}' | \
jq --arg experimental enabled '. + {experimental: $experimental}' | \
sponge ~/.docker/config.json

echo "✅ Copy qemu binaries into docker build context"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"
# The current setup copies the qemu binary into the image (see Dockerfile)
# Pro:
# - it's easy to run non-amd64 images on amd64 systems for debugging
# Contra:
# - it's dead weight in the "destination" architecture and consumes space
# Alternative:
# - use a multistage Dockerfile (no RUN in the last stage possible of course)
# - wait for https://github.com/moby/moby/issues/14080
#
for arch in ${build_architectures[@]}; do
cp /usr/bin/qemu-${docker_qemu_arch_map[${arch}]}-static qemu-${arch}-static
done

ls -la
10 changes: 10 additions & 0 deletions hooks/pre_build
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
set -eu

echo "🔵 pre_build"
source hooks/.config

echo "✅ Register qemu-*-static for all supported processors except current"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"

docker run --rm --privileged multiarch/qemu-user-static:register --reset
52 changes: 52 additions & 0 deletions hooks/push
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/bash
set -eu

echo "🔵 push"
source hooks/.config

# 1. push all images
DOCKER_REPO="${DOCKER_REPO//index.docker.io\/}"

for arch in ${build_architectures[@]}; do
echo "✅ Pushing ${IMAGE_NAME}-${arch}"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"
echo
docker push ${IMAGE_NAME}-${arch}
done


# 2. build and push manifest
DOCKER_REPO="index.docker.io/${DOCKER_REPO}"
manifests=""

for arch in ${build_architectures[@]}; do
manifests="${manifests} ${IMAGE_NAME}-${arch}"
done

echo "✅ Creating manifest ${IMAGE_NAME}"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"
docker manifest create ${IMAGE_NAME} \
$manifests
echo

echo "✅ Annotating manifest"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"
for arch in ${build_architectures[@]}; do
docker manifest annotate ${IMAGE_NAME} \
${IMAGE_NAME}-${arch} \
--os linux \
--arch ${docker_to_manifest_map[${arch}]}
done

echo "✅ Inspecting manifest ${IMAGE_NAME}"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"
docker manifest inspect ${IMAGE_NAME}
echo

echo "✅ Pushing manifest ${IMAGE_NAME}"
echo "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯"
docker manifest push --purge ${IMAGE_NAME}
echo

echo
echo "😊"