tencent cloud

Development Containers

Download
Focus Mode
Font Size
Last updated: 2026-09-30 18:15:50
AI-Translated

Overview

The CodeBuddy Code dev container provides a preconfigured, secure development environment for teams that require consistent and isolated workspaces. It integrates seamlessly with the Dev Containers extension for Visual Studio Code and similar tools.

Core Features

1. Production-ready Node.js environment: built on Node.js 20 with essential development dependencies
2. Security design: Customize the firewall to limit network access to essential services
3. Developer-friendly tools: includes git, ZSH, productivity-enhancing tools, fzf, and more
4. Seamless VS Code integration: Preconfigured extensions and optimized settings
5. Session Persistence: Command history and configurations are retained after container restarts.
6. Cross-platform support: Compatible with macOS, Windows, and Linux development environments

Four Steps to Get Started

1. Install VS Code and the Remote - Containers extension.
2. Create the .devcontainer directory and related files in your workspace by referring to the configuration details below.
3. Open the repository in VS Code.
4. When prompted, click "Reopen in Container" (or use the command palette: Cmd+Shift+P → "Remote-Containers: Reopen in Container")

Configuration Details

Directory Structure
your-project/
├── .devcontainer/
│ ├── devcontainer.json
│ ├── Dockerfile
│ └── init-firewall.sh
└── ...

Installing CodeBuddy Code (Recommended)

Option 1: Using the Dev Containers Feature (Recommended)

Dev Containers Feature is the recommended way to install CodeBuddy Code in a Dev Container. It offers advantages such as automatic version management, configuration consistency with other features, and simplified maintenance.
Strengths:
Automatic version management - Easily upgrade to the latest version or pin a specific version
Configuration consistency - Uses the same configuration approach as other Dev Containers features
Simplified maintenance - No need to manage complex installation logic in the Dockerfile
Team Sharing - Easy to configure uniformly across teams
Configuration method:
Add the configuration to the features field in devcontainer.json:
{
"name": "CodeBuddy Code Sandbox",
"features": {
"ghcr.io/devcontainers-contrib/features/codebuddy-code:1": {
"version": "latest"
}
},
// ... other configurations
}
Pin a specific version:
{
"features": {
"ghcr.io/devcontainers-contrib/features/codebuddy-code:1": {
"version": "2.16.0"
}
}
}
Use the default latest version:
{
"features": {
"ghcr.io/devcontainers-contrib/features/codebuddy-code:1": {}
}
}

Option 2: Installing Manually in a Dockerfile

If you need more control or have special scenarios, you can install it manually in the Dockerfile. For details, see the Dockerfile section below.

1. devcontainer.json

Control container settings, manage extensions, and configure volume mounts.
Complete example with Dev Containers Features:
{
"name": "CodeBuddy Code Sandbox",
"build": {
"dockerfile": "Dockerfile",
"args": {
"TZ": "${localEnv:TZ:America/Los_Angeles}",
"GIT_DELTA_VERSION": "0.18.2",
"ZSH_IN_DOCKER_VERSION": "1.2.0"
}
},
"features": {
"ghcr.io/devcontainers-contrib/features/codebuddy-code:1": {
"version": "latest"
}
},
"runArgs": [
"--cap-add=NET_ADMIN",
"--cap-add=NET_RAW"
],
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"eamodio.gitlens"
],
"settings": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.profiles.linux": {
"bash": {
"path": "bash",
"icon": "terminal-bash"
},
"zsh": {
"path": "zsh"
}
}
}
}
},
"remoteUser": "node",
"mounts": [
"source=codebuddy-code-bashhistory-${devcontainerId},target=/commandhistory,type=volume",
"source=codebuddy-code-config-${devcontainerId},target=/home/node/.codebuddy,type=volume"
],
"containerEnv": {
"NODE_OPTIONS": "--max-old-space-size=4096",
"CODEBUDDY_CONFIG_DIR": "/home/node/.codebuddy",
"POWERLEVEL9K_DISABLE_GITSTATUS": "true"
},
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
"workspaceFolder": "/workspace",
"postStartCommand": "sudo /usr/local/bin/init-firewall.sh",
"waitFor": "postStartCommand"
}
Key configuration notes:
features - Declares the use of the CodeBuddy Code Dev Containers Feature, with version management support.
version: "latest" - Use the latest version (replaceable with a specific version number such as "2.16.0")
Note: When the Feature method is used, the CODEBUDDY_CODE_VERSION parameter is not required in the Dockerfile.

2. Dockerfile

Define the container image and specify the tools to install.

Simplified Dockerfile When the Feature Is Used

If you install CodeBuddy Code using the Dev Containers Feature above, the Dockerfile can be simpler, with no need for the CODEBUDDY_CODE_VERSION parameter or manual installation commands:
Note:
If you choose to use the Dev Containers Feature method (recommended), refer to the "Simplified Dockerfile" below. If you need to install manually in the Dockerfile, refer to the "Full Dockerfile".
Simplified Dockerfile (recommended for use with Features):
FROM node:20

ARG TZ
ENV TZ="$TZ"

# Install basic development tools and iptables/ipset
RUN apt-get update && apt-get install -y --no-install-recommends \\
less \\
git \\
procps \\
sudo \\
fzf \\
zsh \\
man-db \\
unzip \\
gnupg2 \\
gh \\
iptables \\
ipset \\
iproute2 \\
dnsutils \\
aggregate \\
jq \\
nano \\
vim \\
&& apt-get clean && rm -rf /var/lib/apt/lists/*

# Ensure default node user has access to /usr/local/share
RUN mkdir -p /usr/local/share/npm-global && \\
chown -R node:node /usr/local/share

ARG USERNAME=node

# Persist bash history.
RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \\
&& mkdir /commandhistory \\
&& touch /commandhistory/.bash_history \\
&& chown -R $USERNAME /commandhistory

# Set `DEVCONTAINER` environment variable to help with orientation
ENV DEVCONTAINER=true

# Create workspace and config directories and set permissions
RUN mkdir -p /workspace /home/node/.codebuddy && \\
chown -R node:node /workspace /home/node/.codebuddy

WORKDIR /workspace

ARG GIT_DELTA_VERSION=0.18.2
RUN ARCH=$(dpkg --print-architecture) && \\
wget "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \\
sudo dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \\
rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb"

# Set up non-root user
USER node

# Install global packages
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
ENV PATH=$PATH:/usr/local/share/npm-global/bin

# Set the default shell to zsh rather than sh
ENV SHELL=/bin/zsh

# Set the default editor and visual
ENV EDITOR=nano
ENV VISUAL=nano

# Default powerline10k theme
ARG ZSH_IN_DOCKER_VERSION=1.2.0
RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh)" -- \\
-p git \\
-p fzf \\
-a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \\
-a "source /usr/share/doc/fzf/examples/completion.zsh" \\
-a "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \\
-x

# CodeBuddy Code will be installed via Dev Containers Feature

# Copy and set up firewall script
COPY init-firewall.sh /usr/local/bin/
USER root
RUN chmod +x /usr/local/bin/init-firewall.sh && \\
echo "node ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/node-firewall && \\
chmod 0440 /etc/sudoers.d/node-firewall
USER node

Complete Dockerfile for Manual Installation

If you need full control over the installation process, you can manually install CodeBuddy Code in the Dockerfile. This approach does not use Dev Containers Features:
FROM node:20

ARG TZ
ENV TZ="$TZ"

ARG CODEBUDDY_CODE_VERSION=latest

# Install basic development tools and iptables/ipset
RUN apt-get update && apt-get install -y --no-install-recommends \\
less \\
git \\
procps \\
sudo \\
fzf \\
zsh \\
man-db \\
unzip \\
gnupg2 \\
gh \\
iptables \\
ipset \\
iproute2 \\
dnsutils \\
aggregate \\
jq \\
nano \\
vim \\
&& apt-get clean && rm -rf /var/lib/apt/lists/*

# Ensure default node user has access to /usr/local/share
RUN mkdir -p /usr/local/share/npm-global && \\
chown -R node:node /usr/local/share

ARG USERNAME=node

# Persist bash history.
RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \\
&& mkdir /commandhistory \\
&& touch /commandhistory/.bash_history \\
&& chown -R $USERNAME /commandhistory

# Set `DEVCONTAINER` environment variable to help with orientation
ENV DEVCONTAINER=true

# Create workspace and config directories and set permissions
RUN mkdir -p /workspace /home/node/.codebuddy && \\
chown -R node:node /workspace /home/node/.codebuddy

WORKDIR /workspace

ARG GIT_DELTA_VERSION=0.18.2
RUN ARCH=$(dpkg --print-architecture) && \\
wget "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \\
sudo dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \\
rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb"

# Set up non-root user
USER node

# Install global packages
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
ENV PATH=$PATH:/usr/local/share/npm-global/bin

# Set the default shell to zsh rather than sh
ENV SHELL=/bin/zsh

# Set the default editor and visual
ENV EDITOR=nano
ENV VISUAL=nano

# Default powerline10k theme
ARG ZSH_IN_DOCKER_VERSION=1.2.0
RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh)" -- \\
-p git \\
-p fzf \\
-a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \\
-a "source /usr/share/doc/fzf/examples/completion.zsh" \\
-a "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \\
-x

# Install CodeBuddy Code (manual installation method - only if not using Dev Containers Feature)
RUN npm install -g @tencent-ai/codebuddy-code@${CODEBUDDY_CODE_VERSION}

# Copy and set up firewall script
COPY init-firewall.sh /usr/local/bin/
USER root
RUN chmod +x /usr/local/bin/init-firewall.sh && \\
echo "node ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/node-firewall && \\
chmod 0440 /etc/sudoers.d/node-firewall
USER node
Note:
If you use this method, the build.args in devcontainer.json must include the "CODEBUDDY_CODE_VERSION" parameter, and the features field must not include the CodeBuddy Code Feature.

3. init-firewall.sh

Establish network security rules.
#!/bin/bash
set -euo pipefail # Exit on error, undefined vars, and pipeline failures
IFS=$'\\n\\t' # Stricter word splitting

# 1. Extract Docker DNS info BEFORE any flushing
DOCKER_DNS_RULES=$(iptables-save -t nat | grep "127\\.0\\.0\\.11" || true)

# Flush existing rules and delete existing ipsets
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
ipset destroy allowed-domains 2>/dev/null || true

# 2. Selectively restore ONLY internal Docker DNS resolution
if [ -n "$DOCKER_DNS_RULES" ]; then
echo "Restoring Docker DNS rules..."
iptables -t nat -N DOCKER_OUTPUT 2>/dev/null || true
iptables -t nat -N DOCKER_POSTROUTING 2>/dev/null || true
echo "$DOCKER_DNS_RULES" | xargs -L 1 iptables -t nat
else
echo "No Docker DNS rules to restore"
fi

# First allow DNS and localhost before any restrictions
# Allow outbound DNS
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
# Allow inbound DNS responses
iptables -A INPUT -p udp --sport 53 -j ACCEPT
# Allow outbound SSH
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
# Allow inbound SSH responses
iptables -A INPUT -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
# Allow localhost
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Create ipset with CIDR support
ipset create allowed-domains hash:net

# Fetch GitHub meta information and aggregate + add their IP ranges
echo "Fetching GitHub IP ranges..."
gh_ranges=$(curl -s https://api.github.com/meta)
if [ -z "$gh_ranges" ]; then
echo "ERROR: Failed to fetch GitHub IP ranges"
exit 1
fi

if ! echo "$gh_ranges" | jq -e '.web and .api and .git' >/dev/null; then
echo "ERROR: GitHub API response missing required fields"
exit 1
fi

echo "Processing GitHub IPs..."
while read -r cidr; do
if [[ ! "$cidr" =~ ^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}/[0-9]{1,2}$ ]]; then
echo "ERROR: Invalid CIDR range from GitHub meta: $cidr"
exit 1
fi
echo "Adding GitHub range $cidr"
ipset add allowed-domains "$cidr"
done < <(echo "$gh_ranges" | jq -r '(.web + .api + .git)[]' | aggregate -q)

# Resolve and add other allowed domains
for domain in \\
"registry.npmjs.org" \\
"copilot.tencent.com" \\
"sentry.io" \\
"marketplace.visualstudio.com" \\
"vscode.blob.core.windows.net" \\
"update.code.visualstudio.com"; do
echo "Resolving $domain..."
ips=$(dig +noall +answer A "$domain" | awk '$4 == "A" {print $5}')
if [ -z "$ips" ]; then
echo "ERROR: Failed to resolve $domain"
exit 1
fi
while read -r ip; do
if [[ ! "$ip" =~ ^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$ ]]; then
echo "ERROR: Invalid IP from DNS for $domain: $ip"
exit 1
fi
echo "Adding $ip for $domain"
ipset add allowed-domains "$ip"
done < <(echo "$ips")
done

# Get host IP from default route
HOST_IP=$(ip route | grep default | cut -d" " -f3)
if [ -z "$HOST_IP" ]; then
echo "ERROR: Failed to detect host IP"
exit 1
fi

HOST_NETWORK=$(echo "$HOST_IP" | sed "s/\\.[0-9]*$/.0\\/24/")
echo "Host network detected as: $HOST_NETWORK"

# Set up remaining iptables rules
iptables -A INPUT -s "$HOST_NETWORK" -j ACCEPT
iptables -A OUTPUT -d "$HOST_NETWORK" -j ACCEPT

# Set default policies to DROP first
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

# First allow established connections for already approved traffic
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Then allow only specific outbound traffic to allowed domains
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT

# Explicitly REJECT all other outbound traffic for immediate feedback
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited

echo "Firewall configuration complete"
echo "Verifying firewall rules..."
if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then
echo "ERROR: Firewall verification failed - was able to reach https://example.com"
exit 1
else
echo "Firewall verification passed - unable to reach https://example.com as expected"
fi

# Verify GitHub API access
if ! curl --connect-timeout 5 https://api.github.com/zen >/dev/null 2>&1; then
echo "ERROR: Firewall verification failed - unable to reach https://api.github.com"
exit 1
else
echo "Firewall verification passed - able to reach https://api.github.com as expected"
fi

Security feature

Containers implement multi-layered security protection:
Precise access control: Restrict outbound connections to allowlisted domains (npm registry, GitHub, CodeBuddy API, and so on).
Allowed outbound connections: The firewall allows outbound DNS and SSH connections.
Default deny policy: Block all other external network access.
Startup verification: Verify firewall rules during container initialization.
Isolation: Create a secure development environment isolated from the host system.

Important Security Notice

While dev containers provide substantial protection, no system is completely immune to all attacks. When CodeBuddy Code is executed with -y (or --dangerously-skip-permissions), dev containers cannot prevent a malicious project from stealing anything accessible within the container, including CodeBuddy Code credentials. We recommend using dev containers only when working with trusted repositories. Always maintain good security practices and monitor CodeBuddy activity.

Unattended Operations

The enhanced container security measures (isolation and firewall rules) allow you to run codebuddy -y (or codebuddy --dangerously-skip-permissions) to bypass permission prompts and enable unattended operation.

Customization Options

The dev container configuration is designed to be flexible and can be adjusted as needed:
Add or remove VS Code extensions based on your workflow.
Adjust resource allocation for different hardware environments.
Adjust network access permissions.
Customize shell configuration and development tools.

Scenarios

1. Secure Customer Project Development

Use dev containers to isolate projects for different customers, ensuring that code and credentials are never mixed.

2. Rapid Team Onboarding

New team members can get a fully configured development environment within minutes, with all necessary tools and settings preinstalled.

3. Consistent CI/CD Environments

Mirror your dev container configuration in CI/CD pipelines to ensure that development and production environments match.

Relevant Resources



Help and Support

Was this page helpful?

Help us improve! Rate your documentation experience in 5 mins.

Feedback