Skip to content

Commit edf9878

Browse files
authored
chore: Add local-testing Dockerfile and build script for feature branch testing in docker (#674)
1 parent cf8de65 commit edf9878

5 files changed

Lines changed: 158 additions & 0 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/node_modules/
22
var/
33
/installer/go/out/
4+
flowfuse-device-agent-*.tgz

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
.browserslistrc
55
/test/
66
/var/
7+
flowfuse-device-agent-*.tgz

docker/Dockerfile.local

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Local-testing variant of docker/Dockerfile.
2+
# Instead of installing the published @flowfuse/device-agent from npm, it
3+
# installs a tarball built from the local working copy via `npm pack`.
4+
#
5+
# Build context MUST be the device-agent repo root so the .tgz is reachable:
6+
# cd packages/device-agent
7+
# npm pack
8+
# docker build -f docker/Dockerfile.local -t flowfuse/device-agent:local .
9+
ARG NODE_VERSION=24
10+
FROM node:${NODE_VERSION}-alpine
11+
12+
ARG FF_UID=2000
13+
ARG FF_GID=2000
14+
15+
RUN apk add --no-cache --virtual buildtools build-base linux-headers udev python3 openssl
16+
17+
RUN addgroup -g ${FF_GID} -S flowfuse \
18+
&& adduser -u ${FF_UID} -S -G flowfuse -h /opt/flowfuse-device flowfuse \
19+
&& mkdir -p /opt/flowfuse-device \
20+
&& chown -R "${FF_UID}":"${FF_GID}" /opt/flowfuse-device
21+
22+
# Copy the locally-built package tarball into the image and install it globally.
23+
COPY flowfuse-device-agent-*.tgz /tmp/device-agent.tgz
24+
RUN npm install -g npm \
25+
&& npm config set cache /opt/flowfuse-device/.npm --global \
26+
&& npm install -g /tmp/device-agent.tgz --omit=dev \
27+
&& rm -f /tmp/device-agent.tgz \
28+
&& chown -R ${FF_UID}:${FF_GID} /opt/flowfuse-device
29+
30+
EXPOSE 1880
31+
32+
ENV HOME=/opt/flowfuse-device
33+
34+
USER flowfuse
35+
36+
CMD ["flowfuse-device-agent"]

docker/build-local.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
## Local feature branch testing
2+
3+
The image published to a registry installs the released `@flowfuse/device-agent`
4+
package from npm. When testing **local code changes** (e.g. on a feature branch),
5+
you can use the provided helper script to build an image from your branch instead.
6+
7+
The script uses [`Dockerfile.local`](./Dockerfile.local), which packages the local
8+
source with `npm pack` and installs that tarball — mirroring how the production
9+
image installs the published package, but with your changes.
10+
11+
### Building
12+
13+
From the device-agent repo root, run the script:
14+
15+
```bash
16+
# Linux / macOS / Windows Subsystem for Linux (WSL)
17+
# optional: make the script executable:
18+
sudo chmod +x ./docker/build-local.sh
19+
# then run:
20+
./docker/build-local.sh
21+
```
22+
23+
The script will:
24+
25+
- remove any stale `flowfuse-device-agent-*.tgz`
26+
- run `npm pack` to package the local working copy
27+
- build and tag the image based on the current git branch:
28+
- on `main` → `flowfuse/device-agent:local-build`
29+
- on any other branch &rarr; `flowfuse/device-agent:<branch>-local-build`
30+
(branch lowercased, illegal tag characters replaced with `-`)
31+
32+
You can override the defaults:
33+
34+
```bash
35+
IMAGE_NAME=myorg/device-agent ./docker/build-local.sh # override repo name
36+
TAG=custom-tag ./docker/build-local.sh # override the whole tag
37+
```
38+
39+
### Running
40+
41+
Run exactly as the published image, just using the locally-built tag and
42+
mounting your `device.yml`:
43+
44+
```bash
45+
docker run --rm -it -v /path/to/device.yml:/opt/flowfuse-device/device.yml -p 1880:1880 flowfuse/device-agent:local-build
46+
```
47+
48+
Re-running a build script reassigns the tag to the freshly built image; the
49+
previous build becomes a dangling (`<none>`) image. A running container is not
50+
updated automatically — stop it and `docker run` again to pick up a rebuild.
51+
Clean up old dangling images occasionally with `docker image prune -f`.

docker/build-local.sh

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env bash
2+
# Builds a local-testing image of the device-agent from the current working copy.
3+
#
4+
# - clears any stale flowfuse-device-agent-*.tgz
5+
# - runs `npm pack` to package the local code
6+
# - tags the image based on the current git branch:
7+
# main -> flowfuse/device-agent:local-build
8+
# <other-branch> -> flowfuse/device-agent:<branch>-local-build
9+
#
10+
# Usage (from anywhere):
11+
# ./docker/build-local.sh
12+
# IMAGE_NAME=myorg/device-agent ./docker/build-local.sh # override repo name
13+
# TAG=custom-tag ./docker/build-local.sh # override the whole tag
14+
15+
# Fail fast: -e exits on any command error, -u errors on unset variables,
16+
# -o pipefail makes a pipeline fail if any stage (not just the last) fails.
17+
set -euo pipefail
18+
19+
# Generate a default image name and tag if not supplied by the caller.
20+
IMAGE_NAME="${IMAGE_NAME:-flowfuse/device-agent}"
21+
TAG="${TAG:-}"
22+
23+
# Resolve the device-agent repo root (parent of this script's /docker dir) and work from there.
24+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
25+
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
26+
cd "$REPO_ROOT"
27+
28+
# 1. Clear any old tarballs so only the fresh pack remains.
29+
for f in flowfuse-device-agent-*.tgz; do
30+
if [ -e "$f" ]; then
31+
echo "Removing old pack: $f"
32+
rm -f "$f"
33+
fi
34+
done
35+
36+
# 2. Package the local working copy.
37+
echo "Running npm pack..."
38+
npm pack
39+
40+
# 3. Work out the tag from the branch name (unless one was supplied).
41+
if [ -z "$TAG" ]; then
42+
branch="$(git rev-parse --abbrev-ref HEAD)"
43+
if [ "$branch" = "main" ]; then
44+
TAG="local-build"
45+
else
46+
# Sanitise: lowercase, and replace anything not allowed in a docker tag with '-'
47+
safe_branch="$(echo "$branch" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9_.-]/-/g')"
48+
TAG="${safe_branch}-local-build"
49+
fi
50+
fi
51+
52+
FULL_IMAGE="${IMAGE_NAME}:${TAG}"
53+
54+
# 4. Build the image (context = repo root, so the .tgz is reachable by COPY).
55+
echo "Building image: $FULL_IMAGE"
56+
docker build -f docker/Dockerfile.local -t "$FULL_IMAGE" .
57+
58+
echo ""
59+
echo "Built $FULL_IMAGE"
60+
echo ""
61+
echo "Enter the following command to run the device-agent:"
62+
echo " docker run --rm -it \\"
63+
echo " -v /opt/flowfuse-device-docker-local/device.yml:/opt/flowfuse-device/device.yml \\"
64+
echo " -p 1888:1880 \\"
65+
echo " $FULL_IMAGE"
66+
echo ""
67+
echo "NOTE:"
68+
echo "Entering the above command will run the device-agent on port 1888"
69+
echo "using your local device.yml (edit as needed before hitting enter)"

0 commit comments

Comments
 (0)