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 # Enable the "Developer" plugin package (File > Configure > Developer) in the # CodeBrowser. Ghidra copies its default tools into the user's settings on # first start, and settings are reset on every container start, so the # default CodeBrowser.tool inside the jar is patched instead of user config. # The build fails if the line could not be inserted. RUN set -e; cd /tmp \ && jar_file=/opt/ghidra/Ghidra/Configurations/Public_Release/lib/Public_Release.jar \ && unzip -q "$jar_file" defaultTools/CodeBrowser.tool \ && sed -i '0,/\n ' defaultTools/CodeBrowser.tool \ && jar uf "$jar_file" defaultTools/CodeBrowser.tool \ && rm -r /tmp/defaultTools # 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"]