# Client image (share and/or use mode). # # Unlike the relay this container needs real access to the host's USB stack, # which only works on a Linux host: containers share the host kernel, and that # kernel is the one managing the devices. On macOS and Windows, Docker runs # inside a Linux VM that never sees the USB hardware, so this image cannot # share devices there — see README. FROM --platform=$BUILDPLATFORM golang:1.26-alpine AS builder ARG TARGETARCH ARG TARGETVARIANT WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN GOARM=$(echo "$TARGETVARIANT" | tr -d 'v') \ CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH \ go build -ldflags="-s -w" -o /usb-client ./cmd/usb-client/ FROM alpine:3.21 # usbutils gives lsusb for diagnosing what the container can actually see; # kmod lets the entrypoint check whether vhci-hcd is loaded on the host. RUN apk add --no-cache ca-certificates usbutils kmod COPY --from=builder /usb-client /usr/local/bin/usb-client COPY docker/client-entrypoint.sh /usr/local/bin/client-entrypoint.sh RUN chmod +x /usr/local/bin/client-entrypoint.sh # Runs as root deliberately: opening /dev/bus/usb, detaching kernel drivers # and rebinding them afterwards all need privileges. EXPOSE 8080 ENTRYPOINT ["/usr/local/bin/client-entrypoint.sh"] CMD ["both"]