Files
claude-re-setup/Dockerfile
T
LinusandClaude Opus 5.5 4baf0208e1 Add Ghidra 12.2 and start it alongside Claude Desktop
Install Ghidra 12.2 from the official GitHub release into /opt/ghidra,
verified against the SHA-256 in the release notes, with Ubuntu's
openjdk-25-jdk (Ghidra 12.2 requires Java 25). Version, build date and
hash are build args.

The entrypoint, renamed from launch-claude.sh to launch-apps.sh, now
starts both apps and stops both, ending the container, when either is
closed: Ghidra when its process exits (closing the project window),
Claude Desktop when none of its windows is open or minimized. Claude is
stopped via its main process so it can shut down its own helpers.

CLAUDE.md now records that Claude Desktop and Ghidra share one
container, at the user's request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:38:38 +01:00

76 lines
3.5 KiB
Docker

FROM ubuntu:24.04
ARG DEBIAN_FRONTEND=noninteractive
# Match the host user so files written to mounted volumes keep the right owner.
ARG USER_NAME=re
ARG USER_UID=1000
ARG USER_GID=1000
# Fingerprint of Anthropic's apt signing key, from the official install docs:
# https://code.claude.com/docs/en/desktop-linux
ARG ANTHROPIC_APT_FPR=31DDDE24DDFAB679F42D7BD2BAA929FF1A7ECACE
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates curl gnupg \
&& rm -rf /var/lib/apt/lists/*
# Add Anthropic's apt repository and refuse to continue if the key is wrong.
RUN curl -fsSLo /usr/share/keyrings/claude-desktop-archive-keyring.asc \
https://downloads.claude.ai/claude-desktop/key.asc \
&& gpg --show-keys --with-colons /usr/share/keyrings/claude-desktop-archive-keyring.asc \
| grep -q "^fpr:::::::::${ANTHROPIC_APT_FPR}:" \
&& echo "deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/claude-desktop-archive-keyring.asc] https://downloads.claude.ai/claude-desktop/apt/stable stable main" \
> /etc/apt/sources.list.d/claude-desktop.list
# Recommends are skipped: they pull in QEMU/OVMF for Cowork, which needs KVM
# and isn't useful in this container. No keyring is installed: sign-in is not
# kept between runs. x11-utils provides the display check tools.
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
claude-desktop \
x11-utils \
xauth \
fonts-dejavu-core \
&& rm -rf /var/lib/apt/lists/*
# Ghidra from the official GitHub release, checked against the SHA-256 in the
# release notes: https://github.com/NationalSecurityAgency/ghidra/releases
# Ghidra 12.2 needs JDK 25 (application.java.min=25). The full JDK, not the
# headless one, because Ghidra's GUI needs the AWT/X11 libraries.
ARG GHIDRA_VERSION=12.2
ARG GHIDRA_BUILD_DATE=20261016
ARG GHIDRA_SHA256=2c2cd776db3c1f6a097ba418922378ac3649cadd5e844a6f5f088ae628a7be67
RUN apt-get update \
&& apt-get install -y --no-install-recommends openjdk-25-jdk unzip \
&& rm -rf /var/lib/apt/lists/* \
&& curl -fsSLo /tmp/ghidra.zip \
"https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_${GHIDRA_VERSION}_build/ghidra_${GHIDRA_VERSION}_PUBLIC_${GHIDRA_BUILD_DATE}.zip" \
&& echo "${GHIDRA_SHA256} /tmp/ghidra.zip" | sha256sum -c - \
&& unzip -q /tmp/ghidra.zip -d /opt \
&& rm /tmp/ghidra.zip \
&& ln -s "/opt/ghidra_${GHIDRA_VERSION}_PUBLIC" /opt/ghidra \
&& ln -s /opt/ghidra/ghidraRun /usr/local/bin/ghidra
ENV GHIDRA_INSTALL_DIR=/opt/ghidra
# Ubuntu 24.04 ships a default "ubuntu" user on UID 1000; replace it.
RUN if id ubuntu >/dev/null 2>&1; then userdel -r ubuntu; fi \
&& groupadd -g "${USER_GID}" "${USER_NAME}" \
&& useradd -m -u "${USER_UID}" -g "${USER_GID}" -s /bin/bash "${USER_NAME}" \
&& install -d -o "${USER_UID}" -g "${USER_GID}" /workspace \
&& ln -s /workspace "/home/${USER_NAME}/workspace"
COPY --chmod=755 launch-apps.sh /usr/local/bin/launch-apps
USER ${USER_NAME}
WORKDIR /home/${USER_NAME}
# launch-apps starts Claude Desktop and Ghidra and stops both (and so the
# container) when either one is closed.
# No keyring: tell Electron not to look for one. Session data lives only in
# the container's filesystem, which is discarded on exit (run with --rm), so
# the user signs in on every start.
# --no-sandbox: Docker's default seccomp profile blocks the namespaces
# Chromium's sandbox needs, so the zygote dies on start. The container's own
# seccomp/namespaces stay in place as the boundary to the host instead.
CMD ["launch-apps", "--password-store=basic", "--no-sandbox"]