Skip to content

How to set up Docker containers for safely running AI agents

Problem

When I started using AI coding agents like Claude, I worried about giving them full access to my computer. What if the agent accidentally deleted important files? What if it accessed my .env files with API keys?

I saw this warning on Reddit:

“I think safe way is to use inside docker container”

But then another user pointed out:

“if you don’t understand security, that environment can still access your network”

So I needed to figure out the right way to set up Docker for AI agent isolation.

Environment

  • Docker Desktop 4.x
  • macOS Sonoma
  • Claude Code CLI

What happened?

Initially, I just ran Claude directly on my machine. It had access to everything:

/home/user/
├── .ssh/ # SSH keys
├── .env # API keys
├── projects/ # Work code
├── personal/ # Private documents
└── .aws/ # AWS credentials

This made me nervous. I wanted Claude to help with coding, but not touch my personal files or credentials.

I tried running Claude in a basic Docker container:

Terminal window
docker run -it -v ~/:/workspace python:3.11-slim bash

But this was worse! I mounted my entire home directory, giving Claude access to everything plus the container environment.

How to solve it?

Step 1: Create a minimal Dockerfile

I started by creating a Dockerfile specifically for AI agent work:

Dockerfile
FROM python:3.11-slim
WORKDIR /workspace
# Install useful tools
RUN apt-get update && apt-get install -y \
git \
curl \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user
RUN useradd -m -s /bin/bash agent
USER agent
# Set safe working directory
WORKDIR /workspace

The key changes from my first attempt:

  • Using python:3.11-slim instead of full images (smaller attack surface)
  • Creating a non-root user agent
  • Working directory is isolated

Step 2: Build the image

Terminal window
docker build -t claude-sandbox .

Step 3: Run with minimal volume mounts

Instead of mounting my home directory, I only mount the specific project:

Terminal window
docker run -it \
-v $(pwd)/my-project:/workspace \
--network none \
claude-sandbox \
bash

The important flags:

  • -v $(pwd)/my-project:/workspace - Only the project directory, not home
  • --network none - No network access at all

Step 4: Test the isolation

Inside the container, I verified:

Terminal window
agent@container:~$ ls /
bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var
agent@container:~$ ls /workspace
# Only my project files
agent@container:~$ curl google.com
curl: (6) Could not resolve host: google.com
# Network blocked - good!

When you need network access

Sometimes the AI agent needs to install packages. I use a two-step approach:

Step 1: Build with dependencies

Dockerfile.with-deps
FROM python:3.11-slim
WORKDIR /workspace
# Install dependencies during build (has network)
RUN pip install anthropic requests
# Then remove network capability
WORKDIR /workspace
RUN useradd -m -s /bin/bash agent
USER agent

Step 2: Run without network

Terminal window
docker build -t claude-ready -f Dockerfile.with-deps .
docker run -it -v $(pwd)/my-project:/workspace --network none claude-ready bash

Handling credentials properly

The biggest mistake is storing credentials inside the container. Instead, I use environment variables from the host:

Terminal window
docker run -it \
-v $(pwd)/my-project:/workspace \
-e ANTHROPIC_API_KEY \
--network none \
claude-sandbox \
bash

But wait - if there’s no network, how does Claude API work?

I had to reconsider. For AI agents that need API access:

Terminal window
# Allow only API traffic
docker run -it \
-v $(pwd)/my-project:/workspace \
-e ANTHROPIC_API_KEY \
claude-sandbox \
bash

I remove --network none but still:

  • No home directory mounted
  • No SSH keys accessible
  • No AWS credentials mounted
  • Only the specific project

The reason

The core security principles I learned:

  1. Least privilege access: Mount only what’s needed, nothing more
  2. Network isolation: Use --network none when possible, or firewall rules
  3. Credential separation: Pass credentials via environment variables, not files
  4. Non-root user: Run as unprivileged user inside container
  5. Minimal image: Use slim images to reduce attack surface

Docker containers are NOT virtual machines. They share the kernel with the host. But for file system isolation and limiting what an AI agent can access, they work well.

┌─────────────────────────────────────────┐
│ Host Machine │
│ ┌─────────────────────────────────┐ │
│ │ Docker Container │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ /workspace/ │ │ │
│ │ │ (only project files) │ │ │
│ │ └─────────────────────────┘ │ │
│ │ │ │
│ │ NO access to: │ │
│ │ - ~/.ssh/ │ │
│ │ - ~/.aws/ │ │
│ │ - ~/personal/ │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘

Common mistakes to avoid

I made these mistakes - don’t repeat them:

MistakeWhy it’s badCorrect approach
-v ~/:/workspaceExposes entire home directoryMount only specific project
Running as rootFull control if compromisedUse non-root user
--network hostFull network accessUse --network none or default bridge
Credentials in DockerfileBaked into image layersPass via -e at runtime
Storing .env in projectAgent can read itUse .dockerignore to exclude

Summary

In this post, I showed how to set up Docker containers for safely running AI agents. The key points are: mount only the specific project directory, use --network none when possible, run as non-root user, and pass credentials via environment variables instead of files.

Docker containers provide good filesystem isolation for AI agents without the overhead of full virtual machines. But remember - containers share the kernel, so they’re not a complete security solution. For sensitive work, consider additional measures like seccomp profiles or even proper VMs.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments