İçeriğe geç
Can Uğurlu
Geri dön

Coolify'da build exit code 137 ile neden ölüyor

Coolify’da Astro build’i exit code 137 ile ölüyorsa sebep neredeyse her zaman OOM. Hata mesajı bunu söylemiyor, sadece 137 diyor.

137 sayısı ne anlatıyor

137, 128 artı 9. 128, bir sinyalle sonlanan süreçlere Docker’ın eklediği sabit; 9 ise SIGKILL sinyalinin numarası. Yani süreç kendi isteğiyle çıkmadı, kernel onu zorla öldürdü. Bunu yapan Linux’un OOM killer’ı: bellek tükendiğinde sistemi ayakta tutmak için en çok bellek tüketen süreci seçip sonlandırıyor.

Hata mesajında “out of memory” yazmaz, sadece exit code 137 görürsünüz. Bu yüzden herkes önce framework’ü, sonra bir bağımlılığın sürümünü suçluyor. Sebep neredeyse hep daha sıkıcı: build container’ına tanımlı bellek limiti yetmiyor.

Bunu nasıl doğrularsınız

Host’ta dmesg çalıştırıp OOM killer’ın log satırını arayın:

dmesg | grep -i "killed process"

Container üzerinden kontrol ediyorsanız docker inspect çıktısındaki OOMKilled alanına bakın:

docker inspect <container_id> --format '{{.State.OOMKilled}}'

true dönüyorsa tartışma bitmiştir. Framework’ün, bundler’ın ya da bir paketin hatası değil, bellek yetersiz.

Statik site build’inde tipik sebepler

Üç şey en sık tekrar ediyor.

Birincisi görsel işleme ve build zamanında üretilen OG görselleri. Bu blogda her yazı için bir OG görseli Satori ile render ediliyor, sonra sharp ile PNG’ye çevriliyor. Yazı sayısı arttıkça bu adım tek seferlik değil, yazı başına bir kez çalışıyor ve bellek orada tepe yapıyor.

İkincisi bundler’ın bütün modül grafiğini bellekte tutması. Vite büyük bir projede bağımlılık ağacının tamamını analiz ederken bellek kullanımı build’in ortasında aniden sıçrayabiliyor.

Üçüncüsü sunucunun runtime’a göre boyutlandırılmış olması. nginx container’ı birkaç yüz megabaytla rahatça çalışıyor, ama build container’ı aynı sunucuda, aynı bellek limitiyle çalışmak zorunda kalıyor. Bu ayrım Docker imajınız neden 1,2 GB yazısındaki build/runtime katman ayrımıyla aynı sebepten geliyor: iki farklı işin tek bir kaynağa sıkıştırılması.

Sırayla ne yapılır

Önce build’in bellek limitini yükseltin. Coolify’da bu, uygulamanın kaynak ayarlarından build container’ına verilen belleği artırmak demek. Bu projede 1 GB’lık bir sunucuda build tam OG görsel üretiminin ortasında düşüyordu, build’e 2 GB verince sorun bitti.

Limit yükseltmek çözmüyorsa tepe kullanımı düşürün: üretilen görsel sayısını azaltın, build’i adımlara bölün, gerekirse OG görselini build zamanı yerine talep anında üretin.

En sona NODE_OPTIONS=--max-old-space-size bırakılır:

NODE_OPTIONS=--max-old-space-size=1536 pnpm build

Bu değeri konteynerin sahip olduğu RAM’in üzerine ayarlamak durumu düzeltmiyor, kötüleştiriyor. Node’a “bu kadar bellek kullanabilirsin” demek kernel’in fiziksel limitini değiştirmiyor. Heap sınırını RAM’den yüksek tutarsanız OOM kill daha erken gelir, daha geç değil.

Build’i sunucudan ayırmak bir seçenek

Build’i her seferinde aynı küçük sunucuda çalıştırmak zorunda değilsiniz. Build’i CI’da, örneğin GitHub Actions’da çalıştırıp sadece bitmiş imajı Coolify’a deploy etmek, sunucunun bellek sınırını denklemden tamamen çıkarıyor. Bedeli var: pipeline bir bağımlılık daha kazanıyor, registry ve kimlik doğrulama ayarlanması gerekiyor. Küçük bir proje için build container’a birkaç GB daha vermek genelde daha basit çözüm; bu ayrımı sadece build tekrar tekrar aynı sebepten düşüyorsa düşünün.

Asıl yanlış sunucuyu servise göre boyutlandırmak

nginx runtime’ı statik dosya servis ediyor, ihtiyacı çok az bellek. Build ise bütün siteyi tek seferde derliyor, görselleri işliyor, modül grafiğini bellekte tutuyor; ihtiyacı katbekat fazla. Sunucuyu “site zaten statik, az kaynak yeter” diyerek runtime’a göre boyutlandırmak, build’i her deploy’da OOM’a mahkum ediyor.

Özet

exit 137 gördüğünüzde önce dmesg ya da OOMKilled ile OOM’u doğrulayın. Build’in bellek limitini yükseltin, sonra tepe kullanımı düşürün, NODE_OPTIONS en son çare olsun. Sunucuyu runtime’a değil build’in ihtiyacına göre boyutlandırın.


Bu yazıyı paylaş:

Önceki Yazı
Statik site mi, SSR mi
Sonraki Yazı
Bu blogu neden ve nasıl kurdum