chore: capture Jenkins Docker baseline

This commit is contained in:
Brent Perteet
2026-08-27 16:08:01 +00:00
commit 9e1cce70e6
13 changed files with 539 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
FROM ubuntu:22.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
openssh-server openjdk-17-jre-headless git make build-essential python3 \
curl unzip ca-certificates xz-utils \
# Electron runtime deps: MCUXpressoInstallerCLI ships as an Electron
# app and needs these even for headless/CLI use.
libglib2.0-0 libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 \
libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 \
libpango-1.0-0 libcairo2 libasound2 libxshmfence1 libx11-6 libxext6 \
libxrender1 libgtk-3-0 xvfb \
&& rm -rf /var/lib/apt/lists/*
RUN useradd -m -s /bin/bash jenkins \
&& mkdir -p /home/jenkins/.ssh /var/run/sshd \
&& chmod 700 /home/jenkins/.ssh
COPY secrets/agent_ssh_key.pub /home/jenkins/.ssh/authorized_keys
RUN chown -R jenkins:jenkins /home/jenkins/.ssh \
&& chmod 600 /home/jenkins/.ssh/authorized_keys
# --- MCUXpresso Installer ---------------------------------------------------
# NXP no longer ships a plain IDE .deb - the download is "MCUXpresso
# Installer", a Makeself-wrapped Electron app (*.deb.bin) that itself
# contains a documented headless CLI (MCUXpressoInstallerCLI) for fetching
# individual packages/components non-interactively, no NXP account/login
# needed at download time. Get it from https://www.nxp.com/mcuxpresso and
# place it in installers/mcuxpresso/ before building. See
# installers/mcuxpresso/README.md.
COPY installers/mcuxpresso/ /tmp/installers/
RUN set -e; \
INSTALLER=$(ls /tmp/installers/*.deb.bin 2>/dev/null | head -n1); \
if [ -z "$INSTALLER" ]; then \
echo "ERROR: no MCUXpresso installer (*.deb.bin) found in installers/mcuxpresso/. See installers/mcuxpresso/README.md" >&2; \
exit 1; \
fi; \
chmod +x "$INSTALLER"; \
# --noexec: unpack the Makeself payload (install.sh + the real .deb)
# without running install.sh, which assumes an interactive desktop user
# and does things (desktop icons, chrome-sandbox setuid) we don't need
# in a headless CI agent.
"$INSTALLER" --target /tmp/mcux_pkg --noprogress --noexec --keep; \
DEB=$(ls /tmp/mcux_pkg/*.deb | head -n1); \
dpkg -x "$DEB" /opt/mcuxpresso-installer; \
rm -rf /tmp/installers /tmp/mcux_pkg; \
# The app writes its own logs/cache next to its binary (e.g.
# <installdir>/logs/cli.log). Left root-owned, a non-root caller can't
# create that path and the app retries the failed write in an infinite
# loop instead of erroring out - so it must be writable by the jenkins
# user before anything ever invokes it.
chown -R jenkins:jenkins /opt/mcuxpresso-installer
# The installer is Electron; running as root needs a setuid chrome-sandbox
# binary we don't bother setting up, and our CI user is unprivileged anyway,
# so just disable the sandbox instead.
ENV ELECTRON_DISABLE_SANDBOX=1
# MCUXpressoInstallerCLI still initializes Electron/Chromium under the hood
# and needs *a* display even for pure CLI output, so always drive it through
# a throwaway Xvfb instance.
RUN printf '#!/bin/sh\nexec xvfb-run -a /opt/mcuxpresso-installer/MCUXpressoInstaller/MCUXpressoInstallerCLI "$@"\n' \
> /usr/local/bin/mcux-cli \
&& chmod +x /usr/local/bin/mcux-cli
# Bake in a default toolchain so pipelines aren't hitting the network on
# every build. `docker run --rm <image> mcux-cli install --help` lists every
# available -p/-c package/component and version if you want to change this.
USER jenkins
RUN mcux-cli install -c armToolchain cmake ninja; \
ARMGCC_DIR=$(ls -d /home/jenkins/.mcuxpressotools/arm-gnu-toolchain-*-x86_64-arm-none-eabi | head -n1); \
CMAKE_DIR=$(ls -d /home/jenkins/.mcuxpressotools/cmake-*-linux-x86_64 | head -n1); \
NINJA_DIR=$(ls -d /home/jenkins/.mcuxpressotools/ninja-* | head -n1); \
ln -s "$ARMGCC_DIR" /home/jenkins/.mcuxpressotools/arm-toolchain; \
ln -s "$CMAKE_DIR" /home/jenkins/.mcuxpressotools/cmake; \
ln -s "$NINJA_DIR" /home/jenkins/.mcuxpressotools/ninja; \
test -x /home/jenkins/.mcuxpressotools/arm-toolchain/bin/arm-none-eabi-gcc
USER root
ENV PATH="/home/jenkins/.mcuxpressotools/arm-toolchain/bin:/home/jenkins/.mcuxpressotools/cmake/bin:/home/jenkins/.mcuxpressotools/ninja:${PATH}"
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

72
agents/mplabx/Dockerfile Normal file
View File

@@ -0,0 +1,72 @@
FROM ubuntu:22.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
openssh-server openjdk-17-jre-headless git make build-essential \
curl unzip ca-certificates \
libxext6 libxrender1 libxtst6 libxi6 libusb-1.0-0 \
&& rm -rf /var/lib/apt/lists/*
# libX* above: MPLAB X's NetBeans-based platform pulls these in even for
# headless/CLI use (mplab_ipe, make-based project builds). Drop them if you
# confirm your specific build path never touches the IDE runtime.
# libusb-1.0-0: required by the installer's own 64-bit library check (used
# for MPLAB IPE's device programming/debug tool support).
RUN useradd -m -s /bin/bash jenkins \
&& mkdir -p /home/jenkins/.ssh /var/run/sshd \
&& chmod 700 /home/jenkins/.ssh
COPY secrets/agent_ssh_key.pub /home/jenkins/.ssh/authorized_keys
RUN chown -R jenkins:jenkins /home/jenkins/.ssh \
&& chmod 600 /home/jenkins/.ssh/authorized_keys
# --- MPLAB X IDE + XC8/XC16/XC32 compilers ---------------------------------
# Download these from https://www.microchip.com (account required) and place
# them in installers/mplabx/ before building this image. See
# installers/mplabx/README.md for expected filenames.
COPY installers/mplabx/ /tmp/installers/
RUN set -e; \
IDE_INSTALLER=$(ls /tmp/installers/MPLABX*.sh 2>/dev/null | head -n1); \
if [ -z "$IDE_INSTALLER" ]; then \
echo "ERROR: no MPLAB X installer (MPLABX-*-linux-installer.sh) found in installers/mplabx/. See installers/mplabx/README.md" >&2; \
exit 1; \
fi; \
chmod +x "$IDE_INSTALLER"; \
# These installers are makeself wrappers around an InstallBuilder elf
# installer: flags before "--" go to the makeself wrapper itself
# (--target, --nox11, ...); flags after "--" are passed through to the
# embedded installer (--mode, --unattendedmodeui, --installdir, ...).
# The wrapper's root check greps $USER (unset under plain `sh -c`, as
# Docker RUN uses) rather than trusting uid 0, so export it explicitly.
export USER=root; \
"$IDE_INSTALLER" --nox11 -- --mode unattended --unattendedmodeui none --installdir /opt/microchip/mplabx; \
# XC compiler installers ship in two different forms depending on
# version: a makeself-wrapped "*.sh" (same two-tier flag convention as
# the IDE installer above, taking --installdir) or a bare InstallBuilder
# elf "*.run" (flags passed directly, taking --prefix instead). Detect
# which by sniffing the first two bytes ("#!" vs the ELF magic).
for XC in /tmp/installers/xc8*.sh /tmp/installers/xc8*.run \
/tmp/installers/xc16*.sh /tmp/installers/xc16*.run \
/tmp/installers/xc32*.sh /tmp/installers/xc32*.run; do \
[ -f "$XC" ] || continue; \
chmod +x "$XC"; \
XC_NAME=$(basename "$XC" | cut -d- -f1); \
if [ "$(head -c2 "$XC")" = "#!" ]; then \
"$XC" --nox11 -- --mode unattended --unattendedmodeui none --installdir "/opt/microchip/$XC_NAME"; \
else \
"$XC" --mode unattended --unattendedmodeui none --prefix "/opt/microchip/$XC_NAME"; \
fi; \
done; \
rm -rf /tmp/installers
ENV PATH="/opt/microchip/mplabx/mplab_platform/bin:/opt/microchip/xc8/bin:/opt/microchip/xc16/bin:/opt/microchip/xc32/bin:${PATH}"
# The IDE installer also symlinks its main executables (mplab_ide, mplab_ipe,
# mdb, prjMakefilesGenerator, projectPackager) into /usr/bin directly, so
# they work even without the mplab_platform/bin entry above.
# --installdir/--prefix above pin each install to an unversioned path, but
# the bin/ subdirectory layout inside it can still vary by installer version
# - if `docker compose run mplabx-agent which xc32-gcc` (or mdb, etc.) comes
# up empty, inspect /opt/microchip/*/ in the built image and adjust PATH.
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]