devcontainer.json
.devcontainer/devcontainer.json
{
"name": "Node.js & TypeScript",
"dockerComposeFile": "docker-compose.yml",
"service": "devcontainer",
"workspaceFolder": "/workspaces/<project name>",
"features": {
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers-extra/features/pre-commit:2": {},
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": true,
"installOhMyZsh": true,
"configureZshAsDefaultShell": true
},
"ghcr.io/nakamasato/devcontainers-features/tig:1": {},
"ghcr.io/devcontainers-extra/features/actionlint:1": {}
},
"containerEnv": {
"CLAUDE_CONFIG_DIR": "/home/node/.claude"
},
"initializeCommand": "echo \"GH_TOKEN=$(gh auth token)\" > .devcontainer/.env.devcontainer",
"postCreateCommand": "bash .devcontainer/setup-git-hooks.sh",
"postStartCommand": "pre-commit install",
"containerUser": "node"
}
ポイント
- docker-composeを使う。理由はいろんなプロジェクトで大体あとから別のコンポーネントに依存してdocker composeになるので、最初からdocker composeにしておく
- claude-code, gh, pre-commit, tig, actionlintなどはfeaturesで入れておく
- tigはfeaturesになかったので自分でfeaturesを作成した https://github.com/nakamasato/devcontainers-features
- CLAUDE CODE用の設定
CLAUDE_CONFIG_DIRとマウント設定 (Dockerfile)をする - initializeCommandで、gh auth tokenを GH_TOKENにセットすることで毎回認証する手間を防ぐ
- postStartCommandでpre-commit installしておく
- postCreateCommandで ~/.zshrc に git --no-verifyを防ぐための設定を追加
- containerUserで"node" などの non-root ユーザを設定しておく
.devcontainer/setup-git-hooks.sh
Claude Codeが git commit --no-verifyを使ってかいくぐってしまうので、以下のスクリプトを追加
.devcontainer/setup-git-hooks.sh
#!/bin/bash
# Add git function to prevent --no-verify usage
cat >> ~/.zshrc << 'EOF'
git() {
if [[ "$1" == "commit" ]]; then
for arg in "$@"; do
if [[ "$arg" == "--no-verify" || "$arg" == "-n" ]]; then
echo "❌ ERROR: --no-verify bypasses quality checks and is forbidden"
echo "Pre-commit hooks ensure code quality. Please fix issues instead of bypassing them."
return 1
fi
done
fi
command git "$@"
}
EOF
AIエージェントによる git commit --no-verify を完全に防ぐ方法で紹介されていたのをDevcontainerでも使えるように設定しています。
docker-compose.yml
.devcontainer/docker-compose.yml
services:
devcontainer:
build: .
volumes:
- ../..:/workspaces:cached
- commandhistory:/commandhistory
- claude-code-config:/home/node/.claude
- home_cache:/home/node/.cache/
env_file:
- .env.devcontainer
command: sleep infinity
ports:
- 3000:3000
# その他依存するコンテナを追加する
volumes:
commandhistory:
claude-code-config:
home_cache:
- Dockerfileを使って柔軟に設定できるようにしておく
- home以下のcache, commandhistory, claude code configなどをvolumeに永続化しておく
Dockerfile
.devcontainer/Dockerfile
FROM mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm
ARG USERNAME=node
# Used to persist shell history
RUN mkdir /commandhistory \
&& touch /commandhistory/.bash_history \
&& touch /commandhistory/.zsh_history \
&& chown -R $USERNAME /commandhistory \
&& echo 'export PROMPT_COMMAND="history -a" && export HISTFILE=/commandhistory/.bash_history' >> "/home/$USERNAME/.bashrc" \
&& echo 'export HISTFILE=/commandhistory/.zsh_history' >> "/home/$USERNAME/.zshrc"
# Create claude config directories and set permissions
RUN mkdir -p /home/$USERNAME/.claude && \
chown -R $USERNAME /home/$USERNAME/.claude
RUN mkdir -p /home/$USERNAME/.cache && \
chown -R $USERNAME /home/$USERNAME/.cache
- baseイメージに
mcr.microsoft.com/devcontainers/typescript-node:1-22-bookwormを使う - コマンドの永続化するfolderと権限を付与する