OpenCode'u konteyner ortamında çalıştırma
Bu yazıda Podman kullanarak, OpenCode’u ana sistemden izole (konteynerize) bir şekilde nasıl kullanabileceğimizi anlatmaya çalışacağım. Bu izole ortama, komut satırından kolayca erişmek için yazdığım Bash betiğinden de bahsedeceğim.
Büyük dil modelleri tabanlı sohbet botları, günümüzde farklı farklı kılıklarda internetin birçok yerinde karşımıza çıkabiliyor.
Sohbet botlarının oldukça faydalı olabileceği yerlerden biri ise; yazılım mühendislerinin, sistem yöneticilerinin ve bu yola gönül vermiş birçok insanın başında uzun saatler geçirdiği: Terminaller (terminal emülatorleri diye okuyun siz)
Her ne kadar masaüstü çalışma ortamında, sadece terminal arayüzü tabanlı programları kullanma fikri bana pek kullanışlı gelmese de, sohbet botlarına komut satırından erişim birçok kolaylığı beraberinde getirebilir:
- Unutulan veya argümanlarını ezberlemesi garip komutlar
- Programlama ve betik dillerinin sözdizimleri
- Terminalin sağladığı kullanım hızı ve çabukluk (Tarayıcıya kıyasla)
- Halihazırda terminaldeyken akla gelen sorular
- ve daha birçok şey….
Dockerfile ve imaj oluşumu
Dockerfile:
FROM docker.io/node:22-bookworm
# /root içindeki kalıcı npm-global dizini
RUN mkdir --parents /root/.npm-global \
&& npm config set prefix /root/.npm-global \
&& npm install --global opencode-ai --loglevel verbose
ENTRYPOINT ["/root/.npm-global/bin/opencode"]
NodeJS 22 Debian Bookworm imajının üstüne /root/.npm-global dizinine, opencode-ai NPM paketini kurulacak şekilde ve giriş noktasını (konteyner başlağında çalışacak işlem) /root/.npm-global/bin/opencode yoluna kurulmuş, opencode çalıştırılabilir dosyası olarak ayarlayalım.
Dockerfile’ı kullanarak, opencode etiketiyle bir imaj oluşturalım:
$ podman image build --tag opencode --file Dockerfile
Kolay erişim için Bash betiği
opencode:
#!/bin/bash
set -e
DATA_VOLUME='opencode-data'
IMAGE_TAG='localhost/opencode-cli'
MOUNT_DIR_CONTAINER='/workspace'
OPENCODE_PATH='/root/.npm-global/bin/opencode'
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
-d|--directory)
MOUNT_DIR_HOST=$(realpath "$2")
shift # Pass argument
shift # Pass value
;;
-o|--mount-options)
MOUNT_OPTS="$2"
shift # Pass argument
shift # Pass value
;;
*)
POSITIONAL_ARGS+=("$1") # Save arguments which will be passed to copilot
shift # Pass argument
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # Replace the arguments
if [ ! -z "${MOUNT_DIR_HOST}" ]; then
WORKSPACE_VOLUME_ARG="--volume ${MOUNT_DIR_HOST}:${MOUNT_DIR_CONTAINER}"
WORKDIR="${MOUNT_DIR_CONTAINER}"
else
WORKDIR="/root"
fi
if [ ! -z "${MOUNT_OPTS}" ]; then
WORKSPACE_VOLUME_ARG="${WORKSPACE_VOLUME_ARG}:${MOUNT_OPTS}"
fi
if ! podman volume exists "${DATA_VOLUME}"; then
podman volume create "${DATA_VOLUME}" # If volume does not exist, create
fi
if ! podman image exists "${IMAGE_TAG}"; then
printf "Error: Image is not available: %s\n" "${IMAGE_TAG}" # If image does not exist, print error message and exit
exit 1
fi
podman run \
--rm \
--interactive \
--tty \
--entrypoint "${OPENCODE_PATH}" \
${WORKSPACE_VOLUME_ARG} \
--volume "${DATA_VOLUME}:/root" \
--workdir "${WORKDIR}" \
"${IMAGE_TAG}" \
"$@"
Bash betiğinin genel amacı:
-d|--directoryve-o|--mount-optionsargümanları ile, ana dosya sisteminden konteyner içindeki dosya sistemine bağlanacak dizinin seçilmesi ve bağlama seçeneklerinin ayarlanması- Geriye kalan argümanların
opencodeprogramına gönderilmesi
- Geriye kalan argümanların
/rootdizininin (NPM dosyaları ve OpenCode yapılandırma dosyaları) kalıcı depolama birimine (volume) bağlanması (yoksa oluşturulması)- Konteyner içi çalışma dizininin belirlenmesi (eğer ana dosya sisteminden dizin bağlanmışsa, çalışma dizini orası olarak ayarlanır)
podman runkomutunun yeni konteyneri durduktan sonra silinecek şekilde, interaktif,/rootdizini depolama birimine bağlı veopencode‘a gönderilen argümanlarla başlatması
Red Hat Enterprise Linux dağıtımıyla beraber gelen, Lightspeed destekli, komut satırı asistanına (command-line-assistant) benzer bir deneyim için, .bashrc dosyanıza bu fonksiyonu ekleyebilirsiniz.
# opencode
c() {
opencode run "$@" | glow
}
Markdown biçimindeki çıktıyı formatlamak için kullanılan
glowaracını dağıtımınızın depolarından kurabilirsiniz.
Kullanımı
Bash betiği dosyasına gerekli çalıştırma yetkilerini verdikten ve PATH ortam değişkenindeki bir dizine taşıdıktan/kopyaladıktan (ben $HOME/.local/bin/ dizinine kopyaladım) sonra aşağıdaki şekillerde kullanabilirsiniz:
$ opencode: OpenCode terminal arayüzünü (TUI) aç. Ajan seçimi, LLM servisi bağlantısı,AGENTS.mdayarları vb. şeyler burada halledilir.$ opencode --directory ./test-dosyalari: Ana dosya sistemindekitest-dosyalaridizinini konteynere bağlar ve OpenCode’un çalışma alanı burası olur. (kısaltması-d)$ opencode --directory ./test-dosyalari --mount-options ro:test-dosyalaridizinini konteynere sadece okunabilir olarak bağlar.$ c 'podmanle imajları tar arşivine kaydetme komutu': OpenCode, prompt cevabını kendi terminal arayüzünde göstermek yerine, standart çıktıya yazar.glowaracı çıktıyı formatlar ve cici gösterir.
opencodeyukarıdaki örneklere ek; birçok seçeneğe, alt komuta ve kullanım alanına sahiptir. Yazının ve betiğin ana konusu konteyner ile izolasyon olduğundan, dosya sistemi ile ilgili komutlara yoğunlaştım. Detaylı bilgi ve daha çok örnek için:$ opencode --helpveya opencode.ai/docs
dogumer@fedora:~ 🚢🐳 $ c "podman niye var ve docker'dan farkı ne?"
│ build · deepseek-v4-flash
│
│ Podman, Docker'ın daemon'sız ve root'suz çalışma felsefesine alternatif
│ olarak Red Hat tarafından geliştirildi.
Ana farklar:
• Daemon yok: Docker, Docker Engine adında sürekli çalışan bir daemon
gerektirir. Podman'da bu yok — her komut kendi işlemini çalıştırır (fork-
exec).
• Root'suz: Podman'ı root olmadan, kendi kullanıcı namespace'inde
çalıştırabilirsin. Docker'da (rootless mode hariç) çoğunlukla root gerekir.
• Pod desteği: Podman, Kubernetes'teki "pod" konseptini doğal destekler.
Docker'da bu yok.
• Systemd entegrasyonu: Podman, servisleri systemd ile kolayca yönetilebilir
şekilde üretir.
• Kubernetes uyumluluğu: Podman'da kendi YAML'ın üretebilirsin ( podman
generate kube ), Docker'da bu daha zor.
Neden var? Güvenlik (daemon'suz + root'suz), daha az sistem kaynağı, ve
Docker'ın ticari yönüne (Docker Hub kotaları, lisanslama) bağımlı kalmamak.
Çoğu Docker komutu Podman'da aynı sözdizimiyle çalışır, o yüzden geçiş
kolaydır.
Özet: Docker tek büyük süreç (daemon) + root; Podman süreç başına izolasyon
+ kullanıcı alanında çalışır.
dogumer@fedora:~/Experiments 🚢🐳 $ ls asciidoc-experiments/
./ ../ aside.adoc counter.out counter.py demo.adoc demo.pdf sample.csv sample.json
dogumer@fedora:~/Experiments 🚢🐳 $ opencode -d asciidoc-experiments/ -o ro
OpenCode izinlerini ayarlama
OpenCode, belirli bir aksiyon almak için aşağıdaki şekillerde yapılandırılabilir:
"allow": Sormadan direk aksiyon al"ask": Aksiyon almadan önce kullanıcıya sor"deny": Aksiyonu engelle
Yapılandırma ayarları JSON formatında, .config/opencode/opencode.jsonc dosyasına yazılır.
Kalıcı depolama için oluşturulan “volume"ün ana dosya sistemindeki yerini bulalım:
dogumer@fedora:~ 🚢🐳 $ podman volume inspect opencode-data
[
{
"Name": "opencode-data",
"Driver": "local",
"Mountpoint": "/home/dogumer/.local/share/containers/storage/volumes/opencode-data/_data",
"CreatedAt": "2026-08-01T22:47:17.960474962+03:00",
"Labels": {},
"Scope": "local",
"Options": {},
"MountCount": 0,
"LockNumber": 8
}
]
Sonrasında yapılandırma ayarlarımızı dosyaya yazalım:
dogumer@fedora:~/.local/share/containers/storage/volumes/opencode-data/_data 🚢🐳 $ vim .config/opencode/opencode.jsonc
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "ask",
"read": {
"/workspace/*": "allow",
".env*": "deny"
}
}
}
Benim kullandığım yapılandırmada, varsayılan olarak OpenCode herhangi bir aksiyon almadan soruyor; sadece
/workspace/dizinindeki (bağlanan dizin) dosyaları sormadan okumasına izin veriliyor ve.envdosyalarını okuması engelleniyor. Kendi kullandığınız ortama ve kişisel tercihlerinize göre izinleri gevşetip sıkılaştırabilirsiniz.Yapılandırmalar hakkında daha detaylı bilgi için
İzinler hakkında daha detaylı bilgi için


