Skip to content

Commit 46f5331

Browse files
committed
docker agent stuff
1 parent 5d4c10a commit 46f5331

File tree

4 files changed

+456
-0
lines changed

4 files changed

+456
-0
lines changed

Dockerfile.agent

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
FROM ubuntu:24.04
2+
3+
ARG NODE_VERSION=22
4+
5+
ENV DEBIAN_FRONTEND=noninteractive
6+
7+
# Install build essentials and tools
8+
RUN apt-get update && \
9+
apt-get install -y \
10+
build-essential \
11+
curl \
12+
wget \
13+
git \
14+
unzip \
15+
jq \
16+
vim \
17+
nano \
18+
openssh-client \
19+
ca-certificates \
20+
gnupg \
21+
sudo && \
22+
rm -rf /var/lib/apt/lists/*
23+
24+
# Install Node.js via NodeSource
25+
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - && \
26+
apt-get install -y nodejs && \
27+
rm -rf /var/lib/apt/lists/*
28+
29+
# Install Bun
30+
RUN curl -fsSL https://bun.sh/install | bash && \
31+
export BUN_INSTALL="$HOME/.bun" && \
32+
export PATH="$BUN_INSTALL/bin:$PATH" && \
33+
echo "export BUN_INSTALL=\"\$HOME/.bun\"" >> ~/.bashrc && \
34+
echo "export PATH=\"\$BUN_INSTALL/bin:\$PATH\"" >> ~/.bashrc
35+
36+
# Install AI CLI tools (failures are non-fatal)
37+
RUN npm install -g @google/gemini-cli 2>/dev/null || true && \
38+
npm install -g @openai/codex 2>/dev/null || true
39+
40+
# Install OpenCode
41+
RUN curl -fsSL https://opencode.ai/install | bash || \
42+
(npm install -g opencode 2>/dev/null || true)
43+
44+
# Ensure CLI config directories exist
45+
RUN mkdir -p /root/.gemini && \
46+
mkdir -p /root/.codex && \
47+
mkdir -p /root/.config/opencode && \
48+
mkdir -p /root/.local/share/opencode
49+
50+
# Setup git worktree-friendly config
51+
RUN git config --global --add safe.directory "*" && \
52+
git config --global init.defaultBranch main
53+
54+
# Create worktrees directory
55+
RUN mkdir -p /worktrees
56+
57+
WORKDIR /workspace
58+
59+
CMD ["bash"]
60+

agent-container.sh

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Configuration
5+
CONTAINER_NAME="agent-dev"
6+
IMAGE="ubuntu:24.04"
7+
WORKSPACE_DIR="${1:-$(pwd)}"
8+
SSH_DIR="$HOME/.ssh"
9+
NODE_VERSION="22"
10+
11+
# CLI Agent credential directories
12+
GEMINI_DIR="$HOME/.gemini"
13+
CODEX_DIR="$HOME/.codex"
14+
OPENCODE_CONFIG_DIR="$HOME/.config/opencode"
15+
OPENCODE_DATA_DIR="$HOME/.local/share/opencode"
16+
17+
# Colors for output
18+
RED='\033[0;31m'
19+
GREEN='\033[0;32m'
20+
YELLOW='\033[1;33m'
21+
NC='\033[0m' # No Color
22+
23+
log() { echo -e "${GREEN}[+]${NC} $1"; }
24+
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
25+
error() { echo -e "${RED}[x]${NC} $1"; exit 1; }
26+
27+
# Check for required API keys
28+
check_api_keys() {
29+
local missing=()
30+
31+
if [[ -z "$GEMINI_API_KEY" ]]; then
32+
missing+=("GEMINI_API_KEY")
33+
fi
34+
35+
if [[ -z "$OPENAI_API_KEY" ]]; then
36+
missing+=("OPENAI_API_KEY")
37+
fi
38+
39+
if [[ -z "$ANTHROPIC_API_KEY" ]]; then
40+
missing+=("ANTHROPIC_API_KEY")
41+
fi
42+
43+
if [[ ${#missing[@]} -gt 0 ]]; then
44+
warn "Missing API keys: ${missing[*]}"
45+
warn "Some tools may not work without these keys"
46+
fi
47+
}
48+
49+
# Check prerequisites
50+
check_prereqs() {
51+
if ! command -v docker &> /dev/null; then
52+
error "Docker is not installed"
53+
fi
54+
55+
if [[ ! -d "$SSH_DIR" ]]; then
56+
error "SSH directory not found at $SSH_DIR"
57+
fi
58+
59+
if [[ ! -d "$WORKSPACE_DIR" ]]; then
60+
error "Workspace directory not found: $WORKSPACE_DIR"
61+
fi
62+
63+
check_api_keys
64+
}
65+
66+
# Build the setup script that runs inside the container
67+
SETUP_SCRIPT='
68+
#!/bin/bash
69+
set -e
70+
71+
export DEBIAN_FRONTEND=noninteractive
72+
73+
echo "[+] Updating package lists..."
74+
apt-get update
75+
76+
echo "[+] Installing build essentials and tools..."
77+
apt-get install -y \
78+
build-essential \
79+
curl \
80+
wget \
81+
git \
82+
unzip \
83+
jq \
84+
vim \
85+
nano \
86+
openssh-client \
87+
ca-certificates \
88+
gnupg \
89+
sudo
90+
91+
# Install Node.js via NodeSource
92+
echo "[+] Installing Node.js '"$NODE_VERSION"'..."
93+
curl -fsSL https://deb.nodesource.com/setup_'"$NODE_VERSION"'.x | bash -
94+
apt-get install -y nodejs
95+
96+
# Install Bun
97+
echo "[+] Installing Bun..."
98+
curl -fsSL https://bun.sh/install | bash
99+
export BUN_INSTALL="$HOME/.bun"
100+
export PATH="$BUN_INSTALL/bin:$PATH"
101+
echo "export BUN_INSTALL=\"\$HOME/.bun\"" >> ~/.bashrc
102+
echo "export PATH=\"\$BUN_INSTALL/bin:\$PATH\"" >> ~/.bashrc
103+
104+
# Install Gemini CLI
105+
echo "[+] Installing Gemini CLI..."
106+
npm install -g @google/gemini-cli 2>/dev/null || true
107+
108+
# Install OpenAI Codex CLI
109+
echo "[+] Installing OpenAI Codex CLI..."
110+
npm install -g @openai/codex 2>/dev/null || true
111+
112+
# Install OpenCode
113+
echo "[+] Installing OpenCode..."
114+
curl -fsSL https://opencode.ai/install | bash || {
115+
echo "[!] OpenCode install script failed, trying npm..."
116+
npm install -g opencode 2>/dev/null || true
117+
}
118+
119+
# Ensure CLI config directories exist
120+
mkdir -p /root/.gemini
121+
mkdir -p /root/.codex
122+
mkdir -p /root/.config/opencode
123+
mkdir -p /root/.local/share/opencode
124+
125+
# Setup git worktree-friendly config
126+
echo "[+] Configuring git..."
127+
git config --global --add safe.directory "*"
128+
git config --global init.defaultBranch main
129+
130+
# Create worktrees directory
131+
mkdir -p /workspace/.worktrees
132+
133+
echo ""
134+
echo "============================================"
135+
echo "[+] Setup complete!"
136+
echo "============================================"
137+
echo ""
138+
echo "Available tools:"
139+
echo " - node $(node --version)"
140+
echo " - npm $(npm --version)"
141+
echo " - bun (restart shell or source ~/.bashrc)"
142+
echo " - git $(git --version | cut -d\" \" -f3)"
143+
echo ""
144+
echo "AI CLI tools (authenticate locally first, credentials are mounted):"
145+
echo " - gemini (run: gemini)"
146+
echo " - codex (run: codex)"
147+
echo " - opencode (run: opencode)"
148+
echo ""
149+
echo "Credential directories:"
150+
echo " - Gemini: ~/.gemini/"
151+
echo " - Codex: ~/.codex/"
152+
echo " - OpenCode: ~/.config/opencode/ & ~/.local/share/opencode/"
153+
echo ""
154+
echo "Git worktrees:"
155+
echo " - Create: git worktree add /workspace/.worktrees/<name> <branch>"
156+
echo " - List: git worktree list"
157+
echo ""
158+
echo "Workspace mounted at: /workspace"
159+
echo ""
160+
161+
exec bash
162+
'
163+
164+
run_container() {
165+
log "Starting agent container..."
166+
167+
# Stop existing container if running
168+
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
169+
log "Removing existing container..."
170+
docker rm -f "$CONTAINER_NAME" > /dev/null 2>&1
171+
fi
172+
173+
# Build docker run command with mounts and env vars
174+
local docker_cmd=(
175+
docker run -it
176+
--name "$CONTAINER_NAME"
177+
--hostname agent
178+
-v "$WORKSPACE_DIR:/workspace"
179+
-v "$SSH_DIR:/root/.ssh:ro"
180+
-w /workspace
181+
)
182+
183+
# Mount CLI agent credential directories if they exist
184+
if [[ -d "$GEMINI_DIR" ]]; then
185+
docker_cmd+=(-v "$GEMINI_DIR:/root/.gemini")
186+
log "Mounting Gemini CLI config: $GEMINI_DIR -> /root/.gemini"
187+
fi
188+
189+
if [[ -d "$CODEX_DIR" ]]; then
190+
docker_cmd+=(-v "$CODEX_DIR:/root/.codex")
191+
log "Mounting Codex CLI config: $CODEX_DIR -> /root/.codex"
192+
fi
193+
194+
if [[ -d "$OPENCODE_CONFIG_DIR" ]]; then
195+
docker_cmd+=(-v "$OPENCODE_CONFIG_DIR:/root/.config/opencode")
196+
log "Mounting OpenCode config: $OPENCODE_CONFIG_DIR -> /root/.config/opencode"
197+
fi
198+
199+
if [[ -d "$OPENCODE_DATA_DIR" ]]; then
200+
docker_cmd+=(-v "$OPENCODE_DATA_DIR:/root/.local/share/opencode")
201+
log "Mounting OpenCode data: $OPENCODE_DATA_DIR -> /root/.local/share/opencode"
202+
fi
203+
204+
# Add API keys as environment variables if they exist
205+
[[ -n "$GEMINI_API_KEY" ]] && docker_cmd+=(-e "GEMINI_API_KEY=$GEMINI_API_KEY")
206+
[[ -n "$OPENAI_API_KEY" ]] && docker_cmd+=(-e "OPENAI_API_KEY=$OPENAI_API_KEY")
207+
[[ -n "$ANTHROPIC_API_KEY" ]] && docker_cmd+=(-e "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY")
208+
[[ -n "$GITHUB_TOKEN" ]] && docker_cmd+=(-e "GITHUB_TOKEN=$GITHUB_TOKEN")
209+
210+
# Add the image and command
211+
docker_cmd+=("$IMAGE" bash -c "$SETUP_SCRIPT")
212+
213+
log "Mounting workspace: $WORKSPACE_DIR -> /workspace"
214+
log "Mounting SSH keys: $SSH_DIR -> /root/.ssh (read-only)"
215+
216+
# Hint about missing credential dirs
217+
local missing_dirs=()
218+
[[ ! -d "$GEMINI_DIR" ]] && missing_dirs+=("~/.gemini (Gemini CLI)")
219+
[[ ! -d "$CODEX_DIR" ]] && missing_dirs+=("~/.codex (Codex CLI)")
220+
[[ ! -d "$OPENCODE_CONFIG_DIR" ]] && missing_dirs+=("~/.config/opencode (OpenCode)")
221+
222+
if [[ ${#missing_dirs[@]} -gt 0 ]]; then
223+
warn "Missing credential dirs (run the CLI tools locally first to create them):"
224+
for dir in "${missing_dirs[@]}"; do
225+
warn " - $dir"
226+
done
227+
fi
228+
229+
# Run the container
230+
"${docker_cmd[@]}"
231+
}
232+
233+
# Main
234+
check_prereqs
235+
run_container

build-agent-container.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Configuration
5+
IMAGE_NAME="agent-dev"
6+
DOCKERFILE="Dockerfile.agent"
7+
NODE_VERSION="${NODE_VERSION:-22}"
8+
9+
# Colors for output
10+
GREEN='\033[0;32m'
11+
YELLOW='\033[1;33m'
12+
NC='\033[0m' # No Color
13+
14+
log() { echo -e "${GREEN}[+]${NC} $1"; }
15+
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
16+
17+
# Check prerequisites
18+
if ! command -v docker &> /dev/null; then
19+
echo "Error: Docker is not installed" >&2
20+
exit 1
21+
fi
22+
23+
if [[ ! -f "$DOCKERFILE" ]]; then
24+
echo "Error: Dockerfile not found: $DOCKERFILE" >&2
25+
exit 1
26+
fi
27+
28+
log "Building agent container image: $IMAGE_NAME"
29+
log "Node.js version: $NODE_VERSION"
30+
31+
docker build \
32+
--build-arg NODE_VERSION="$NODE_VERSION" \
33+
-t "$IMAGE_NAME" \
34+
-f "$DOCKERFILE" \
35+
.
36+
37+
log "Build complete! Image: $IMAGE_NAME"
38+
log "Run with: ./run-agent-container.sh <container-name>"
39+

0 commit comments

Comments
 (0)