commit b3b0fd1e48a59391136a2791dd8b37711b4f333c Author: Timo Bingmann Date: Tue Oct 28 14:32:05 2025 -0700 Add Dockerfile for Claude Code diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dd910e2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,241 @@ +FROM ubuntu:25.10 + +ENV \ + DEBIAN_FRONTEND=noninteractive \ + INITRD=no \ + TZ="America/Los_Angeles" + +# Remove initctl +RUN \ + dpkg-divert --local --rename --add /sbin/initctl && \ + ln -sf /bin/true /sbin/initctl && \ + dpkg-divert --local --rename --add /usr/bin/ischroot && \ + ln -sf /bin/true /usr/bin/ischroot + +################################################################################ +# update system and install base packages + +RUN \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + apt-utils \ + apt-transport-https \ + ca-certificates \ + nano \ + tzdata && \ + apt-get upgrade -y && \ + apt-get clean -y && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN \ + update-alternatives --set editor /bin/nano && \ + ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \ + echo $TZ > /etc/timezone && \ + dpkg-reconfigure tzdata && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# Add eBay Root CA Certificate +RUN cat < /usr/local/share/ca-certificates/ebay-root-ca.crt +-----BEGIN CERTIFICATE----- +MIIGMjCCBBqgAwIBAgIQRQCIgkcAjohM0C1xoDWBDjANBgkqhkiG9w0BAQsFADA3 +MQswCQYDVQQGEwJ1czERMA8GA1UEChMIZUJheSBJbmMxFTATBgNVBAMTDGVCYXkg +Um9vdCBDQTAeFw0xNTA5MjQxOTAwNTNaFw0zNTA5MjQxOTA4MDRaMDcxCzAJBgNV +BAYTAnVzMREwDwYDVQQKEwhlQmF5IEluYzEVMBMGA1UEAxMMZUJheSBSb290IENB +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1wskOGcbS9crEfeqokRt +fZlVAQOIj4fbaZdxrvMqPiqxPyj98NZ8cNyLN+NxkVKEJZZqbb8d7JjVCCr44f7G +5Gi6yO6MYBKCtFqBR+HqDnlioJZm4wgTGTtaFWCWq3eLFJsigbdlGKXZCeawmhj1 +75D34vmFWHbUlTej67EzwSz53NgXge34X0FmoeIbiSi25j1TS41RMlDxKGaHu6/t +Z71A53q8Kj4KBEj1XrR5IDuCvdSEwbdsVWcjQUok2WAhmMsLFZhv3SMYGRdzs/ug +EmAZWp4B6i7kgYgRZ2LGZmtXR2Y8q3UrUczPucUUGUV5Iluy6Me9gruLK0LL+rzk +5VrS+79TKoi6UBTqnmGxnPru9oDwuZfnRFmdrTKsvL7fDZO1XsZILNYlj0ve5a8K +tbD/WDEuqPx7YF9jHv/vmEM9468rtYM66yQapH9n8IfIFyVtzaXkrJDzfHV7U6RM +C7bV1S3J2TaYkPhdLoUp/EPzBNRL3PoYOO9C9SSS8rTKB1af0WdabEOTW81Kiy9s +IfAeUwuUaBXnwR6cumR50LkUXHmiWpZO+Qt4QwnvXFxR9/XuFGalcOU2R0JM+EXH +5Rmq2gNUn5/XhcTh0fa8SbuChRf+Dl4O0YB/SRReam1s8SVcEKk6zf/UMMrr4fLd +29ZLWVQITgRgu2LD+2+6wpECAwEAAaOCATgwggE0MAsGA1UdDwQEAwIBhjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBSjQ7F8N33X6kfu+UUjsQK+O/j6kzAQBgkr +BgEEAYI3FQEEAwIBADCB4gYDVR0gBIHaMIHXMIHUBgRVHSAAMIHLMIHIBggrBgEF +BQcCAjCBux6BuABQAGwAZQBhAHMAZQAgAGMAbwBuAHQAYQBjAHQAIABQAEsASQBB +AGQAbQBpAG4AcwBAAGUAQgBhAHkALgBjAG8AbQAgAHQAbwAgAG8AYgB0AGEAaQBu +ACAAYQAgAGMAbwBwAHkAIABvAGYAIAB0AGgAZQAgAEMAZQByAHQAaQBmAGkAYwBh +AHQAaQBvAG4AIABQAHIAYQBjAHQAaQBjAGUAcwAgAFMAdABhAHQAZQBtAGUAbgB0 +AC4wDQYJKoZIhvcNAQELBQADggIBALRMkpOkBtYeywc9iPssXTkaphzj9DhqgBoM +jVK9kGVwXSwlal1eV2dhG0fr833yqkqaVvjsnsCmCNWZNiEKbSmdkeuT/PMxUajv +7sMaulfSuQCG+/8yuraX7ls10xIVGrdTg43amz1QGSsgvgneksjOkkhQfxJaUncQ +0uGHIOgKGGxLGoikVAmQ4Yy1PN+q5clW19ZvJk+J2qrHOdunvVFtOZStHEkIURjV +5f0J9f+aROfd3PRNrWpif3G6+l2q4jG5SJH0vPbxZgphvjhogZUK7KNR+8wMV/G6 +nmd0cmdm444wTalsIKuu6bSZ45L+9ZZaL+9Xeje04rlUOmsOMk4oGbLdiZ8imxYD +O6T5tZnfewABIeFhZcq5QYg8JzBqH0IrfOaB3vG4DyKsbmjvkzL9e7knPQEbXhyF +xnb89kXhuFfZLt0hL24frOI8HlbJUKc/snuESczkwqUteAxHLNfLlozs37SEJ16a +4pNZMIn17v1WlzMe/nh/uTGw9Ov1z9QK1owzHrTIjb20riNq1Au3TzfBIj7kA1uY +LEwFUHfXozeTUvlFPOFkOeFF8V9cqlfl87UuFs4SVgsK+uZI+QJ56G3YTUB7h5R5 +O+MnuGpUJq/+cQhEaFAKwF1B/w4ZdkEvlrvMizUGyElE5krpiZzqtSxp5xlL05SS +am1iee2A +-----END CERTIFICATE----- +EOF +RUN update-ca-certificates + +################################################################################ +# Install basic development tools +RUN apt-get update && apt-get install -y \ + \ + alsa-utils \ + antlr4 \ + build-essential \ + ca-certificates \ + clang \ + clang-format \ + clang-tidy \ + clang-tools \ + cmake \ + cmake-curses-gui \ + curl \ + curl \ + dnsutils \ + emscripten \ + g++ \ + gcc \ + gdb \ + git \ + iproute2 \ + ipset \ + iptables \ + libboost-dev \ + libboost-thread-dev \ + libcereal-dev \ + libcurl4-openssl-dev \ + libfontconfig1-dev \ + libfreetype6-dev \ + libgl1-mesa-dev \ + libglu1-mesa \ + libgtk-3-dev \ + libhowardhinnant-date-dev \ + libjsoncpp-dev \ + liblz4-dev \ + liblzma-dev \ + libmagic-dev \ + libmagick++-dev \ + libnlopt-cxx-dev \ + libnlopt-dev \ + libpq-dev \ + libpugixml-dev \ + libsqlite3-dev \ + libssl-dev \ + libstdc++-12-dev \ + lldb \ + make \ + mesa-utils \ + mpv \ + nano \ + netcat-traditional \ + ninja-build \ + nlohmann-json3-dev \ + nodejs \ + npm \ + pkg-config \ + pulseaudio \ + python3 \ + python3-pip \ + ragel \ + ripgrep \ + sound-theme-freedesktop \ + sudo \ + terminfo \ + unzip \ + vim \ + wget \ + xz-utils \ + zip \ + \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install basic development tools +RUN apt-get update && apt-get install -y \ + \ + tree \ + valgrind \ + libglfw3-dev \ + black \ + mypy \ + python3-pytest-mypy \ + node-typescript \ + python3-venv \ + libsdl2-dev \ + libpugixml-dev \ + libquantlib0-dev \ + default-jdk \ + \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN \ + apt-get update && apt-get install -y apt-transport-https curl gnupg && \ + echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | tee /etc/apt/sources.list.d/sbt.list && \ + echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | tee /etc/apt/sources.list.d/sbt_old.list && \ + curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/scalasbt-release.gpg --import && \ + chmod 644 /etc/apt/trusted.gpg.d/scalasbt-release.gpg && \ + apt-get update && \ + apt-get install -y sbt && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN pip install --break-system-packages pyright + +# Create user dev with uid 7777 +ARG USER_NAME=dev +ARG UID=7777 +ARG GID=1000 +RUN useradd -m -d "/home/$USER_NAME" -u $UID -g users -s /bin/bash "$USER_NAME" + +RUN groupadd -g 17 sound +RUN usermod -G sound $USER_NAME + +# Passwordless sudo is disabled. +RUN echo "dev ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/dev + +# Copy the firewall setup script +COPY init-firewall.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/init-firewall.sh && \ + echo "dev ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/node-firewall && \ + chmod 0440 /etc/sudoers.d/node-firewall + +# Setup working directory +WORKDIR /home/dev + +USER dev +RUN git config set --global "credential.helper" "store --file ~/.git-credentials" + +ENV EM_FROZEN_CACHE=0 +ENV EM_CACHE=/home/dev/.emscripten_cache/ +RUN mkdir -p $EM_CACHE +RUN embuilder build MINIMAL + +# Install Deno +ENV PATH="/home/dev/.bun/bin:$PATH" +RUN curl -fsSL https://bun.sh/install | bash + +RUN bun add -g @anthropic-ai/claude-code + +USER root + +# Install basic development tools +RUN apt-get update && apt-get install -y \ + \ + default-jdk \ + maven \ + \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Claude Code CLI +#RUN npm install -g @anthropic-ai/claude-code + +# Install OpenAI Codex CLI +#RUN npm install -g @openai/codex + +# Set up entrypoint to initialize firewall and execute commands +#ENTRYPOINT ["/usr/local/bin/init-firewall.sh"] +#ENTRYPOINT ["sudo", "-u", "dev"] +#USER $USER_NAME +#CMD ["/bin/bash"] diff --git a/init-firewall.sh b/init-firewall.sh new file mode 100644 index 0000000..b6cc0a5 --- /dev/null +++ b/init-firewall.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -e + +echo "Initializing container security settings..." + +# Reset iptables +iptables -F +iptables -P INPUT ACCEPT +iptables -P FORWARD ACCEPT +iptables -P OUTPUT DROP # Default to blocking all outbound connections + +# Allow local connections +iptables -A OUTPUT -o lo -j ACCEPT +iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT + +# Allow DNS lookups (required to resolve domains) +iptables -A OUTPUT -p udp --dport 53 -j ACCEPT +iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT + +# Allow connections to specific Anthropic endpoints +for DOMAIN in api.anthropic.com statsig.anthropic.com sentry.io g.t1.xyz wg1.t1.xyz; do + echo "Allowing access to: $DOMAIN" + for IP in $(dig +short $DOMAIN); do + # Check if the result is actually an IP address + if [[ $IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + iptables -A OUTPUT -p tcp -d $IP -j ACCEPT + fi + done +done + +# Verify the rules were applied +echo "Firewall rules successfully applied:" +iptables -L OUTPUT -n + +echo "Container security configuration complete. Claude can now use --dangerously-skip-permissions safely." + +CMDS="$@" +if [[ "$CMDS" == "" ]]; then + CMDS="/bin/bash" +fi + +# Execute the command provided as arguments (or start a shell by default) +exec sudo --user tb TERM=$TERM PULSE_SERVER=$PULSE_SERVER "$CMDS" diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..2656fa1 --- /dev/null +++ b/run.sh @@ -0,0 +1,58 @@ +#!/bin/sh -xe +# Build and launch docker container. + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) + +TAG=bingmann/dev:claude-docker +CONTAINER=claude-$(pwd | md5sum | cut -c1-8) + +if [[ "$1" == "bash" ]]; then + docker exec --interactive --tty --user tb "$CONTAINER" /bin/bash + exit 0 +fi + +docker build $SCRIPT_DIR --tag "$TAG" + +if [[ "$1" == "push" ]]; then + docker push "$TAG" + exit 0 +elif [[ "$1" == "build" ]]; then + echo "Build completed for $TAG" + exit 0 +fi + +CMDS="$@" +OPTS="" + +if [[ "$CMDS" == "" ]]; then + CMDS="/usr/local/bin/init-firewall.sh" +else + OPTS="--user tb" +fi + +CMDS="/bin/bash" +OPTS="--user tb" + +# --network=host \ + +docker run --rm --interactive --tty \ + --name "$CONTAINER" \ + --cap-add=NET_ADMIN \ + --cap-add=NET_RAW \ + --log-driver none \ + --network host \ + -v "${XDG_RUNTIME_DIR}/pulse/native:${XDG_RUNTIME_DIR}/pulse/native" \ + -v "$HOME/.config/pulse/cookie:/root/.config/pulse/cookie" \ + -e "TERM=$TERM" \ + -e "PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native" \ + -v "$PWD/:$PWD/" \ + -v "$HOME/.bash_history:/home/$(whoami)/.bash_history" \ + -v "$HOME/.claude:/home/$(whoami)/.claude" \ + -v "$HOME/.claude.json:/home/$(whoami)/.claude.json" \ + -v "$HOME/.git-credentials:/home/$(whoami)/.git-credentials:ro" \ + -e "DISPLAY=$DISPLAY" \ + -v "/tmp/.X11-unix:/tmp/.X11-unix" \ + --device /dev/dri --device /dev/snd --device /dev/vga_arbiter \ + -w "$PWD" \ + $OPTS \ + "$TAG" "$CMDS"