Skip to content

Commit

Permalink
Add some rough but functional Docker support (#154)
Browse files Browse the repository at this point in the history
* add docker build

* update docker support for latest versions, and add readme

* add comment for linter
  • Loading branch information
slim-bean authored Jan 24, 2025
1 parent 506eae6 commit 3b9d8d5
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 0 deletions.
6 changes: 6 additions & 0 deletions Magefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,12 @@ func (Build) All(ctx context.Context) {
)
}

// Build a docker image, call with image name as an argument: mage -v build:dockerArm64 "slimbean/grafana-kiosk:2024-11-29"
func (Build) DockerArm64(ctx context.Context, image string) error {
log.Printf("Building docker...")
return sh.RunV("docker", "build", "--build-arg", "TARGET_PLATFORM=linux/arm64", "--build-arg", "COMPILE_GOARCH=arm64", "-t", image, "-f", "build/Dockerfile", ".")
}

// Lint Run linter against codebase
func (Build) Lint() error {
os.Setenv("GO111MODULE", "on")
Expand Down
20 changes: 20 additions & 0 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
ARG BUILD_PLATFORM=linux/amd64
ARG TARGET_PLATFORM=linux/amd64

FROM --platform=${BUILD_PLATFORM} golang:1.23-alpine AS builder
ARG COMPILE_GOOS=linux
ARG COMPILE_GOARCH=amd64
ARG COMPILE_GOARM=""
COPY . /build
WORKDIR /build
RUN CGO_ENABLED=0 GOOS=${COMPILE_GOOS} GOARCH=${COMPILE_GOARCH} GOARM=${COMPILE_GOARM} go build -ldflags '-extldflags "-static"' -o grafana-kiosk ./pkg/cmd/grafana-kiosk/main.go
RUN mv /build/grafana-kiosk /

FROM --platform=${TARGET_PLATFORM} dtcooper/raspberrypi-os:latest
RUN apt-get update && \
apt-get install -qy \
tzdata ca-certificates chromium-browser

WORKDIR /
COPY --from=builder /grafana-kiosk /kiosk/grafana-kiosk
ENTRYPOINT [ "/kiosk/grafana-kiosk" ]
240 changes: 240 additions & 0 deletions build/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
If you would like to run Grafana Kiosk from a docker container, this is possible and I do so in my kubernetes cluster!

## Note

This only works for Raspberry Pi as it uses the Raspberry Pi OS as the base image. (See Debugging)

Your raspberry pi must be running X, newer versions run wayland by default so you have to change this:
* sudo raspi-config
* Advanced Options
* Wayland
* Select `W1 X11`
* OK -> Reboot

## Build

Pass the image name in as an argument, e.g.:

```bash
mage -v build:dockerArm64 "slimbean/grafana-kiosk:2024-11-29"
```

## Running in Kubernetes

Here's an example I use which creates a namespace, the deployment and also a cron job that restarts Grafana every day.

The cron job isn't really necessary, but I generally deploy things like this with some mechanism of restarting them to deal with any unexpected issues.

Also I have a few extra affinity and toleration settings, the node in my k3s cluster that I want to run this on has a label `role=grafana-kiosk` and also a taint so I can target it specifically.

```yaml
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: role
operator: In
values:
- grafana-kiosk
```
Also that same node has a taint `role=grafana-kiosk:NoSchedule` so I can ensure that only this pod runs on that node.

```yaml
tolerations:
- effect: NoSchedule
key: role
operator: Equal
value: grafana-kiosk
```
Toleration syntax is confusing to me, but what this says is that this pod "tolerates" the taint `role=grafana-kiosk` with the value `grafana-kiosk` and the effect `NoSchedule`.


Full YAML:

Make sure to update the URL, USR, PASS, and IMAGE fields.

```yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: null
name: grafana-kiosk
spec: {}
status: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: grafana-kiosk
name: grafana-kiosk
namespace: grafana-kiosk
spec:
replicas: 1
selector:
matchLabels:
app: grafana-kiosk
strategy:
type: Recreate
template:
metadata:
creationTimestamp: null
labels:
app: grafana-kiosk
name: grafana-kiosk
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: role
operator: In
values:
- grafana-kiosk
containers:
- args:
- -URL=FIXME URL
- -login-method=local
- -username=FIXME USER
- -password=FIXME PASS
- -kiosk-mode=full
env:
- name: DISPLAY
value: unix:0.0
- name: KIOSK_DEBUG
value: "false"
image: FIXME IMAGE
imagePullPolicy: IfNotPresent
name: grafana-kiosk
ports:
- containerPort: 3000
name: http-metrics
protocol: TCP
resources:
limits:
cpu: "3"
memory: 2000Mi
requests:
cpu: "1"
memory: 500Mi
volumeMounts:
- mountPath: /tmp/.X11-unix
name: x11
tolerations:
- effect: NoSchedule
key: role
operator: Equal
value: grafana-kiosk
volumes:
- hostPath:
path: /tmp/.X11-unix
name: x11
status: {}
---
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: kiosk-cron
namespace: grafana-kiosk
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: kiosk-cron
namespace: grafana-kiosk
rules:
- apiGroups:
- apps
- extensions
resources:
- deployments
verbs:
- get
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: kiosk-cron
namespace: grafana-kiosk
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kiosk-cron
subjects:
- kind: ServiceAccount
name: kiosk-cron
namespace: grafana-kiosk
---
apiVersion: batch/v1
kind: CronJob
metadata:
creationTimestamp: null
name: kiosk-cron
namespace: grafana-kiosk
spec:
concurrencyPolicy: Forbid
jobTemplate:
metadata:
creationTimestamp: null
spec:
backoffLimit: 2
template:
metadata:
creationTimestamp: null
spec:
containers:
- command:
- kubectl
- rollout
- restart
- deployment/grafana-kiosk
image: rancher/kubectl:v1.22.2
name: kubectl
resources: {}
restartPolicy: Never
serviceAccountName: kiosk-cron
schedule: 00 07 * * *
status: {}
```


## Debugging

Debugging chromium issues is tricky...

If you get a "context canceled" error when the kiosk is starting, this is typically because the chromium process failed to start or crashed.
You can enable `KIOSK_DEBUG=true` env var but this will only help so much.

Instead I modified the docker container to sleep forever so I could run chromium exec'd into it:

using:
```dockerfile
#ENTRYPOINT [ "/kiosk/grafana-kiosk" ]
CMD sleep infinity
```

Then inside the container I was trying to run what I believe to be the similar command as run by the kiosk program

```bash
chromium --autoplay-policy=no-user-gesture-required --bwsi --check-for-update-interval=31536000 --disable-atures=Translate --disable-notifications --disable-overlay-scrollbar --disable-sync --ignore-certificate-errors=false --incognito --kiosk --noerrdialogs --kiosk --start-fullscreen --start-maximized --user-agent="Mozilla/5.0 (X11; CrOS armv7l 13597.84.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36" --window-position="0,0" --user-data-dir="/tmp/123"
```

for debian bookworm it seemed like i made progress adding:
```bash
--no-zygote --no-sandbox
```

While disabling these options worked, I found it a bit unsatisfying... and googling led me to believe that this may somehow be a raspberry pi problem which was already handled by the raspberry pi os images.

Unfortunately they don't officially publish docker images for raspberry pi os, but I was able to find someone that is, using these images fixed my problems, even though they are huge images...

Still wish I had succeeded in getting the debian images to work, but maybe I'll revisit it again someday, and since I'm running on raspberry pi's and way exceeded how much time I want to spend on this, this is how it stays for now :)

0 comments on commit 3b9d8d5

Please sign in to comment.