Skip to content

Commit cf514c9

Browse files
committed
first commit
1 parent a4e7523 commit cf514c9

4 files changed

Lines changed: 389 additions & 2 deletions

File tree

.devcontainer/Dockerfile

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Dev Container compatible avec Claude Code
2+
# Base: Debian 13 (Trixie)
3+
FROM debian:trixie-slim
4+
5+
LABEL org.opencontainers.image.source="https://github.com/Pikatsuto/DevContainer-Claude-Code-Compatible"
6+
LABEL org.opencontainers.image.description="Dev Container with Claude Code pre-installed on Debian 13"
7+
LABEL org.opencontainers.image.licenses="MIT"
8+
9+
# Arguments pour la configuration
10+
ARG USERNAME=vscode
11+
ARG USER_UID=1000
12+
ARG USER_GID=$USER_UID
13+
ARG NODE_VERSION=24
14+
15+
ENV DEBIAN_FRONTEND=noninteractive
16+
17+
# Installation: Claude Code + outils d'analyse et debug
18+
RUN apt-get update && apt-get install -y --no-install-recommends \
19+
# Requis pour Claude Code
20+
ca-certificates \
21+
curl \
22+
git \
23+
sudo \
24+
# Outils d'analyse et debug
25+
ripgrep \
26+
fd-find \
27+
jq \
28+
less \
29+
procps \
30+
lsof \
31+
file \
32+
tree \
33+
&& rm -rf /var/lib/apt/lists/*
34+
35+
# Installation de Node.js
36+
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - && \
37+
apt-get install -y nodejs && \
38+
rm -rf /var/lib/apt/lists/*
39+
40+
# Création de l'utilisateur non-root
41+
RUN groupadd --gid $USER_GID $USERNAME \
42+
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
43+
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
44+
&& chmod 0440 /etc/sudoers.d/$USERNAME
45+
46+
# Configuration npm global pour l'utilisateur
47+
ENV NPM_CONFIG_PREFIX=/home/$USERNAME/.npm-global
48+
ENV PATH=$NPM_CONFIG_PREFIX/bin:$PATH
49+
50+
# Installation de Claude Code
51+
RUN npm install -g @anthropic-ai/claude-code && \
52+
npm cache clean --force
53+
54+
# Préparer les répertoires Claude Code
55+
RUN mkdir -p /home/$USERNAME/.claude && \
56+
chown -R $USERNAME:$USERNAME /home/$USERNAME/.claude && \
57+
chown -R $USERNAME:$USERNAME /home/$USERNAME/.npm-global
58+
59+
USER $USERNAME
60+
WORKDIR /workspaces
61+
62+
CMD ["bash"]

.devcontainer/devcontainer.json

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"name": "Claude Code Dev Container",
3+
"image": "ghcr.io/Pikatsuto/devcontainer-claude-code:latest",
4+
5+
// Montage du contexte Claude Code de l'hôte pour réutiliser l'authentification
6+
"mounts": [
7+
"source=${localEnv:HOME}/.claude,target=/home/vscode/.claude,type=bind,consistency=cached"
8+
],
9+
10+
// Configuration de l'utilisateur
11+
"remoteUser": "vscode",
12+
"containerUser": "vscode",
13+
14+
// Variables d'environnement
15+
"remoteEnv": {
16+
"CLAUDE_CONFIG_DIR": "/home/vscode/.claude"
17+
},
18+
19+
// Extensions VSCode recommandées
20+
"customizations": {
21+
"vscode": {
22+
"extensions": [
23+
"anthropics.claude-code"
24+
],
25+
"settings": {
26+
"terminal.integrated.defaultProfile.linux": "bash"
27+
}
28+
}
29+
},
30+
31+
// Commande post-création pour vérifier l'installation
32+
"postCreateCommand": "claude --version || true",
33+
34+
// Options du container
35+
"features": {},
36+
37+
// Capacités additionnelles si nécessaire
38+
"capAdd": [],
39+
40+
// Monter le workspace
41+
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/${localWorkspaceFolderBasename},type=bind,consistency=cached",
42+
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}"
43+
}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
name: Build and Push Dev Container
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- '.devcontainer/**'
9+
- '.github/workflows/build-container.yml'
10+
schedule:
11+
# Toutes les 24h à 2h du matin UTC
12+
- cron: '0 2 * * *'
13+
workflow_dispatch:
14+
15+
env:
16+
REGISTRY: ghcr.io
17+
IMAGE_NAME: ${{ github.repository_owner }}/devcontainer-claude-code
18+
19+
jobs:
20+
check-updates:
21+
runs-on: ubuntu-latest
22+
outputs:
23+
should_build: ${{ steps.check.outputs.should_build }}
24+
claude_version: ${{ steps.versions.outputs.claude_version }}
25+
steps:
26+
- name: Checkout
27+
uses: actions/checkout@v4
28+
29+
- name: Get current versions
30+
id: versions
31+
run: |
32+
# Récupérer la dernière version de Claude Code
33+
CLAUDE_VERSION=$(npm view @anthropic-ai/claude-code version 2>/dev/null || echo "unknown")
34+
echo "claude_version=$CLAUDE_VERSION" >> $GITHUB_OUTPUT
35+
echo "Claude Code version: $CLAUDE_VERSION"
36+
37+
- name: Check if rebuild is needed
38+
id: check
39+
run: |
40+
# Pour les push, toujours rebuild
41+
if [[ "${{ github.event_name }}" == "push" ]]; then
42+
echo "should_build=true" >> $GITHUB_OUTPUT
43+
echo "Push event - will rebuild"
44+
exit 0
45+
fi
46+
47+
# Pour les workflow_dispatch, toujours rebuild
48+
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
49+
echo "should_build=true" >> $GITHUB_OUTPUT
50+
echo "Manual trigger - will rebuild"
51+
exit 0
52+
fi
53+
54+
# Pour le cron, vérifier si l'image existe et comparer les versions
55+
echo "Checking existing image..."
56+
57+
# Tenter de récupérer les labels de l'image existante
58+
TOKEN=$(echo ${{ secrets.GITHUB_TOKEN }} | base64)
59+
60+
MANIFEST=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
61+
"https://ghcr.io/v2/${{ env.IMAGE_NAME }}/manifests/latest" 2>/dev/null || echo "")
62+
63+
if [[ -z "$MANIFEST" || "$MANIFEST" == *"error"* ]]; then
64+
echo "No existing image found - will build"
65+
echo "should_build=true" >> $GITHUB_OUTPUT
66+
exit 0
67+
fi
68+
69+
# Récupérer la version de Claude Code dans l'image existante via le cache
70+
CACHE_FILE=".claude-version-cache"
71+
CURRENT_CLAUDE_VERSION="${{ steps.versions.outputs.claude_version }}"
72+
73+
# Utiliser le cache GitHub pour stocker la dernière version buildée
74+
if [[ -f "$CACHE_FILE" ]]; then
75+
CACHED_VERSION=$(cat "$CACHE_FILE")
76+
if [[ "$CACHED_VERSION" != "$CURRENT_CLAUDE_VERSION" ]]; then
77+
echo "Claude Code version changed: $CACHED_VERSION -> $CURRENT_CLAUDE_VERSION"
78+
echo "should_build=true" >> $GITHUB_OUTPUT
79+
exit 0
80+
fi
81+
fi
82+
83+
# Vérifier le hash du Dockerfile
84+
DOCKERFILE_HASH=$(sha256sum .devcontainer/Dockerfile | cut -d' ' -f1)
85+
CACHE_DOCKERFILE=".dockerfile-hash-cache"
86+
87+
if [[ -f "$CACHE_DOCKERFILE" ]]; then
88+
CACHED_HASH=$(cat "$CACHE_DOCKERFILE")
89+
if [[ "$CACHED_HASH" != "$DOCKERFILE_HASH" ]]; then
90+
echo "Dockerfile changed"
91+
echo "should_build=true" >> $GITHUB_OUTPUT
92+
exit 0
93+
fi
94+
else
95+
echo "No cache found - will build"
96+
echo "should_build=true" >> $GITHUB_OUTPUT
97+
exit 0
98+
fi
99+
100+
echo "No changes detected - skipping build"
101+
echo "should_build=false" >> $GITHUB_OUTPUT
102+
103+
- name: Cache version info
104+
if: steps.check.outputs.should_build == 'true'
105+
uses: actions/cache@v4
106+
with:
107+
path: |
108+
.claude-version-cache
109+
.dockerfile-hash-cache
110+
key: build-cache-${{ github.run_id }}
111+
restore-keys: |
112+
build-cache-
113+
114+
build-and-push:
115+
needs: check-updates
116+
if: needs.check-updates.outputs.should_build == 'true'
117+
runs-on: ubuntu-latest
118+
permissions:
119+
contents: read
120+
packages: write
121+
122+
steps:
123+
- name: Checkout
124+
uses: actions/checkout@v4
125+
126+
- name: Set up QEMU
127+
uses: docker/setup-qemu-action@v3
128+
129+
- name: Set up Docker Buildx
130+
uses: docker/setup-buildx-action@v3
131+
132+
- name: Log in to Container Registry
133+
uses: docker/login-action@v3
134+
with:
135+
registry: ${{ env.REGISTRY }}
136+
username: ${{ github.actor }}
137+
password: ${{ secrets.GITHUB_TOKEN }}
138+
139+
- name: Extract metadata
140+
id: meta
141+
uses: docker/metadata-action@v5
142+
with:
143+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
144+
tags: |
145+
type=raw,value=latest
146+
type=raw,value={{date 'YYYYMMDD'}}
147+
type=sha,prefix=
148+
149+
- name: Build and push
150+
uses: docker/build-push-action@v5
151+
with:
152+
context: .devcontainer
153+
file: .devcontainer/Dockerfile
154+
push: true
155+
tags: ${{ steps.meta.outputs.tags }}
156+
labels: |
157+
${{ steps.meta.outputs.labels }}
158+
org.opencontainers.image.claude-code-version=${{ needs.check-updates.outputs.claude_version }}
159+
platforms: linux/amd64,linux/arm64
160+
cache-from: type=gha
161+
cache-to: type=gha,mode=max
162+
163+
- name: Update version cache
164+
run: |
165+
echo "${{ needs.check-updates.outputs.claude_version }}" > .claude-version-cache
166+
sha256sum .devcontainer/Dockerfile | cut -d' ' -f1 > .dockerfile-hash-cache
167+
168+
- name: Save cache
169+
uses: actions/cache@v4
170+
with:
171+
path: |
172+
.claude-version-cache
173+
.dockerfile-hash-cache
174+
key: build-cache-${{ github.run_id }}

README.md

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,110 @@
1-
# DevContainer-Claude-Code-Compatible
2-
DevContainer Claude Code Compatible
1+
# DevContainer Claude Code Compatible
2+
3+
Dev Container template with Claude Code pre-installed on Debian 13 (Trixie).
4+
5+
## Features
6+
7+
- **Debian 13 (Trixie) base**: Lightweight and up-to-date image
8+
- **Claude Code pre-installed**: Ready to use out of the box
9+
- **Shared authentication**: Reuses your host's Claude Code credentials
10+
- **Analysis tools included**: ripgrep, fd, jq, tree, etc.
11+
- **Multi-architecture**: Supports amd64 and arm64
12+
- **Auto-update**: Daily rebuild if changes detected
13+
14+
## Usage
15+
16+
### Option 1: Use the image directly
17+
18+
Copy the `.devcontainer/devcontainer.json` file to your project and update the `image` field with your GitHub username:
19+
20+
```json
21+
{
22+
"image": "ghcr.io/Pikatsuto/devcontainer-claude-code:latest"
23+
}
24+
```
25+
26+
### Option 2: Extend the image
27+
28+
Create your own Dockerfile based on this image:
29+
30+
```dockerfile
31+
FROM ghcr.io/pikatsuto/devcontainer-claude-code:latest
32+
33+
# Add your additional packages
34+
RUN sudo apt-get update && sudo apt-get install -y \
35+
python3 \
36+
python3-pip \
37+
&& sudo rm -rf /var/lib/apt/lists/*
38+
```
39+
40+
## Requirements
41+
42+
### Claude Code Authentication
43+
44+
Authentication is shared from your host machine via the `~/.claude` mount.
45+
46+
**Before using the container**, authenticate on your host machine:
47+
48+
```bash
49+
claude login
50+
```
51+
52+
The container will automatically reuse this authentication.
53+
54+
### GitHub Package Permissions
55+
56+
To use the image, make sure the package is public or you are authenticated:
57+
58+
```bash
59+
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
60+
```
61+
62+
## Create Your Own Template
63+
64+
1. Use this repository as a template (click "Use this template" button)
65+
2. Replace `Pikatsuto` with your username in these files:
66+
- `.devcontainer/Dockerfile`: `org.opencontainers.image.source` label
67+
- `.devcontainer/devcontainer.json`: `image` field
68+
3. Enable GitHub Actions
69+
4. Make the package public in Settings > Packages
70+
71+
## Structure
72+
73+
```
74+
.
75+
├── .devcontainer/
76+
│ ├── Dockerfile # Docker image: Debian 13 + Claude Code
77+
│ └── devcontainer.json # VS Code Dev Container configuration
78+
├── .github/
79+
│ └── workflows/
80+
│ └── build-container.yml # Automatic build every 24h
81+
└── README.md
82+
```
83+
84+
## Automatic Updates
85+
86+
The GitHub Action checks every 24 hours for:
87+
88+
- New Claude Code version on npm
89+
- Changes in the Dockerfile
90+
91+
Rebuild only occurs if changes are detected.
92+
93+
## Image Contents
94+
95+
96+
| Package | Description |
97+
| ----------- | ----------------------- |
98+
| Node.js 24 | JavaScript runtime |
99+
| Claude Code | Anthropic CLI |
100+
| git | Version control |
101+
| ripgrep | Fast search |
102+
| fd-find | File finder |
103+
| jq | JSON parser |
104+
| tree | Directory visualization |
105+
| procps | Process tools (ps, top) |
106+
| lsof | File/network debugging |
107+
108+
## License
109+
110+
MIT

0 commit comments

Comments
 (0)