10 min read

Sandbox your GitHub Copilot CLI on Linux

Containerized AI agent isolation with Docker

Banner

TL;DR
  • This article shows how to set up rootless Docker on Linux for running GitHub Copilot CLI in isolation
  • Build a custom Ubuntu container image with GitHub Copilot CLI pre-installed
  • Mount your project directory into the container so you and Copilot share the same workspace
  • Configure persistent authentication so you don't need to log in every time
  • Launch ephemeral containers for different projects with a simple script
  • Copilot gets full access to your project directory but can't touch the rest of your system

GitHub Copilot CLI is a powerful AI coding assistant, but unlike Claude Code or Codex, it has no built-in sandboxing. If you want to be safe, you have to constantly approve every file read/write outside the project directory, and every new command execution. You might want to enable --yolo mode and let the agent work uninterrupted, but that’s risky as Copilot could easily go rogue.

The solution: run Copilot CLI in an isolated sandbox. Docker is perfect for this. Full filesystem access inside, zero risk to your host machine.

If you’re on macOS or Windows with Docker Desktop, you’re in luck. Just use the experimental docker --sandbox command and you’re done. However, if you’re on Linux, docker --sandbox isn’t available.

This guide shows you how to set up a similar isolation using rootless Docker. You’ll get a sandboxed environment for Copilot CLI without needing Docker Desktop.

Disclaimer: Unlike docker --sandbox, this approach doesn’t restrict network traffic. Your agent can communicate freely with the internet, which creates the risk of data exfiltration.

Sneak-peak of what you’ll going to build

With this setup, you’ll be able to launch Copilot CLI in a sandboxed container with a single command.

For example, let’s say you have a project at ~/projects/my-project. You can just run:

Terminal window
./copilot-sandbox.sh ~/projects/my-project

This will do the following:

  • Start GitHub Copilot CLI in a sandboxed environment
  • Give Copilot access to your project folder but nothing else on your system
  • Destroy the sandbox when you exit again, but remember the authentication so you don’t have to log in next time
  • Allow you to run multiple sandboxed agents for different projects in parallel

Let’s go!

1. Install rootless Docker on Linux

Rootless Docker means the Docker daemon runs as your regular user (not root), and containers are isolated using user namespaces. The containers think they’re running as root inside, but they’re actually mapped to your unprivileged user ID on the host. This is much safer than regular Docker.

1.1 Install prerequisites

Terminal window
sudo apt-get update
sudo apt-get install -y uidmap dbus-user-session

What’s happening here:

  • uidmap provides the newuidmap and newgidmap tools that allow your user to map a range of user IDs
  • dbus-user-session ensures systemd user services work correctly
  • These tools let Linux create “fake” root environments inside containers while keeping everything unprivileged on the host

1.2 Configure subordinate UIDs/GIDs

Check if you already have subordinate UID/GID ranges:

Terminal window
cat /etc/subuid
cat /etc/subgid
  • If you see lines like, you’re already set up. Go to the next step (1.3).

    yourusername:100000:65536
  • Otherwise, if these files are empty or your user isn’t listed, add ranges:

    Terminal window
    sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER

What this means:

  • Your user gets a range of 65,536 “fake” UIDs (100000-165535)
  • When a container thinks it’s running as UID 0 (root), it’s actually mapped to UID 100000 on your host
  • This means even if a container is compromised, the attacker only has access to these mapped, unprivileged UIDs

1.3 Install Docker CE (if not already installed)

Terminal window
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

1.4 Install rootless Docker extras

Terminal window
sudo apt-get install -y docker-ce-rootless-extras

What’s in this package:

  • dockerd-rootless-setuptool.sh - the setup script
  • rootlesskit - creates the user namespace and handles networking
  • slirp4netns - provides user-mode networking (no root needed)

1.5 Disable the root Docker daemon

Terminal window
sudo systemctl disable --now docker.service docker.socket

Why:

  • You don’t want the root daemon running alongside rootless
  • This prevents confusion and conflicts

1.6 Initialize rootless Docker

Terminal window
dockerd-rootless-setuptool.sh install

What this does:

  1. Checks prerequisites (subuid/subgid)
  2. Creates systemd user service files in ~/.config/systemd/user/docker.service
  3. Starts the Docker daemon as your user
  4. Sets up the Docker socket at /run/user/$(id -u)/docker.sock

1.7 Configure your shell

Add to ~/.bashrc:

Terminal window
export PATH=/home/$USER/bin:$PATH
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock

Then reload:

Terminal window
source ~/.bashrc

Why:

  • The Docker CLI needs to know to talk to your user’s socket, not the system socket
  • The binaries are installed in your home directory, not system paths

1.8 Enable the service to start on boot

Terminal window
systemctl --user enable docker
sudo loginctl enable-linger $USER

What enable-linger does:

  • Normally, user services stop when you log out
  • enable-linger keeps your user’s systemd instance running even when you’re not logged in
  • This means your Docker daemon persists across logins

1.9 Verify installation

Terminal window
docker run hello-world

Check the output in the terminal. You should see a message confirming Docker is working.


2. Building your Copilot sandbox image

Now let’s create myorg/copilot-sandbox:latest with Copilot CLI pre-installed.

2.1 Create a Dockerfile

Terminal window
mkdir ~/copilot-sandbox
cd ~/copilot-sandbox
nano Dockerfile

Put this in the Dockerfile:

FROM ubuntu:22.04
# Prevent interactive prompts during installation
ENV DEBIAN_FRONTEND=noninteractive
# Install basic tools and Node.js repository
RUN apt-get update && apt-get install -y \
curl \
git \
nano \
ripgrep \
ca-certificates \
gnupg \
&& mkdir -p /etc/apt/keyrings \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
# Install Node.js 22
RUN apt-get update && apt-get install -y nodejs
# Install GitHub Copilot CLI
RUN npm install -g @github/copilot
# OPTIONAL: Install any other dependencies your devleopment setup
# might require (Python, Java, etc.)
# Clean up to reduce image size
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /workspace
# Default command: bash
CMD ["/bin/bash"]

Important: make sure you also add all other packages your developer setup might require to this file.

2.2 Build the image

Terminal window
docker build -t myorg/copilot-sandbox:latest .

This will take a few minutes. The -t flag tags it with the name you want.


3. Running a session with the sandboxed Copilot CLI

You’ll use ephemeral containers (destroyed on exit with --rm) but persist authentication data in named Docker volumes. This means:

  • Each container is fresh and clean
  • You can work on different projects easily
  • You only have to authenticate once (auth data persists in volumes)
  • No container clutter building up

3.1 Create a persistent volume for authentication

First, let’s create the volume that will store authentication data:

Terminal window
docker volume create copilot-sandbox-root

What this does:

  • Creates a named volume called copilot-sandbox-root
  • This volume persists on your system even when containers are destroyed
  • You’ll mount this to /root inside the container where Copilot CLI usually stores its auth tokens

3.2 Create the launch script

Terminal window
nano ~/copilot-sandbox.sh

Put this in the file:

#!/bin/bash
# Get project directory from first argument, default to current directory
PROJECT_DIR="${1:-.}"
# Resolve to absolute path
PROJECT_PATH="$(realpath "$PROJECT_DIR")"
# Check if project directory exists
if [ ! -d "$PROJECT_PATH" ]; then
echo "Error: Directory $PROJECT_PATH does not exist"
exit 1
fi
echo "=========================================="
echo "Launching Copilot sandbox container"
echo "Project: $PROJECT_PATH"
echo "=========================================="
echo ""
echo "Inside the container, run 'copilot' to open the CLI."
echo ""
# Run the container
docker run --rm -it \
--cap-drop ALL \
--security-opt no-new-privileges \
-v "$PROJECT_PATH":/workspace:rw \
-v copilot-sandbox-root:/root \
myorg/copilot-sandbox:latest \
bash

Flag explanations:

  • --rm: Automatically removes the container when you exit (keeps system clean)
  • -it: Combined flags:
    • -i (interactive): Keeps STDIN open so you can type commands
    • -t (pseudo-TTY): Allocates a terminal for proper interactive experience
  • --cap-drop ALL: Drops all Linux capabilities (prevents privileged operations)
  • --security-opt no-new-privileges: Prevents privilege escalation via setuid/setgid
  • -v "$PROJECT_PATH":/workspace:rw: Mounts your project directory to /workspace with read-write access
  • -v copilot-sandbox-root:/root: Mounts the persistent volume to /root (where auth data is stored)
  • myorg/copilot-sandbox:latest: The image you built earlier
  • bash: Starts an interactive bash shell

3.3 Make the script executable

Terminal window
chmod +x ~/copilot-sandbox.sh

4. First-time authentication

4.1 Launch your first session

Terminal window
~/copilot-sandbox.sh ~/projects/my-project

You’re now inside a container with a bash prompt. Your project files are available at /workspace.

4.2 Authenticate with GitHub Copilot CLI

Inside the same container, run:

Terminal window
copilot

What happens:

  1. Copilot CLI starts for the first time
  2. It prompts you to authenticate with /login
  3. Type /login and press Enter
  4. Follow the browser authentication flow
  5. Sign in with your GitHub account that has Copilot access
  6. Token is saved to the copilot-sandbox-root volume

4.3 Exit the Container

Terminal window
exit

The container is destroyed, but your authentication data remains in the copilot-sandbox-root volume and persists across container sessions.


Usage examples

Example 1: Run from your project directory

Terminal window
cd ~/projects/my-project
~/copilot-sandbox.sh

If you’re already in the project folder, you can just run the script without arguments. It will use the current directory if no argument is provided.

Example 2: Run multiple projects in parallel

Terminal 1:

Terminal window
~/copilot-sandbox.sh ~/projects/project-a

Terminal 2:

Terminal window
~/copilot-sandbox.sh ~/projects/project-b

Terminal 3:

Terminal window
~/copilot-sandbox.sh ~/projects/project-c

Each container is isolated, fresh, and destroyed on exit. Your authentication persists across sessions.


Wrapping Up

You now have a fully isolated environment for running GitHub Copilot CLI on Linux. Fresh containers for each project, persistent authentication, and strong security boundaries. Copilot can modify files in /workspace freely but can’t touch the rest of your host system.

Remember: the container has full network access. The agent can send data to external servers. Don’t run untrusted code or work with sensitive credentials inside the container unless you’re comfortable with that risk.

If you found this useful, follow me on X, BlueSky, or LinkedIn for more technical deep dives like this.