Skip to content
Konsultasi

Bare python di entrypoint Docker: interpreter sistem, bukan venv

Adityo Guni Waluyo

Script seed knowledge gagal terus di container padahal file ada di image. Ternyata bare python manggil interpreter sistem, bukan venv.

Ringkasan

Script knowledge seed gagal di Docker karena bare python memakai interpreter sistem, bukan venv, sehingga dependensi yang terpasang tidak terlihat. Solusinya panggil interpreter venv dengan path absolut dan set PYTHONPATH ke root project agar import berfungsi. Tambahkan || echo skipped supaya container tetap hidup dan kegagalan tetap tercatat di log.

Knowledge Seed Gagal Terus, Padahal Scriptnya Udah Ada di Image

Log entrypoint muter terus tiap container naik: knowledge seed skipped (failed). Script-nya jelas ada di image, lengkap dengan foldernya. Gue coba jalanin manual di dalam container dan yang muncul sama aja: ModuleNotFoundError. Padahal venv lengkap sama dependensi aplikasinya kepasang rapi di image. File-nya ada, package-nya ada, tapi script-nya tetap nggak bisa jalan. Di situ gue mulai curiga: python yang dipanggil ini sebenarnya interpreter yang mana?

Bare python di container itu interpreter sistem yang bawaan base image. Bukan interpreter venv. Package yang terpasang di venv (/app/api/.venv/) sama sekali nggak keliatan buat interpreter ini, soalnya venv itu punya interpreter sendiri plus site-packages yang terisolasi dari base Python [1]. Jadi walaupun image udah include venv lengkap dengan semua dependensi, manggil python tanpa path spesifik itu kayak manggil orang yang nggak kenal sama project-nya.

## Kenapa CWD Juga Nggak Menyelamatkan

Dugaan awal gue: "Ya udah, cd /app/api dulu sebelum jalanin script." Ternyata nggak cukup.

CWD cuma dimasukkin ke sys.path kalau kamu menjalankan Python secara interaktif, atau lewat opsi command line kayak dash c dan dash m [3]. Kalau kamu jalankan file script secara langsung kayak python scripts/seed_knowledge.py, entry pertama di search path itu direktori berisi script-nya, bukan CWD [2].

Jadi cd /app/api && python scripts/seed_knowledge.py tetap gagal buat import yang butuh root project. /app/api nggak masuk sys.path otomatis. Interpreter cuma nyari di direktori lokasi script dan path standar sistem.

Solusi yang bener butuh dua hal sekaligus. Pertama, panggil interpreter venv langsung: /app/api/.venv/bin/python. Kedua, tambahin PYTHONPATH=/app/api supaya root project masuk search path.

## Fix-nya: Path Penuh + PYTHONPATH Eksplisit

Di .docker/entrypoint.sh, baris lama:

python /app/api/scripts/seed_knowledge.py

Diganti jadi:

cd /app/api && PYTHONPATH=/app/api /app/api/.venv/bin/python scripts/seed_knowledge.py || echo skipped

cd /app/api di sini sebenernya redundan buat path script absolut — nggak ngubah perilaku import. Tapi gue biarin karena nggak berbahaya dan bikin konteks kerja lebih jelas kalau seeder nanti butuh file relatif.

Yang penting: interpreter venv dipanggil pakai path absolut, dan PYTHONPATH di-set eksplisit ke root project. Ini bukan hack, ini cara yang docs-nya rekomendasikan [2].

Satu catatan buat yang iseng mau jalan pintas: pasang package langsung di interpreter sistem biar bare python bisa jalan. Jalur ini emang ditutup rapi. Sejarahnya, pip dulu default-nya manggil ke konteks global, dan itu sering tabrakan sama package manager-nya OS: konflik file, package bawaan distro ketimpa. Makanya PEP 668 bikin distro nandain environment dasar sebagai "externally managed" yang nolak pip install di situ [4].

Ada satu jebakan halus lagi dari sisi command line: mode isolated atau python -I mengabaikan semua variabel lingkungan berawalan PYTHON, termasuk PYTHONPATH [3]. Jadi kalau suatu saat entrypoint-nya diubah pake mode itu demi kebersihan environment, trik PYTHONPATH di artikel ini bakal bisu. Path penuh ke interpreter venv tetap jadi fondasi, PYTHONPATH cuma pelengkap.

## Kenapa Ini Gampang Banget Kena

Kesalahan ini gampang banget terjadi karena dua hal. Pertama, Docker image yang "lengkap" bikin kamu ngerasa semua udah beres: script ada, file ada, tinggal jalanin. Kedua, di mesin lokal, activated venv bikin python otomatis nunjuk ke interpreter yang benar. Pas pindah ke Docker di mana activation nggak terjadi di entrypoint, kebiasaan itu jadi jebakan.

Satu hal yang gue pelajari: di entrypoint script, jangan pernah andalkan environment inheriting dari build stage atau aktivasi venv yang implicit. Panggil interpreter venv dengan path penuh. Set PYTHONPATH kalau import-nya butuh root project. Dan kalau step-nya non-critical, kasih || echo skipped di ujungnya biar container nggak mati total, tapi kejadiannya tetap keliatan di log.

Kebiasaan lain yang menurut gue patut ditiru dari fix ini: seed yang gagal nggak bikin container mati. Tapi gagalnya jangan sampai hilang begitu aja. Baris "skipped (failed)" di log itu jejak yang bikin masalah ketahuan belakangan, bukan lenyap selamanya. Bayangin kalau script-nya dihapus aja dari entrypoint, bertahun-tahun kemudian baru sadar knowledge base-nya kosong.

Artikel terkait