This commit is contained in:
2025-09-29 14:14:30 +00:00
parent 953a8d8825
commit 9701a6ed89
28 changed files with 2058 additions and 377 deletions

View File

@@ -1,6 +1,21 @@
# Start from the universal devcontainer base image
FROM mcr.microsoft.com/devcontainers/universal:2-linux
ARG LAZYGIT_VERSION=0.55.1
ARG LAZYGIT_SHA256=6385a699dde302b7fdcd1cc8910ae225ed0c19a230285569c586051576f0d6a3
ARG LAZYDOCKER_VERSION=0.24.1
ARG LAZYDOCKER_SHA256=461cacf618e1020dff1d7896248c1c1f2267d5c25fb529755e4b9c43c5d1d4a5
ARG SUPERFILE_VERSION=1.3.3
ARG SUPERFILE_SHA256=b74dffa446bdbeaef38cae0815e1714f78d5bffc0b39aafd1bd9f26ef191210a
ARG BTOP_VERSION=1.4.5
ARG BTOP_SHA256=206b0f9334e93c06de9025eaf90676c374ca79815b41dadff1b36ef4e4e6d1d4
ARG CODE_SERVER_VERSION=4.104.2
ARG CODE_SERVER_SHA256=bc650b57fd8d0bcee952c97308dd43ae37ad8dc11b83a713d8eca8ce823fefd9
ARG UV_VERSION=0.8.22
ARG UV_PYTHON_VERSION=3.12.5
ARG GO_VERSION=1.25.1
ARG GO_SHA256=7716a0d940a0f6ae8e1f3b3f4f36299dc53e31b16840dbd171254312c41ca12e
# Switch to root for installations
USER root
@@ -25,14 +40,15 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive && \
curl \
wget \
unzip \
xz-utils \
# Development tools
jq \
httpie \
software-properties-common \
# Build tools
build-essential \
cmake \
pkg-config \
make \
# Database clients
postgresql-client \
redis-tools \
@@ -43,11 +59,90 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive && \
git \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Install the Go toolchain from upstream tarball to guarantee a fresh version
RUN set -eux; \
curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -o /tmp/go.tar.gz; \
echo "${GO_SHA256} /tmp/go.tar.gz" | sha256sum -c -; \
rm -rf /usr/local/go; \
tar -C /usr/local -xzf /tmp/go.tar.gz; \
rm -f /tmp/go.tar.gz
# Install Python 3.12 system-wide and set as default
RUN set -eux; \
add-apt-repository ppa:deadsnakes/ppa -y; \
apt-get update; \
apt-get install -y python3.12 python3.12-venv python3.12-dev; \
python3.12 -m ensurepip --upgrade; \
python3.12 -m pip install --upgrade pip; \
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 2; \
update-alternatives --set python3 /usr/bin/python3.12; \
update-alternatives --install /usr/bin/python python /usr/bin/python3.12 2; \
update-alternatives --set python /usr/bin/python3.12; \
if command -v pip3.12 >/dev/null 2>&1; then \
ln -sf "$(command -v pip3.12)" /usr/local/bin/pip3; \
ln -sf "$(command -v pip3.12)" /usr/local/bin/pip; \
fi; \
apt-get clean && rm -rf /var/lib/apt/lists/*
# Install pinned CLI utilities that workspaces depend on
RUN set -eux; \
tmpdir=$(mktemp -d); \
cd "$tmpdir"; \
curl -fsSL "https://github.com/yorukot/superfile/releases/download/v${SUPERFILE_VERSION}/superfile-linux-v${SUPERFILE_VERSION}-amd64.tar.gz" -o superfile.tar.gz; \
echo "${SUPERFILE_SHA256} superfile.tar.gz" | sha256sum -c -; \
tar -xzf superfile.tar.gz; \
install -Dm755 "dist/superfile-linux-v${SUPERFILE_VERSION}-amd64/spf" /usr/local/bin/spf; \
curl -fsSL "https://github.com/jesseduffield/lazygit/releases/download/v${LAZYGIT_VERSION}/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz" -o lazygit.tar.gz; \
echo "${LAZYGIT_SHA256} lazygit.tar.gz" | sha256sum -c -; \
tar -xzf lazygit.tar.gz lazygit; \
install -Dm755 lazygit /usr/local/bin/lazygit; \
curl -fsSL "https://github.com/jesseduffield/lazydocker/releases/download/v${LAZYDOCKER_VERSION}/lazydocker_${LAZYDOCKER_VERSION}_Linux_x86_64.tar.gz" -o lazydocker.tar.gz; \
echo "${LAZYDOCKER_SHA256} lazydocker.tar.gz" | sha256sum -c -; \
tar -xzf lazydocker.tar.gz lazydocker; \
install -Dm755 lazydocker /usr/local/bin/lazydocker; \
curl -fsSL "https://github.com/aristocratos/btop/releases/download/v${BTOP_VERSION}/btop-x86_64-linux-musl.tbz" -o btop.tbz; \
echo "${BTOP_SHA256} btop.tbz" | sha256sum -c -; \
tar -xjf btop.tbz; \
install -Dm755 btop/bin/btop /usr/local/bin/btop; \
cd /; \
rm -rf "$tmpdir"
# Install code-server into a fixed prefix so the module can run in offline mode
RUN set -eux; \
curl -fsSL "https://github.com/coder/code-server/releases/download/v${CODE_SERVER_VERSION}/code-server-${CODE_SERVER_VERSION}-linux-amd64.tar.gz" -o /tmp/code-server.tar.gz; \
echo "${CODE_SERVER_SHA256} /tmp/code-server.tar.gz" | sha256sum -c -; \
rm -rf /opt/code-server; \
mkdir -p /opt; \
tar -xzf /tmp/code-server.tar.gz -C /opt; \
mv /opt/code-server-${CODE_SERVER_VERSION}-linux-amd64 /opt/code-server; \
ln -sf /opt/code-server/bin/code-server /usr/local/bin/code-server; \
rm -f /tmp/code-server.tar.gz; \
chown -R coder:coder /opt/code-server
# Install the uv Python toolchain manager system-wide
RUN set -eux; \
curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin UV_VERSION=${UV_VERSION} sh
# Preinstall JavaScript tooling for all users
RUN set -eux; \
npm install -g --silent \
pnpm@latest \
yarn@latest \
turbo@latest \
@anthropic-ai/claude-code@latest \
vercel@latest \
netlify-cli@latest \
tsx@latest \
nodemon@latest \
tldr@latest \
fkill-cli@latest \
repomix@latest
# Switch to coder user for user-specific installations
USER coder
# Install uv early for Python package management
RUN pip install --user uv
# Ensure user-local bin directories and system installs are on PATH
ENV PATH="/home/coder/.venv/bin:/usr/local/go/bin:/usr/local/bin:/home/coder/.local/bin:/home/coder/bin:${PATH}"
# Install Rust-based tools using cargo (check if available first)
RUN if [ -f ~/.cargo/env ]; then \
@@ -58,34 +153,78 @@ RUN if [ -f ~/.cargo/env ]; then \
echo "Rust/cargo not available, skipping Rust tools"; \
fi
# Install Node.js and Python packages in single layer
RUN echo "Installing Node.js packages..." && \
npm install -g --silent \
pnpm@latest \
yarn@latest \
turbo@latest \
@anthropic-ai/claude-code@latest \
vercel@latest \
netlify-cli@latest \
tsx@latest \
nodemon@latest \
tldr@latest \
fkill-cli@latest \
repomix@latest && \
echo "Installing Python packages..." && \
export PATH="/home/coder/.local/bin:$PATH" && \
~/.local/bin/uv tool install poetry && \
~/.local/bin/uv tool install black && \
~/.local/bin/uv tool install ruff && \
~/.local/bin/uv tool install mypy && \
~/.local/bin/uv tool install pytest && \
# Install Python tooling for coder user
RUN echo "Installing Python packages..." && \
uv tool install poetry && \
uv tool install black && \
uv tool install ruff && \
uv tool install mypy && \
uv tool install pytest && \
pip install --user --quiet pipenv httpx rich && \
echo "All packages installed successfully"
echo "Python packages installed successfully"
# Create necessary directories and copy scripts
# Preinstall Python 3.12 virtual environment and Marimo environment expected by the template
RUN set -eux; \
uv python install ${UV_PYTHON_VERSION}; \
uv venv --python ${UV_PYTHON_VERSION} /home/coder/.venv; \
/home/coder/.venv/bin/python -m ensurepip --upgrade; \
/home/coder/.venv/bin/python -m pip install --upgrade pip; \
/home/coder/.venv/bin/python -m pip install --upgrade marimo; \
mkdir -p /home/coder/workspaces/notebooks; \
cat <<MARIMO_APP > /home/coder/workspaces/notebooks/welcome.py
import marimo
__generated_with = "0.16.0"
app = marimo.App()
@app.cell
def __():
import marimo as mo
return mo,
@app.cell
def __(mo):
mo.md("# Welcome to Marimo!")
return
@app.cell
def __(mo):
mo.md("This is your interactive notebook environment.")
return
if __name__ == "__main__":
app.run()
MARIMO_APP
# Seed code-server configuration matching the Terraform defaults
RUN set -eux; \
mkdir -p /home/coder/.config/code-server; \
cat <<CONFIG > /home/coder/.config/code-server/config.yaml
bind-addr: 127.0.0.1:13337
auth: none
cert: false
CONFIG
# Create necessary directories and stage workspace helper scripts (if present)
USER root
COPY tf/scripts/*.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/*.sh
COPY . /tmp/devcontainer-src
RUN if [ -d /tmp/devcontainer-src/terraform/scripts ]; then \
cp -r /tmp/devcontainer-src/terraform/scripts/*.sh /usr/local/bin/; \
if [ -d /tmp/devcontainer-src/terraform/scripts/agentapi ]; then \
rm -rf /usr/local/bin/agentapi; \
cp -r /tmp/devcontainer-src/terraform/scripts/agentapi /usr/local/bin/agentapi; \
fi; \
elif [ -d /tmp/devcontainer-src/scripts ]; then \
cp -r /tmp/devcontainer-src/scripts/*.sh /usr/local/bin/; \
if [ -d /tmp/devcontainer-src/scripts/agentapi ]; then \
rm -rf /usr/local/bin/agentapi; \
cp -r /tmp/devcontainer-src/scripts/agentapi /usr/local/bin/agentapi; \
fi; \
else \
echo "No workspace helper scripts found; skipping copy"; \
fi && \
find /usr/local/bin -maxdepth 1 -type f -name *.sh -exec chmod +x {} \; && \
rm -rf /tmp/devcontainer-src
# Switch to coder user
USER coder
@@ -101,9 +240,17 @@ RUN echo 'export PATH="$HOME/.local/bin:$HOME/bin:$PATH"' >> ~/.zshrc && \
echo 'command -v starship >/dev/null 2>&1 && eval "$(starship init zsh)"' >> ~/.zshrc && \
echo 'command -v zoxide >/dev/null 2>&1 && eval "$(zoxide init zsh)"' >> ~/.zshrc
# Set up IDE configurations using our scripts
RUN /usr/local/bin/cursor-setup.sh && \
/usr/local/bin/windsurf-setup.sh
# Set up IDE configurations if the helper scripts are present
RUN if [ -f /usr/local/bin/cursor-setup.sh ]; then \
/usr/local/bin/cursor-setup.sh; \
else \
echo "cursor-setup.sh not found; skipping"; \
fi && \
if [ -f /usr/local/bin/windsurf-setup.sh ]; then \
/usr/local/bin/windsurf-setup.sh; \
else \
echo "windsurf-setup.sh not found; skipping"; \
fi
# Create devinfo utility
RUN cat <<'EOF' > "$HOME/bin/devinfo" \
@@ -169,4 +316,4 @@ ENV META_DIR=/tmp/git-metadata
EXPOSE 3000 5000 8000 8080 8888 5050 6333
# Default command
CMD ["/bin/zsh"]
CMD ["/bin/zsh"]