aboutsummaryrefslogtreecommitdiff
path: root/docker/Dockerfile
blob: a43e90fd5da36a04c0256122d16fbca80774453e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# syntax=docker/dockerfile:1
# Author:  cirakg & claude ai
# Summary: garmin-otp/dev image: Connect IQ build, test and headless-simulator toolchain (no SDK inside).
#
# garmin-otp/dev: the toolchain image for this project.
#
# Everything that builds, tests or runs the watch app happens in a container
# made from this image (README section 15). The image deliberately does NOT
# contain the Garmin Connect IQ SDK, the device files or your developer key:
#   * Garmin's licence does not allow redistributing the SDK, so `make sdk`
#     downloads it at runtime into the project's .cache/ folder, after you
#     accept the licence yourself.
#   * The developer key is generated by `make key` into .cache/keys/.
#
# Reproducibility: the base image is pinned by digest, Ubuntu packages come
# from a dated snapshot of the archive, the SDK manager CLI is checked against
# its release checksum, and Python packages install from a lock file with
# hashes (docker/requirements.txt).

ARG UBUNTU_IMAGE=ubuntu@sha256:0a9887931b0e38af2e3487ed39e29436b0535c4f3f52e57745baaf79d1898956
FROM ${UBUNTU_IMAGE}

# Dated snapshot of the Ubuntu archive (https://snapshot.ubuntu.com). Changing
# this date is the only way the Ubuntu package versions change.
ARG UBUNTU_SNAPSHOT=20261001T000000Z
# connect-iq-sdk-manager-cli, Apache-2.0: https://github.com/lindell/connect-iq-sdk-manager-cli
ARG SDKMGR_VERSION=0.8.4
ARG SDKMGR_SHA256=5d57b8f9cfcd02d3b3f48e19d6daca0480e4c6f627926f15d8617ef8a6f57e0b
# Your user and group IDs, so files written into the bind-mounted project
# folder belong to you (see the user setup at the end).
ARG UID=1000
ARG GID=1000

LABEL project=garmin-otp \
      org.opencontainers.image.title="garmin-otp/dev" \
      org.opencontainers.image.description="Connect IQ build, test and simulator toolchain (Garmin SDK not included)"

ENV DEBIAN_FRONTEND=noninteractive \
    LANG=C.UTF-8 \
    LC_ALL=C.UTF-8 \
    TZ=UTC

# Step 1: CA certificates, so apt can reach the HTTPS-only snapshot mirror.
# They come from the regular archive; apt verifies every package against the
# archive's signing keys, so this bootstrap step is integrity-checked too.
RUN apt-get update \
 && apt-get install -y --no-install-recommends ca-certificates \
 && rm -rf /var/lib/apt/lists/*

# Step 2: switch apt to the dated snapshot and install the toolchain.
#   openjdk-17-jre-headless             monkeyc (the Monkey C compiler runs on Java)
#   libwebkit2gtk-4.0-37, libgtk-3-0,   the Connect IQ simulator (GTK + WebKitGTK 4.0,
#   libusb-1.0-0, libsm6, libsecret,    which is why the base is Ubuntu 22.04: 24.04
#   dbus-x11, fonts-dejavu-core         no longer ships WebKitGTK 4.0)
#   xvfb, openbox                       virtual display and a window manager, so the
#                                       simulator runs headless and its window can be
#                                       found for screenshots
#   x11vnc, novnc, websockify           optional live view in your browser (make sim)
#   xdotool, x11-utils, imagemagick     scripted input and screenshots for UI tests
#   python3, python3-venv               Python tools (test reports, reference encoders)
#   make, openssl, unzip, curl, jq,     build helpers and developer-key generation
#   procps, file
RUN printf '%s\n' \
      "deb https://snapshot.ubuntu.com/ubuntu/${UBUNTU_SNAPSHOT} jammy main universe" \
      "deb https://snapshot.ubuntu.com/ubuntu/${UBUNTU_SNAPSHOT} jammy-updates main universe" \
      "deb https://snapshot.ubuntu.com/ubuntu/${UBUNTU_SNAPSHOT} jammy-security main universe" \
      > /etc/apt/sources.list \
 && apt-get update \
 && apt-get install -y --no-install-recommends \
      openjdk-17-jre-headless \
      libwebkit2gtk-4.0-37 libgtk-3-0 libusb-1.0-0 libsm6 libsecret-1-0 dbus-x11 \
      fonts-dejavu-core \
      xvfb openbox x11vnc novnc websockify xdotool x11-utils imagemagick \
      python3 python3-venv \
      make openssl unzip curl jq procps file \
 && rm -rf /var/lib/apt/lists/*

# Step 3: the SDK manager CLI (downloads the SDK and device files for `make sdk`),
# verified against the SHA-256 published with the release.
RUN curl -fsSL -o /tmp/sdkmgr.tgz \
      "https://github.com/lindell/connect-iq-sdk-manager-cli/releases/download/v${SDKMGR_VERSION}/connect-iq-sdk-manager-cli_${SDKMGR_VERSION}_Linux_x86_64.tar.gz" \
 && echo "${SDKMGR_SHA256}  /tmp/sdkmgr.tgz" | sha256sum --check --strict - \
 && tar -xzf /tmp/sdkmgr.tgz -C /usr/local/bin connect-iq-sdk-manager \
 && mkdir -p /usr/local/share/doc/connect-iq-sdk-manager \
 && tar -xzf /tmp/sdkmgr.tgz -C /usr/local/share/doc/connect-iq-sdk-manager LICENSE \
 && rm /tmp/sdkmgr.tgz

# Step 4: Python tools in a virtual environment: exact versions, hashes, wheels only.
COPY requirements.txt /opt/garmin-otp/requirements.txt
RUN python3 -m venv /opt/venv \
 && /opt/venv/bin/pip install --no-cache-dir --disable-pip-version-check \
      --require-hashes --only-binary :all: -r /opt/garmin-otp/requirements.txt
ENV PATH=/opt/venv/bin:${PATH}

# Step 5: the container-side scripts are not baked in. They live in the
# project (docker/scripts/, mounted at /work), so they are versioned with the
# code and a script change never needs an image rebuild.
ENV PATH=/work/docker/scripts:${PATH}

# Step 6: an unprivileged user with your UID/GID. Containers also run with
# `--user`, but Java takes its home directory from /etc/passwd, and the Garmin
# tools keep the SDK and device files under ~/.Garmin. At runtime /home/dev is
# replaced by the project's .cache/home folder, so all of that stays inside the
# project and disappears with `make nuke`.
RUN groupadd --non-unique --gid "${GID}" dev \
 && useradd --non-unique --uid "${UID}" --gid "${GID}" --home-dir /home/dev \
      --create-home --shell /bin/bash dev

USER dev
ENV HOME=/home/dev
WORKDIR /work