|
| 1 | +// CHANGE: use the shared link-foundation JS box as the generated project base image |
| 2 | +// WHY: issue #267 asks docker-git to reuse unified box containers instead of maintaining a raw Ubuntu workspace base; the Docker Hub JS image is public and version-pinned to avoid latest drift |
| 3 | +// QUOTE(ТЗ): "Что бы не зависить только от своих обновлений, а иметь единую инфраструктру есть смысл юзать готовый репозиторий" |
| 4 | +// REF: issue-267 |
| 5 | +// SOURCE: https://github.com/link-foundation/box#docker-hub---combo-boxes |
| 6 | +// FORMAT THEOREM: renderDockerfile(config) -> base_image_default(rendered) = konard/box-js:2.1.1 |
| 7 | +// PURITY: CORE |
| 8 | +// INVARIANT: the rendered Dockerfile inherits JS/runtime tooling from link-foundation/box while preserving docker-git bootstrap layers |
| 9 | +// COMPLEXITY: O(1)/O(1) |
| 10 | +const dockerGitBaseImage = "konard/box-js:2.1.1" |
| 11 | + |
| 12 | +// CHANGE: include tmux in generated project images for durable terminal multiplexing. |
| 13 | +// WHY: stable project SSH links attach to persisted tmux sessions instead of one-off shell processes. |
| 14 | +// QUOTE(ТЗ): n/a |
| 15 | +// REF: PR-309 |
| 16 | +// SOURCE: n/a |
| 17 | +// PURITY: CORE |
| 18 | +// INVARIANT: generated base image contains the terminal multiplexer required by project SSH sessions. |
| 19 | +// COMPLEXITY: O(1)/O(1) |
| 20 | +const renderDockerfileBase = (): string => |
| 21 | + `ARG DOCKER_GIT_BASE_IMAGE=${dockerGitBaseImage} |
| 22 | +FROM \${DOCKER_GIT_BASE_IMAGE} |
| 23 | +
|
| 24 | +#checkov:skip=CKV_DOCKER_8: docker-git entrypoint must start as root to prepare SSH/auth/bootstrap and run sshd |
| 25 | +USER root |
| 26 | +ARG UBUNTU_APT_MIRROR= |
| 27 | +ENV DEBIAN_FRONTEND=noninteractive |
| 28 | +ENV NVM_DIR=/usr/local/nvm |
| 29 | +
|
| 30 | +RUN set -eu; \ |
| 31 | + if [ -n "\${UBUNTU_APT_MIRROR:-}" ]; then \ |
| 32 | + sed -i \ |
| 33 | + -e "s|http://archive.ubuntu.com/ubuntu|\${UBUNTU_APT_MIRROR}|g" \ |
| 34 | + -e "s|http://security.ubuntu.com/ubuntu|\${UBUNTU_APT_MIRROR}|g" \ |
| 35 | + /etc/apt/sources.list /etc/apt/sources.list.d/ubuntu.sources 2>/dev/null || true; \ |
| 36 | + fi; \ |
| 37 | + for attempt in 1 2 3 4 5; do \ |
| 38 | + rm -rf /var/lib/apt/lists/*; \ |
| 39 | + if apt-get -o Acquire::Retries=3 -o Acquire::By-Hash=force update; then \ |
| 40 | + break; \ |
| 41 | + fi; \ |
| 42 | + if [ "$attempt" = "5" ]; then \ |
| 43 | + echo "apt-get update failed after retries" >&2; \ |
| 44 | + exit 1; \ |
| 45 | + fi; \ |
| 46 | + echo "apt-get update attempt \${attempt} failed; retrying..." >&2; \ |
| 47 | + sleep $((attempt * 2)); \ |
| 48 | + done; \ |
| 49 | + apt-get -o Acquire::Retries=3 install -y --no-install-recommends \ |
| 50 | + openssh-server git gh ca-certificates curl unzip bsdutils sudo tmux \ |
| 51 | + make docker.io docker-compose-v2 bash-completion zsh zsh-autosuggestions xauth \ |
| 52 | + ncurses-term jq \ |
| 53 | + && rm -rf /var/lib/apt/lists/*` |
| 54 | + |
| 55 | +// CHANGE: install the unified Rust browser connection with a current Rust toolchain. |
| 56 | +// WHY: rust-browser-connection uses modern Cargo metadata; Ubuntu apt cargo 1.75 cannot resolve edition-2024 dependencies pulled by current crates. |
| 57 | +// QUOTE(ТЗ): "Rust-only отдельный модуль для noVNC/browser, без TS-дублирования" |
| 58 | +// REF: issue-347 |
| 59 | +// SOURCE: n/a |
| 60 | +// FORMAT THEOREM: image_build_success -> executable(/usr/local/bin/docker-git-browser-connection) |
| 61 | +// PURITY: SHELL |
| 62 | +// EFFECT: Docker build downloads rustup and installs the GitHub Rust crate. |
| 63 | +// INVARIANT: generated images use rustup stable for cargo install and expose the browser binary on runtime PATH. |
| 64 | +// COMPLEXITY: O(network + cargo_build) |
| 65 | +const renderDockerfileRustBrowserConnection = (): string => |
| 66 | + `ENV CARGO_HOME=/usr/local/cargo |
| 67 | +ENV RUSTUP_HOME=/usr/local/rustup |
| 68 | +ENV PATH="/usr/local/cargo/bin:/root/.cargo/bin:/home/box/.cargo/bin:\${PATH}" |
| 69 | +RUN set -eu; \ |
| 70 | + curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs -o /tmp/rustup-init.sh; \ |
| 71 | + HOME=/root sh /tmp/rustup-init.sh -y --profile minimal --default-toolchain stable --no-modify-path; \ |
| 72 | + rm -f /tmp/rustup-init.sh; \ |
| 73 | + rustc --version; \ |
| 74 | + cargo --version |
| 75 | +
|
| 76 | +# Install unified Rust browser connection (noVNC + CDP + single dg-*-browser guarantee) |
| 77 | +# Replaces all previous TS/MCP browser-connection duplication (per issue #347) |
| 78 | +RUN cargo install --git https://github.com/ProverCoderAI/rust-browser-connection --branch main --locked --root /usr/local docker-git-browser-connection \ |
| 79 | + && /usr/local/bin/docker-git-browser-connection --version |
| 80 | +
|
| 81 | +# Passwordless sudo for all users (container is disposable) |
| 82 | +RUN printf "%s\\n" "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/zz-all \ |
| 83 | + && chmod 0440 /etc/sudoers.d/zz-all` |
| 84 | + |
| 85 | +/** |
| 86 | + * Renders the base image, package prelude, Rust toolchain, and browser module install. |
| 87 | + * |
| 88 | + * @returns Dockerfile fragment that establishes the shared project container base. |
| 89 | + * @pure true |
| 90 | + * @effect none; CORE template renderer only constructs a string. |
| 91 | + * @invariant the returned fragment starts from the configured shared JS box image and installs the Rust browser CLI. |
| 92 | + * @precondition docker-git generated entrypoint remains the container entrypoint. |
| 93 | + * @postcondition the fragment keeps root available for setup and publishes docker-git-browser-connection on PATH. |
| 94 | + * @complexity O(1) time / O(1) space. |
| 95 | + */ |
| 96 | +export const renderDockerfilePrelude = (): string => |
| 97 | + [renderDockerfileBase(), renderDockerfileRustBrowserConnection()].join("\n\n") |
0 commit comments