Basic OpenCode Sandboxing with Docker
I’ve been playing with OpenCode as a way to test different models, play with self-hosted models and to avoid reliance on big tech provided systems. With these kinds of tools, I’m not keen on giving it free access to all my files. Therefore, I came up with a simple little docker based setup so that OpenCode’s access is limited somewhat.
Note: I am not a security expert and this kind of setup does not assure any kind of absolute sandboxing or security.
Here’s the Dockerfile:
FROM node:24-trixie
RUN npm install -g opencode-ai
RUN mkdir -p /home/node/.local/share/opencode \
/home/node/.local/state/opencode \
/home/node/.cache/opencode \
&& chown -R node:node /home/node
ENTRYPOINT ["opencode"]
This installs OpenCode within a Debian Trixie-based image with Node.js installed.
Build that from the same directory using docker build -t local:opencode .
and then create the following bash script as opencode, located somewhere in your $PATH:
#!/usr/bin/env bash
set -euo pipefail
CWD="$(pwd)"
# Check if CWD is under /home/ and at least 3 levels deep (e.g. /home/user/project/subdir)
is_valid_path() {
local path="$1"
# Must start with /home/
[[ "$path" == /home/* ]] || return 1
# Strip /home/ prefix and count remaining components
local relative="${path#/home/}"
# Count slashes to determine depth (need at least 2 more levels after /home/)
local depth
depth=$(echo "$relative" | tr -cd '/' | wc -c)
[[ "$depth" -ge 2 ]] || return 1
}
if is_valid_path "$CWD"; then
CONTAINER_WORKDIR="/app${CWD}"
else
# Construct a fallback path at least 3 levels deep under /home/
USER_NAME="${USER:-node}"
PROJECT_NAME="$(basename "$CWD")"
TIMESTAMP="$(date '+%Y_%m_%d-%H%M%S')"
FALLBACK="/home/${USER_NAME}/Projects/scratch/opencode-${TIMESTAMP}"
CONTAINER_WORKDIR="/app${FALLBACK}"
CWD="${FALLBACK}"
echo ""
echo -e "\033[31mNot in a safe project directory.\033[0m"
echo "Starting OpenCode in a fallback temp directory: ${FALLBACK}"
mkdir -p "${FALLBACK}"
echo -n "Loading"
for i in $(seq 1 50); do
echo -n "."
sleep 0.06
done
echo ""
fi
exec docker run --rm -it \
--user "$(id -u):$(id -g)" \
-v "$HOME/.config/opencode:/home/node/.config/opencode" \
-v "$HOME/.cache/opencode:/home/node/.cache/opencode" \
-v "$HOME/.local/share/opencode:/home/node/.local/share/opencode" \
-v "$HOME/.local/state/opencode:/home/node/.local/state/opencode" \
-v "${CWD}:${CONTAINER_WORKDIR}" \
-w "${CONTAINER_WORKDIR}" \
-p "127.0.0.1:4040:4040" \
--security-opt=no-new-privileges \
--cap-drop all \
local:opencode "--port" "4040" "--hostname" "0.0.0.0" "$@"
This script runs the container, running OpenCode as the same user/group ID as the host user.
All the OpenCode config/cache/state directories are passed through to retain sessions/login/state between sessions.
Then the current working directory is mapped into the container at /app$(pwd). I include the /app prefix to contain working data to a specific place inside the container.
~/Projects/scratch/opencode-DATETIME folder instead.
Some docker options have been added/tweaked to improve sandboxing.
Port 4040 is passed through between host and container, which is set for OpenCode on the next line, along with a 0.0.0.0 hostname. These are to allow the web UI to be accessed via http://localhost:4040 on the host.
Lastly, it runs the container using the local:opencode tag we built it with, setting those web server UI options and then it passes any extra options which the user provided when running the bash script.
Make the script executable with chmod +x opencode.
Then, with the script in your $PATH somewhere, you should be able to run opencode to start the docker-based OpenCode in your current working directory. In the bottom left corner you should see the path starting with /app/
To re-iterate, this does not assure security in any way, and there may be better options elsewhere such as in this thread but for me I wanted a setup which was simple, using the tools I’m familiar with, which should cover my greatest concern (unrestricted access to my files). Your concerns & considerations may differ.
There may also be limitations/complications/side-effects with this kind of setup, I’m still in the early stages of testing it.
I did try to initially use “Docker Sandboxes”, but I abandoned this route when it required me to accept non-open terms when following their usage guide. From what I can see at a glance, this is a proprietary service/offering.