In my previous post, I described how to create a separate OS user to run Claude Code. This creates some nice separation between the AI agent account and your main user account so you’re not leaving your front door open for the AI agent, and you can keep it under control.
Recently, I found an even better approach: using Docker for this purpose. This gives you even stronger isolation.
I’ve started using OpenCode which, if you like Claude Code, can easily be configured to work
with Claude Code as a passthrough.
Dockerfile
Let’s start by creating a Docker image. This allows you to control what utilities are installed in the OS, which user is used, and other basics.
FROM ghcr.io/anomalyco/opencode:latest
USER root
# Install additional tools
RUN apk add --no-cache \
curl \
git \
bash \
openjdk25 \
maven \
xdg-utils \
xclip \
wl-clipboard
ca-certificates \
unzip
# Create 'piotr' user with UID=1000 to match the host user
RUN addgroup -g 1000 piotr && \
adduser -D -u 1000 -G piotr -h /home/piotr -s /bin/bash piotr
USER piotr
# Set git config for OpenCode to recognize user
RUN git config --global user.name "Piotr Nowicki" && \
git config --global user.email "[email protected]"
ENV JAVA_HOME=/usr/lib/jvm/java-25-openjdk
ENV PATH="${JAVA_HOME}/bin:${PATH}"
WORKDIR /workspace
You can easily extend the utils list to add whatever you need.
I also use my host OS user inside the container to avoid permission issues with the files the AI will work on. I’ll be
working on the same files using my IDE on the host, so I want full transparency here.
Save it as Dockerfile and run: docker build . -t opencode-custom
Docker compose
Now let’s move to the Docker Compose file that will use the image we just built:
services:
opencode:
build: .
image: opencode-custom:latest
container_name: opencode-custom
# Needed to be able to type input as in regular TTY
stdin_open: true
tty: true
volumes:
# Projects to work on
- /home/piotr/IdeaProjects/my-nice-project:/workspace/my-nice-project:rw
# OpenCode
- ./data/home:/home/opencode:rw
- ./config:/config:rw
working_dir: /workspace
environment:
- HOME=/home/opencode
- OPENCODE_API_KEY=${OPENCODE_API_KEY:-} # To be used with OpenCode Zen
- OPENCODE_CONFIG=/config/custom-config.json
networks:
- opencode-net
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
read_only: false
restart: unless-stopped
networks:
opencode-net:
driver: bridge
Save it as docker-compose.yml next to Dockerfile.
Then run: docker compose up -d
Connect to it using: docker exec -it opencode-custom opencode
The Docker Compose setup grants the minimum required permissions to the container and only mounts the projects you actually want it to have access to.
This setup gives me confidence and freedom to let the agent do many things automatically without worrying it will suddenly go into Skynet mode on me ;-)