OpenCode in Docker: problems met on real tasks and what to do instead

Introduction

This article is part of a larger manual, OpenCode in Docker on Ubuntu 24.04.

The manual shows how to run OpenCode with the --auto option inside a Docker container.

With --auto the agent does not ask you before each command, so the container limits what it can reach: the agent works only in one git worktree, a separate copy of the project.

The first real tasks with this setup were a new Perl course and a plan for the errors in yesterday's access log.

Below is what went wrong, why, and what to do instead.

Tools used here: git, Docker, awk.

A new run does not know the last one

Every run starts a new session. Asked to repeat its report in English, the agent of a second run answered that the conversation had just started.

opencode run takes --continue for the last session and --session for a given one, and the launcher passes both on:

container/tools/ai/opencode-docker.sh ../site-agent run --session <id> "Repeat your report in English."

Name the session, not --continue, when two agents run.

All their containers keep sessions in the same volume, so --continue takes the newest session of either.

Started with the worktree of the other task, a resumed agent looked for the files it had written and for its notes in /tmp, found neither, and waited:

ls: cannot access '/work/container/src/dev/perl': No such file or directory ls: cannot access '/tmp/agentwork': No such file or directory

The files were in the other worktree, and /tmp had gone with the container of the earlier run.

The ids are in the shell of step 6 (check what the container sees), newest first, with the time in UTC, the clock of the container:

opencode session list

ses_e8351f6a7ffehA4yRD0x6NlBtH Untitled session 10/27/2026, 10:09:11 AM ses_e83357c41ffeT3ReWox83y3CJF Untitled session 10/27/2026, 10:07:43 AM

A run started with --title doc-test is listed by its title, which tells the tasks apart:

ses_e8296785dffeIxdSRidoUwdNLJ doc-test 10/27/2026, 12:50:34 PM

The agent sees only the worktree

The log task named a file in an ignored folder of the main checkout.

The container does not have it, so the agent found nothing.

A run that finds nothing can still write a plan, from old notes in the repo.

Do not mount the log instead: it holds the IP addresses and browsers of visitors, and a free model may keep what it is sent.

Cut out on the host what the task needs, into a folder that is mounted and not ignored:

awk '$9 == 404 || $9 >= 500 {print $9, $4, $7}' access.log > ../site-agent/container/docs/errors.txt

cat ../site-agent/container/docs/errors.txt

404 [26/Oct/2026:10:15:11 /old/page.php 500 [26/Oct/2026:10:16:40 /ru/x/

"All checks pass" covers what the agent checked

The report of the course listed php -l, page renders, tag balance and the sitemap: checks of the HTML.

None ran the Perl, although Perl is in the image, and one lesson said that my $last = (1..5); gives 5.

Run such an example in the image yourself, without network and with nothing else mounted:

vi demo.pl

my $last = (1..5); print "[$last]\n";

docker run --rm --network none --cap-drop ALL -v "$PWD/demo.pl:/tmp/demo.pl:ro" --entrypoint perl opencode-agent -w /tmp/demo.pl

Use of uninitialized value $. in range (or flip) at /tmp/demo.pl line 1. []

In scalar context .. is the flip-flop operator, not a range, and the value is empty.

A second run fixed the lesson and added real output to 51 pages of the course.

Of 126 examples with output, 116 printed exactly what the page shows.

The other 10 depend on files the lesson creates first, a module that is not in the image, the machine, or the order of normal and error output.

The same run broke a page after its own php -l: a shell command with single quotes inside the single-quoted PHP string of the page.

The commit hook in the worktree caught it, once the hooks worked there.

Commit hooks in a worktree

A worktree uses the hooks of the repo, but git runs them differently there: it hands the hook GIT_DIR, the path of the worktree's git folder, and no GIT_WORK_TREE.

Then git -C <folder> takes that folder for the top of the work tree.

A hook script that finds its files that way stops with an error, or finds no files and passes. In a throwaway repo:

mkdir -p ~/hooktest/main

cd ~/hooktest/main

git init -q

mkdir -p a/b

touch a/b/f

git add .

git commit -qm init

vi .git/hooks/pre-commit

#!/bin/sh echo "GIT_DIR=$GIT_DIR" git -C a/b rev-parse --show-toplevel exit 1

chmod +x .git/hooks/pre-commit

git commit --allow-empty -m test

GIT_DIR= /home/me/hooktest/main

exit 1 stops each test commit, so nothing is committed. The same commit in a worktree:

git worktree add -q ../wt -b side

cd ../wt

git commit --allow-empty -m test

GIT_DIR=/home/me/hooktest/main/.git/worktrees/wt /home/me/hooktest/wt/a/b

With unset GIT_DIR GIT_WORK_TREE in place of the echo line, git finds the worktree from the folder again, and the same commit prints the right top:

/home/me/hooktest/wt

main moved on while the agent worked

When the course was ready, its worktree was ten commits behind main, feed updates among them.

Commit on an old base, and those files conflict at the merge.

Bring the worktree up to date first; staged files stay staged, checked in a throwaway worktree:

git -C ../site-agent merge --ff-only main

A hook that runs after the commit and stages files, such as a feed of new pages, leaves them for a second commit.

Make it in the worktree too, so git merge --ff-only brings both.

Another agent in your folder while you commit

pre-commit puts your unstaged changes aside while the hooks run and brings them back afterwards.

A commit in the main checkout failed with files were modified by this hook on a hook that changes nothing.

Another agent, working in the same folder, had edited a file during that minute.

An edit made in that window can also be lost when pre-commit brings your changes back.

List the agents and their folders before you commit (user name replaced):

for p in $(pgrep -x 'claude|opencode'); do echo "$p $(readlink /proc/$p/cwd)"; done

13509 /home/me/github/site 24610 /home/me/github/site 40276 /home/me

The list includes the agent you may be asking to run it.

Commit when no other agent works in that folder, or give each of them a worktree too, as Claude Code in two agents: one branch each.

The free model has a usage limit

After a day of runs, a new one stopped at the first request:

Error: Free usage limit reached. Connect a provider or subscribe to OpenCode Go to keep going, or switch models.

Wait, or continue the same task on an OpenCode Go model or a model through OpenRouter.

Read the section When the free model reaches its usage limit of the day to day article to learn how.

Article author: Klavdiya Kondakova

Banner image