|
| 1 | +# DevX tooling layer — sits between Dockerfile.base and Dockerfile |
| 2 | +# Build: docker-compose -f .devcontainer/docker-compose.base.yml build devx |
| 3 | +ARG BASE_IMAGE=ghcr.io/chatwoot-br/chatwoot_codespace:latest |
| 4 | +FROM ${BASE_IMAGE} |
| 5 | + |
| 6 | +USER root |
| 7 | + |
| 8 | +ARG TARGETARCH |
| 9 | +ARG USERNAME=vscode |
| 10 | + |
| 11 | +# DevX system dependencies (not needed by Rails itself) |
| 12 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 13 | + fzf \ |
| 14 | + ripgrep \ |
| 15 | + jq \ |
| 16 | + socat \ |
| 17 | + file \ |
| 18 | + poppler-utils \ |
| 19 | + man-db \ |
| 20 | + bubblewrap \ |
| 21 | + && apt-get clean \ |
| 22 | + && rm -rf /var/lib/apt/lists/* |
| 23 | + |
| 24 | +# Fish shell |
| 25 | +ARG FISH_VERSION=4.6.0 |
| 26 | +RUN FISH_ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "x86_64") && \ |
| 27 | + curl -fsSL "https://github.com/fish-shell/fish-shell/releases/download/${FISH_VERSION}/fish-${FISH_VERSION}-linux-${FISH_ARCH}.tar.xz" \ |
| 28 | + | tar xJ -C /usr/local/bin && \ |
| 29 | + echo /usr/local/bin/fish >> /etc/shells |
| 30 | + |
| 31 | +# Neovim (LazyVim requires >= 0.11.2) |
| 32 | +ARG NVIM_VERSION=0.12.0 |
| 33 | +RUN NVIM_ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "arm64" || echo "x86_64") && \ |
| 34 | + curl -fsSL "https://github.com/neovim/neovim/releases/download/v${NVIM_VERSION}/nvim-linux-${NVIM_ARCH}.tar.gz" \ |
| 35 | + | tar xz --strip-components=1 -C /usr/local && \ |
| 36 | + ln -s /usr/local/bin/nvim /usr/local/bin/vim |
| 37 | + |
| 38 | +# Configure vscode user: set shell to fish |
| 39 | +RUN usermod -s /usr/local/bin/fish $USERNAME |
| 40 | + |
| 41 | +# lazygit |
| 42 | +ARG LAZYGIT_VERSION=0.60.0 |
| 43 | +RUN LAZYGIT_ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "arm64" || echo "x86_64") && \ |
| 44 | + curl -fsSL "https://github.com/jesseduffield/lazygit/releases/download/v${LAZYGIT_VERSION}/lazygit_${LAZYGIT_VERSION}_Linux_${LAZYGIT_ARCH}.tar.gz" \ |
| 45 | + | tar xz -C /usr/local/bin lazygit |
| 46 | + |
| 47 | +# git-delta |
| 48 | +ARG DELTA_VERSION=0.19.1 |
| 49 | +RUN DELTA_ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "x86_64") && \ |
| 50 | + curl -fsSL "https://github.com/dandavison/delta/releases/download/${DELTA_VERSION}/delta-${DELTA_VERSION}-${DELTA_ARCH}-unknown-linux-gnu.tar.gz" \ |
| 51 | + | tar xz --strip-components=1 -C /usr/local/bin "delta-${DELTA_VERSION}-${DELTA_ARCH}-unknown-linux-gnu/delta" |
| 52 | + |
| 53 | +# yazi + ya companion (terminal file manager) |
| 54 | +ARG YAZI_VERSION=26.1.22 |
| 55 | +RUN YAZI_ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "x86_64") && \ |
| 56 | + curl -fsSL "https://github.com/sxyazi/yazi/releases/download/v${YAZI_VERSION}/yazi-${YAZI_ARCH}-unknown-linux-musl.zip" -o /tmp/yazi.zip && \ |
| 57 | + unzip /tmp/yazi.zip -d /tmp/yazi && \ |
| 58 | + mv /tmp/yazi/yazi-${YAZI_ARCH}-unknown-linux-musl/yazi /usr/local/bin/ && \ |
| 59 | + mv /tmp/yazi/yazi-${YAZI_ARCH}-unknown-linux-musl/ya /usr/local/bin/ && \ |
| 60 | + rm -rf /tmp/yazi.zip /tmp/yazi |
| 61 | + |
| 62 | +# glow (markdown renderer) |
| 63 | +ARG GLOW_VERSION=2.1.1 |
| 64 | +RUN GLOW_ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "arm64" || echo "x86_64") && \ |
| 65 | + curl -fsSL "https://github.com/charmbracelet/glow/releases/download/v${GLOW_VERSION}/glow_${GLOW_VERSION}_Linux_${GLOW_ARCH}.tar.gz" \ |
| 66 | + | tar xz --strip-components=1 -C /usr/local/bin "glow_${GLOW_VERSION}_Linux_${GLOW_ARCH}/glow" |
| 67 | + |
| 68 | +# chafa >= 1.16 from source (yazi image preview; Debian ships 1.14) |
| 69 | +ARG CHAFA_VERSION=1.18.1 |
| 70 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 71 | + libglib2.0-dev libjpeg-dev libpng-dev libwebp-dev libfreetype6-dev && \ |
| 72 | + curl -fsSL -o /tmp/chafa.tar.xz \ |
| 73 | + "https://github.com/hpjansson/chafa/releases/download/${CHAFA_VERSION}/chafa-${CHAFA_VERSION}.tar.xz" && \ |
| 74 | + cd /tmp && tar xf chafa.tar.xz && cd chafa-${CHAFA_VERSION} && \ |
| 75 | + ./configure --prefix=/usr/local --disable-static --disable-man && \ |
| 76 | + make -j$(nproc) && make install && ldconfig && \ |
| 77 | + cd / && rm -rf /tmp/chafa* && \ |
| 78 | + apt-get purge -y --auto-remove libglib2.0-dev libjpeg-dev libpng-dev libwebp-dev libfreetype6-dev && \ |
| 79 | + apt-get clean && rm -rf /var/lib/apt/lists/* |
| 80 | + |
| 81 | +# Playwright + Chromium (browser automation / E2E tests) |
| 82 | +ENV PLAYWRIGHT_BROWSERS_PATH=/opt/playwright |
| 83 | +RUN npx playwright install --with-deps chromium && \ |
| 84 | + chmod -R a+rwx /opt/playwright && \ |
| 85 | + CHROME_BIN="$(find /opt/playwright -name chrome -type f | head -1)" && \ |
| 86 | + mkdir -p /opt/google/chrome && \ |
| 87 | + ln -s "$CHROME_BIN" /opt/google/chrome/chrome && \ |
| 88 | + apt-get clean && rm -rf /var/lib/apt/lists/* && \ |
| 89 | + npm cache clean --force && \ |
| 90 | + rm -rf /root/.cache/ms-playwright |
| 91 | + |
| 92 | +# pnpm via corepack (overrides base npm-installed pnpm) |
| 93 | +ARG PNPM_VERSION="10.33.0" |
| 94 | +RUN corepack enable && corepack prepare pnpm@${PNPM_VERSION} --activate |
| 95 | + |
| 96 | +# Starship prompt (pinned version) |
| 97 | +ARG STARSHIP_VERSION=1.22.1 |
| 98 | +RUN curl -fsSL "https://github.com/starship/starship/releases/download/v${STARSHIP_VERSION}/starship-$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "x86_64")-unknown-linux-musl.tar.gz" \ |
| 99 | + | tar xz -C /usr/local/bin starship |
| 100 | + |
| 101 | +# Ghostty terminal integration (pinned version) |
| 102 | +ARG GHOSTTY_SHELL_TAG=v1.1.3 |
| 103 | +COPY .devcontainer/ghostty/xterm-ghostty.terminfo /tmp/xterm-ghostty.terminfo |
| 104 | +RUN tic -x /tmp/xterm-ghostty.terminfo && rm /tmp/xterm-ghostty.terminfo |
| 105 | +RUN mkdir -p /usr/share/ghostty/shell-integration/fish/vendor_conf.d \ |
| 106 | + /usr/share/ghostty/shell-integration/bash && \ |
| 107 | + curl -fsSL "https://raw.githubusercontent.com/ghostty-org/ghostty/${GHOSTTY_SHELL_TAG}/src/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish" \ |
| 108 | + -o /usr/share/ghostty/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish && \ |
| 109 | + curl -fsSL "https://raw.githubusercontent.com/ghostty-org/ghostty/${GHOSTTY_SHELL_TAG}/src/shell-integration/bash/ghostty.bash" \ |
| 110 | + -o /usr/share/ghostty/shell-integration/bash/ghostty.bash |
| 111 | + |
| 112 | +# Fish system configs (/etc/fish/conf.d/ is the only path not shadowed by bind mounts) |
| 113 | +RUN mkdir -p /etc/fish/conf.d |
| 114 | +COPY .devcontainer/ghostty/ghostty-shell-integration.fish /etc/fish/conf.d/ghostty-shell-integration.fish |
| 115 | +RUN echo 'starship init fish | source' > /etc/fish/conf.d/starship.fish |
| 116 | +RUN echo 'fish_add_path -gP ~/.claude/bin' > /etc/fish/conf.d/claude-path.fish |
| 117 | +RUN echo 'status is-interactive; and rbenv init - fish | source' > /etc/fish/conf.d/rbenv.fish |
| 118 | + |
| 119 | +# Pre-create user-local directories so bind mounts don't leave root-owned parents |
| 120 | +RUN mkdir -p /home/$USERNAME/.local/share /home/$USERNAME/.local/state \ |
| 121 | + && chown -R $USERNAME:$USERNAME /home/$USERNAME/.local |
| 122 | + |
| 123 | +# Global npm tools |
| 124 | +RUN npm install -g @anthropic-ai/claude-code \ |
| 125 | + && npm cache clean --force |
| 126 | + |
| 127 | +# Switch to vscode user |
| 128 | +USER vscode |
| 129 | +ENV PATH="/home/vscode/.rbenv/bin:/home/vscode/.rbenv/shims:/home/vscode/.claude/bin:/home/vscode/.bun/bin:/home/vscode/.local/bin:$PATH" |
| 130 | + |
| 131 | +# bun (JS runtime/bundler, pinned version) |
| 132 | +ARG BUN_VERSION=1.2.17 |
| 133 | +RUN curl -fsSL https://bun.sh/install | bash -s "bun-v${BUN_VERSION}" |
| 134 | + |
| 135 | +# Git config for delta |
| 136 | +RUN git config --global core.pager delta && \ |
| 137 | + git config --global interactive.diffFilter "delta --color-only" && \ |
| 138 | + git config --global delta.navigate true && \ |
| 139 | + git config --global delta.side-by-side true && \ |
| 140 | + git config --global merge.conflictstyle zdiff3 |
0 commit comments