- Docker imajlarını zaten dağıtım birimi olarak kullanan bir ortamda Nix, iş akışını büyük ölçüde değiştirmeden deterministik derlemeler ve bağımlılık sabitlemeyi denemek için bir giriş noktası olur
- Tipik bir
docker build, Ubuntu depoları veya harici indirmeler gibi açık internetin durumuna kolayca bağımlı hâle gelir; bu da aradan zaman geçtikten sonra aynı imajı yeniden üretmeyi zorlaştırır
- Nix, gerekli bağımlılıkları paket düzeyinde bildiği için
dockerTools.buildLayeredImage ile yalnızca değişen katmanları yeniden yükleyen bir yapılandırma mümkün olur
- Go tabanlı
douglas-adams-quotes örneği, ikili dosyanın pkgs.buildGoModule ile oluşturulup nix build .#docker, docker load < ./result ile normal bir Docker imajı gibi yüklenerek dağıtılabileceğini gösterir
- Bir monorepo’daki birden fazla servis katmanları ve Nix önbelleğini paylaştığında, geçmiş commit’lerin imajlarını yeniden üretirken ve tekrarlı dağıtımlarda derleme süresi ile maliyet azaltılabilir
Docker imajı derlemeye Nix eklemenin nedeni
- Nix aynı anda üç niteliğe sahiptir: paket yöneticisi, dil ve işletim sistemi
- Paket derleme talimatları Nix diliyle yazılır
- Nix paket yöneticisi bu talimatlara dayanarak yazılım, araçlar, NixOS imajları, konteyner imajları vb. oluşturabilir
- Nix’i mevcut CI/CD pipeline’larına dahil etmek kolay değildir
- Nix, birçok geliştiricinin alışık olduğu yöntemlerden farklıdır
- Yeni bir startup ya da homelab gibi her şeye sıfırdan başlanabilen bir ortam değilse benimseme eşiği yüksektir
- Zaten Docker kullanan kuruluşlar, mevcut dağıtım akışını büyük ölçüde bozmadan deneme yapmak için Nix’i önce konteyner imajı derleme tarafında uygulayabilir
Docker derlemesinin sallandığı noktalar
- Docker ve konteynerleştirme yaygın biçimde benimsendiği için Docker imajları internette fiilen evrensel paket formatı gibi kullanılır
- Fly.io, Railway, Render gibi platformlar rastgele VM imajları veya tarball biçimindeki Linux programları yerine Docker imajlarını kullanır
- Docker derlemeleri her zaman deterministik değildir
- İnternette sık görülen Dockerfile’ların çoğu sorunsuz derlenir; ancak başarısız olan küçük bir oran operasyonel sorunlara yol açabilir
- En büyük zayıf noktalardan biri, Docker derlemesinin açık internete erişmesidir
- Ubuntu deposundan paket indirmek için bu gerekir
- Daha sonra aynı imajı yeniden oluşturmak gerektiğinde, o zamanki Ubuntu deposunun tam durumuna geri dönmek zordur
- Ubuntu 18.04 ilgili yıl içinde destek sonuna yaklaşmış durumda olduğundan, bir şeyin o sürüme bağlı olduğunu ancak arıza yaşandıktan sonra fark edebilirsiniz
- Docker imajına basit yöntemlerle paket eklemek boşa harcanan alan oluşturabilir
- Derlemenin başlarında
apt-get upgrade çalıştırılırsa konteyner imajı içindeki dosyalar değiştirilebilir
- Değiştirilmeden önceki dosyalar katmanlarda kalıp gölge kopyalar gibi birikebilir
Nix’in Docker katmanlarını ele alma biçimi
- Nix, gerekli bağımlılıkları önceden bilir ve bunları mümkün olduğunca az Docker katmanına bölebilir
- Kodda tek bir satır değişti diye
apt veya npm bağımlılıkları yeniden kurmak zorunda kalmaz
- İmaj güncellemesine yalnızca gerçekten değişen en küçük içerik yansıtılabilir
dockerTools, Nix paketlerini ve bağımlılıklarını Docker imajına koymaya yarayan bir araç kümesidir
- Nix ile oluşturulan Docker imajları kabaca iki yönteme ayrılır
- Katmansız imaj: Programı, bağımlılıkları ve TLS kök sertifikaları gibi ek öğeleri tek bir klasöre koyup tek katmanlı imaj olarak sunar
- Katmanlı imaj: Her bağımlılığı ayrı bir imaj katmanı olarak yerleştirir; böylece yalnızca gerçekten değişen parçalar yüklenebilir
- Docker’ın içinde de içerik tabanlı bir depo vardır, ancak yalnızca
docker build ile bundan yeterince yararlanmak zordur
- Nix’in katmanlı imajları paket bazlı katmanlar kullandığından
glibc gibi bağımlılıkları yalnızca bir kez yüklemek yeterlidir
- Ancak ilgili kütüphanede değişiklik gerekiyorsa o katmanın yeniden yüklenmesi gerekir
Go servisi örneği: Douglas Adams Quotes
- Örnek servis, Douglas Adams alıntıları sunan bir Go programıdır
- Go modül projesi,
pkgs.buildGoModule ile Nix paketi olarak tanımlanır
bin = pkgs.buildGoModule {
pname = "douglas-adams-quotes";
inherit version;
src = ./.;
vendorHash = null;
};
- Bu tanım, Go modül şablonunu kullanarak Go derleyicisini, CGo için C derleyicisini ve harici bağımlılık indirmelerini yapılandırır
pname paket adıdır
version, servisin Git commit’inden otomatik oluşturulur
src = ./.; mevcut çalışma dizinindeki kaynak kodu kullanır
- Standart kütüphane dışında bağımlılık yoksa
vendorHash = null verilebilir
- Harici bağımlılıklar varsa tüm bağımlılıkların hash’i belirtilmeli veya
gomod2nix kullanılmalıdır
- Paket şu komutla derlenir
nix build .#bin
- Docker katmanlı imajı
dockerTools.buildLayeredImage ile oluşturulabilir
docker = pkgs.dockerTools.buildLayeredImage {
name = "registry.fly.io/douglas-adams-quotes";
tag = "latest";
config.Cmd = "${bin}/bin/douglas-adams-quotes";
};
config.Cmd içinde derlenmiş sunucu ikili dosyası belirtilirse gerekli öğeler birlikte kopyalanır
glibc ve çalıştırma için gereken öğeler de dahil edilir
- CA kök sertifikaları gibi ek paketler
contents içine konabilir
docker = pkgs.dockerTools.buildLayeredImage {
name = "registry.fly.io/douglas-adams-quotes";
tag = "latest";
contents = with pkgs; [ cacert ];
config.Cmd = "${bin}/bin/douglas-adams-quotes";
};
- İmaj şu komutlarla oluşturulur ve Docker daemon’a yüklenir
nix build .#docker
docker load < ./result
dive ile açıldığında her katmanın nixpkgs’ten farklı bir paket eklediği ve en sonda öğelerin imaj köküne sembolik linklendiği görülür
Monorepo’da katman paylaşmanın etkisi
- Aynı depoda birden fazla servis varsa Nix ile oluşturulan Docker imajları katmanları paylaşabilir
- Paylaşım ek yapılandırma olmadan gerçekleşir
- Bunu yalnızca Docker ile yapmak için birden fazla ortak base imaj oluşturmak gerekir; bu da bazı servislerin kullanmadığı araçları ve gereksiz içerikleri içerebilir
- Örneğin
Xe/x deposu, 10 yıllık yan projelerin, deneylerin ve araçların toplandığı bir monorepo’dur
- Birden fazla proje yaklaşık üç platforma dağıtılmıştır
- Ortak dağıtım temeline yakınsamak için bunları Docker imajlarına koyma çalışması yürütülmüştür
- Bir servis güncellemesi push edildiğinde, diğer servislerin çoğuyla paylaşılan güncellemelerin bir kısmı da birlikte push edilir
- Bu yöntem birden fazla projede zaman ve maliyet tasarrufu sağlar
Yalnızca Docker önbelleğiyle yetişmenin zor olduğu kısımlar
- Docker caching kullanılırsa teoride imajları Nix kadar verimli derlemek mümkün olabilir
- Ancak Docker yöntemiyle aynı etkiyi elde etmeye çalışmak derleme adımlarını bakımı zor hâle getirebilir
- Paylaşılan kütüphaneler ayrı bir katmana kurulmalıdır
- Derleme sırasında ağ stack’inin yeniden açılması gerekir; bu da yeniden üretilebilirliği zayıflatır
- Arama yolları, derleyici bayrakları ve CGo ile ilgili ayarlar yeniden düzenlenmelidir
- Nix’in
dockerTools.buildLayeredImage aracı, paketleri konteynere koymanın ayrıntılarını üstlenerek yapılandırmayı basitleştirir
Geçmiş bir noktayı yeniden üretme ve Nix önbelleği
- Nix’in en büyük avantajlarından biri, geçmiş bir andaki yazılımı tam olarak yeniden derleyebilmesidir
- Daha sonra belirli bir müşteri ortamındaki hatayı yeniden üretmek gerektiğinde aynı Docker imajı yeniden oluşturulabilir
- Paket derlemesi, yazılımın ve tüm bağımlılıkların durumunu belirli bir ana sabitleme işlevi görür
XeDN, birkaç yıldır üzerinde çalışılan bir projedir ve 14 ay önceki sürüm şu komutla derlenebilir
nix build github:Xe/x/567fdc2#xedn-docker
- Bu komut,
GitHub repo Xe/x içindeki belirli bir commit’ten xedn-docker hedefini derler
- Docker daemon’a yüklendiğinde o zamankiyle aynı baytlara sahip imaj oluşturulur
- Örnekte Go 1.19 da dahildir
- Yalnızca standart Docker derlemesiyle aynı yeniden üretimi yapmak büyük miktarda depolama maliyeti gerektirebilir
- Nix önbelleği, Nix komutlarının çıktılarını saklayarak daha sonra yeniden derlenmelerini önler
- Her geliştirici dizüstü bilgisayarında
nokogiri gibi paketlerin yeniden derlenmesi gerekmez
- Bulutta önceden derlenmiş sonuçlar alınabilir
- Garnix, tüm flakes projelerinin CI’ında kullanılır ve her commit için derleme durumunu bildirir
- Homelab makine ayarları da Garnix ile derlenir; her akşam güncelleme yapılırken yerel derleme yerine en güncel ayarlar Garnix önbelleğinden alınır
Dağıtım çıktısı olarak sonuç
- Nix’in, Docker imaj oluşturucusu olarak Docker’ın kendi imaj oluşturucusundan daha iyi olduğu söylenebilir
- Nix, sonucu belirtmeye yönlendirir; o sonuca ulaşmak için gereken ayrıntılı adımları tek tek sıralatmaz
- Zaten Docker kullanan ortamlarda Nix’i Docker imajı derlemeden başlayarak uygulamak gerçekçi bir benimseme yoludur
- Nix ile oluşturulan Docker imajları, monorepo’nun farklı bölümleri arasında katmanları paylaşabilir
- İkili önbellek sayesinde geçmişte zaten derlenmiş kodu yeniden derlemek gerekmez
- Nihai çıktı, AWS, Google Cloud, Fly.io gibi platformlara dağıtılabilen sıradan bir konteyner imajıdır
1 yorum
Hacker News yorumları
Nix'i sevmeye çalışmayı birkaç kez denedim ama artık vazgeçmem gerektiğini hissediyorum
Nix çalıştıran 2 sistemim var; onlara dokunmaya korkuyorum ve geçmişte ikisi de bozulduğu için sıfırdan yeniden kurmak zorunda kaldığım da oldu. Teoride Nix idempotent ve deterministik; ama pratikte neye göre deterministik olduğunu anlamanız gerekiyor. Bağımlı olduğunuz tüm parçaların davranışını derinlemesine bilmiyorsanız tuhaf sonuçlarla, garip ve işe yaramayan hatalarla ya da hiçbir geri bildirim alamadığınız durumlarla karşılaşıyorsunuz
Belgeler eksiksiz ve teknik olarak doğru olsa bile berbat derecede anlaşılması zor; eğitimler sizi yolun ancak %80'ine kadar götürüyor. Bunun dışına çıktığınızda kendiniz inşa etmeniz gerekiyor; bu da yıllarca birikmiş deneyim bilgisi ve hayal kırıklığı gerektiriyor, artık bunu kaldırmak istemiyorum. Docker'ın avantajı ise tam tersine kaosun kendisi: kabuk ve dağıtım paket yöneticilerini kabaca bilseniz bile neredeyse her şeyi yapabiliyorsunuz; bir sorun çıktığında da onlarca yıllık araçlar sayesinde teşhis etmek ve düzeltmek çok daha kolay
Nix, Emacs gibi; sabrınız ve derin, vizyoner bilginiz varsa her şeyi yapabilirsiniz, ama ya tamamen içine dalmanız ya da uzaktan izlemekle yetinmeniz gerekiyor gibi görünüyor
Aynı makinede arka arkaya iki kez derlerseniz aynı sonucu alırsınız; ama zaman geçip paket yöneticisi ve base image etiketleri güncellendiğinde, bir ay sonra yeniden derleme sonucu tamamen farklı olur. Ekibin yönettiği yaklaşık 40 konteyner olduğunda, konteynerleri düzeltmek işin büyük bir parçası haline geliyor
Bu yüzden teoride Nix'in kusursuz olması gerekir; ancak çok farklı olduğu için vendor araçları Nix'te çalışmıyor ve hata aldığınızda web'de hızlıca çözüm bulmak zor. Bu sıkıntı yüzünden https://www.stablebuild.com'u yaptım; Docker tabanlı deterministik derlemeleri Ubuntu, Debian ve Alpine konteynerleri üzerinde sunuyor. Değişmez bir Docker Hub pull-through cache, Ubuntu/Debian/Alpine paket depolarının günlük tam kopyaları, popüler PPA'ların ve PyPI indeksinin günlük kopyaları, rastgele dosya/URL'ler için değişmez cache'ten oluşuyor
Pratikte kullanması ve debug etmesi kolay, yazılım uyumluluğu da geniş; StableBuild'e taşıdığımız konteynerlerde deterministik olmamaktan kaynaklanan sorun sayısı 0 oldu
nix develop'ın neden belgelerde yazdığı gibi davranmadığını ve öyle davranmasını nasıl sağlayacağımı anlamaya zaman harcadığım olmuştu. Belgeler varsayılan olarak derleme zamanı ortamına girildiğini söylüyor; ama gerçek varsayılan yalıtılmış değil, komut satırı seçeneklerinin adları da kafa karıştırıcı olduğu için bilgiyi kaynaktan kazıp çıkarmak zorunda kaldımYeniden üretilebilirliği bozan edge case'lerin de daha açık ele alınmasını isterdim. Kayan nokta kodu işlem sırasına duyarlıdır ve işletim sistemi preemption'ı yüzünden durum sızabilir; bariz şeyler bile açıkça belirtilmezse insanlar kendi ayağına sıkıyor
“Erase your darlings” yapılandırmasını kullanırsanız kullanıcı hesabı dışındaki yeniden üretilemeyen durumun çoğunu ortadan kaldırabilirsiniz. Biraz zahmetli ama NixOS'ta zahmetli olmayan ne var ki diye düşünmeden edemiyor insan
https://grahamc.com/blog/erase-your-darlings/
Kullanıcı hesabının içini umursamıyorum ve Home Manager'ı sevmiyorum
Docker fena değil ama Mac'te performansı pek iyi değil; Nix ise birden fazla makinede aynı şekilde kurulmasını ve çalışmasını sağlamayı önemsiz hale getirdiği için güzel. Nix belgeleri berbat ama ChatGPT-4 Nix sorunlarını çözmede harikaydı
Nix sorunlarının %90'ı “Nix yöntemi” olmayan bir şeyi yapmaya çalışmaktan kaynaklanıyormuş gibi geldi
Neredeyse tüm dağıtım paket yöneticilerini kullandım ve özel bir şey yapmasam bile hepsini bir şekilde bozmayı başardım. Fedora Kinoite ise layer ekleme/çıkarma, günlük güncelleme, hatta Silverblue'dan rebase etme gibi işlemlere rağmen sağlam duruyor. Kişisel olarak rpm-ostree'nin Nix'in yerini alacağını düşünüyorum
Nix ve NixOS’un, GitHub öncesi git’e benzer bir durumda olduğunu düşünüyorum
Temel fikir, SVN veya Docker gibi mevcut yaklaşımlardan daha ciddi bilgisayar bilimine dayanıyor; iç tesisatında hâlâ sorunlar var ama daha kötü değil. Ancak kullanıcıya dönük araçlar ve dokümantasyon ana akım benimseme seviyesinde değil
flox’un çıkışı bunu değiştirmiş olabilir: https://flox.dev. Neredeyse sorunsuz; DE Shaw kökenli oldukları için şaşırtıcı da değil
Nix, flakes ve
nix-commandolmadan pek anlamlı değil; ikisi de dokümantasyonda deneysel olarak geçiyor ve varsayılan olarak kapalı. Dokümantasyon iyileşiyor ama hâlâ yetersiz; nixlang iyi öğrenildiğinde harika, fakat ana akıma giriş engeli olarak kabul edilebilir değil.nix-env -iA fooçoğu durumda fiilen istenen davranış değil; bu yüzden Nix, reklamı yapıldığı türden bir paket yöneticisinden çok, kurum içi uzmanlığı kaldırabilecek şirketlerin gizli silahına daha yakınflox, “bir kez deneyip hemen daha iyi bir deneyim elde etme” eşiğini düşürüyor. Nix/NixOS ya da ona benzer bir şey sonunda Docker’ı Subversion gibi geriye itecek; ancak GitHub benzeri bir an gelene kadar bu olmayacak, geldiğinde de bir anda olacak
Bu başlıktaki Nix şikâyetlerinin çoğu teknik olarak yanlış ama tamamen anlaşılır; daha önemlisi, kullanıcının suçu değil. git/GitHub olmayan bir dünyayı bilen kuşağın azaldığının farkındayım ama Linus’un, ilk dönem Google işe alım kriterlerini geçmiş insanların önünde, neden karmaşık hissettiren bir araca önem vermeleri gerektiğini anlatmasını dinlemek iyi olur
https://youtu.be/MjIPv8a0hU8?si=QC0UnHXRdMpp2tI4
Bunu bir süredir geliştiriyoruz; daha iyi yapmak için öncelik vermemiz gereken bir şey varsa duymak isterim
git böyle, ama Nix henüz değil; bu yüzden GitHub benzeri bir anın yardımcı olup olmayacağından pek emin değilim
Bu blog yazısında paylaşılan Docker katmanlarının neden yararlı olduğuna dair açıklama eksik
Nedeni önbellekleme; ne kadar çok imaj aynı katmanları paylaşırsa o kadar çok şey önbelleğe alınabilir ve konteyner başlatma hızlanır
Docker’ın burada zayıf olmasının nedeni, önbellekleme avantajı elde etmek için imaj oluşturulurken mevcut katmanlarla mümkün olduğunca aynı katmanların ortaya çıkması gerekmesi. Örneğin bugün
apt-get install python3çalıştırdığınızda yeni güncelleme yoksa dünle tamamen aynı katman oluşmalı; ancak Docker katmanları dosya hash’leriyle önbelleğe alındığından, oluşturulma zamanı gibi metaveriler dâhil tüm dosyaların birebir aynı olması gerekirNix zaten bağımlılıkları hash olarak sakladığı için, aynı sürüm ve aynı ayarlar varsa katman her zaman aynı olur
Bağımlılıklar genellikle ağaç değil grafik oluşturduğu için bu kısa sürede can sıkıcı hâle gelir. Nix veya muhtemelen Bazel gibi alternatif araçlarda bu kısıt yoktur; bağımlılık grafiğini Docker katmanlarına eşleyerek ince taneli önbellekleme sağlayabilirler. Bu, Dockerfile ile ifade edilemeyen bir yöntemdir
apt-getiçeren katman otomatik olarak geçersiz kılınmazYalnızca
--no-cachekullanıldığında veya üst katmanda değişiklik olduğunda farklılaşırSon 2-3 gündür Darwin üzerinde Docker imajı derlemeye çalışırken uğraşıyordum; bu yazı evrenin benimle dalga geçmesi gibi hissettirdi.
Nix, hedeflediğiniz şey için kesinlikle en iyi araç; ama ruhu emen karanlık ve terk edilmiş köşeleri var. Seviyorum, ama bazen kendimi Rick'in Derleyici Diyarı macerasına sürüklenen Morty gibi hissediyorum.
Docker özünde Linux ikililerini tutan bir hapishaneye daha yakın. Linux'ta ikiliyi derleyip container'a koyarsınız, biter; Nix kodu da basittir. Kodu derleyebiliyorsanız container oluşturmak yalnızca bir adım daha demektir.
Ama Docker Linux ikilileri ister; Mac'te ise Docker Desktop bir Linux VM'i ayağa kaldırır, tüm işi onun içinde yapar ve bu gerçeği gizler. Nix bunu yapmadığı için iki seçeneğiniz vardır.
Birincisi çapraz derleme yapmak; ama glibc'ye kadar çapraz derlenebilir olması gerekir. Topluluk bağımlılıklarının çoğu çalışsa bile bazı paketlerin yazarları çapraz derlemeyi önemsememiş olabilir. Üstelik standart Nix önbelleğini dolduran Hydra çapraz derleme build'leri yapmadığı için uzun süre derleyip sonunda başarısız olabilirsiniz.
İkincisi Mac'e bir Linux builder bağlayıp
x86_64-linuxbuild işlerini oraya göndermek. Fiziksel makine, VM, hatta NixOS Docker container'ı bile olabilir.1 numara doğru yol gibi görünür, ama 2 numara daha pratiktir. Yaşadığınız sorunlar büyük olasılıkla 1 numarayı denediğiniz içindir; bu da yalnızca Nix değil, epey çapraz derleme deneyimi de gerektirir. Hydra'nın Darwin'den Linux'a çapraz derlemeleri de build edip önbelleğe koyması ve kırılmaları engellemesi iyi olurdu, ama maliyeti de artırırdı. 2 numaralı çözümü denemek daha iyi görünüyor.
Sanırım resmi bir çözüm vardı: https://ryantm.github.io/nixpkgs/builders/special/darwin-bui...
Bazı stack'lerde çapraz derleme çok sağlam olmadığı için Docker ile
{aarch64,amd64} x {linux,darwin}çapraz derlemesi yapıyorum. Darwin aarch64 üzerinde birden fazla Docker çalıştırıp hepsini derliyorum; deneyim gayet iyiydi.https://github.com/gytis-ivaskevicius/high-quality-nix-conte...
Bir iki bug var ama daha çok volume ile ilgili görünüyor; Docker imajı build etmeyi gayet iyi hallediyor. Daha çetin kısım hız: donanım ile Docker'ın Linux VM'i emüle etmek zorunda olması birleşince ciddi bir darbe vuruyor.
Java uygulamaları için Docker imajlarını Nix ile derleme deneyimi pek iyi değildi
gradle2nixterk edildikten sonra Gradle tabanlı Java uygulamaları için net bir alternatif yok gibi görünüyor. Daha önce bir arkadaşımdan basit bir Spring Boot uygulaması için mümkün olduğunca küçük bir Docker imajı yapmasını istemiştim; Nix ile ortaya çıkan sonuç, Nix kullanılmadan yapılan imajın iki katı boyutundaydıKodu burada görebilirsiniz: https://github.com/jossephus/Docker_challenge/blob/main/flak...
zulu ile gradle'ın
jdkargümanı olarak dahil ettiği JDK birlikte geliyor. nixpkgs'dekigradleGene bakarsanız ne demek istediğimi anlarsınız.gradle2nixiçin üzgünüm; daha az hack kokan bir iyileştirme üzerinde çalışıyorumKabaca şöyleydi: https://gist.github.com/takeda/17b6b645ad4758d5aaf472b84447b...
Her şeyi musl ile linkledim, Python'ı derlerken uygulamanın kullanmadığı tüm paketleri devre dışı bıraktım ve boto3/botocore'da kullanılmayan kısımları çıkardım. Sadece boto3/botocore bile 100 MB'tan büyük
Nix paketleri varsayılan olarak NixOS işletim sistemini hedeflediğinden, disk alanının bol olduğu normal senaryolarda tüm özelliklerin açık olması istenir. Bu yüzden gereksiz birçok bağımlılık beraberinde gelir. Buna karşılık Alpine imajları Docker için tasarlandığından, paketlerde ek özellikleri kapatmak hedeflenir ve sonuç daha küçük olur
Küçük imajlar yapmak için gereksiz şeyleri
overrideile kapatmak gerekir. Örneğin zulu; alsa, fontconfig, freetype, xorg, cups, gtk, cairo, ffmpeg gibi şeyleri içerir. Arkadaşım yalnızca gerekli dosyaları dikkatle çıkarıp konteynere koymuştu; Nix tarafı ise zulu paketinin tamamını ve tüm bağımlılıklarını bundle'a dahil etmiş sayılırÖnce yalnızca tek bir JDK içerecek şekilde düzeltip, ardından yukarıdaki yöntemlerle JDK boyutunu daha da küçültebilirsiniz.
openjdk_headlesskullanmak daha basit olabilirhttps://github.com/NixOS/nixpkgs/blob/master/pkgs/developmen...
https://github.com/GoogleContainerTools/jib/tree/master/jib-...
openjdk_headless, Spring'in ihtiyaç duymadığı GTK ve X bağımlılıklarını atlarZulu yerine Nixpkgs'in headless OpenJDK derlemesini temel alacak şekilde değiştirerek GUI kütüphanesi bağımlılıklarını kaldırdım ve
pkgs.jre_minimalilejlinkkullanarak özel bir minimal JRE oluşturdumİmaj boyutu 161 MB;
demo_jlinkimajından biraz büyük. Çünkü uygulamayı gerçekten çalıştırmak için gereken tüm modülleri içerdiğinde JRE yaklaşık 90 MB oluyor.Dockerfile_jlinkiçindekijdepsçağrısı tüm modülleri tespit edemediği için JRE'yi yalnızcajava.baseile oluşturuyordu. Benim minimal JRE'me de yalnızcajava.basekoyarsam JRE boyutu yaklaşık 50 MB oluyor ve bozuk konteyner imajı Podman'a göre 117 MBdockerTools.buildImageçağrısındaki hatalıcopyToRootu da kaldırdım.config.Cmdiçindeki string context tek başına uygulamanın imaja girmesini sağlıyor; mevcut kod uygulamayı bir kez daha kopyalıyordu. AyrıcadockerTools.buildLayeredImagee geçerek her store path'i ayrı bir imaj katmanına koydum; bu, birden fazla konteyner imajı arasında bağımlılıkları paylaşırken alan ölçeklenebilirliği açısından iyi, ancak tek imajlık deneyde etkisi yokGeriye çoğunlukla JRE boyutunu optimize etmek kalıyor. Bir sonraki en büyük bağımlılık yaklaşık 30 MB ile
glibc; bunun nedeni Nixpkgs'in glibc'yi çok sayıda locale ve karakter kodlamasını destekleyecek şekilde derlemesi gibi görünüyor. Bunu ayrı bir derivation ya da output olarak ayırıp seçilebilir hale getirmenin mümkün ya da pratik olup olmadığını bilmiyorum. Birden fazla imajdockerTools.buildLayeredImageile oluşturulursa, aynı Nixpkgs commit'inin kullanıldığı varsayımıyla glibc ve kalan bağımlılıkların tamamı paylaşılırhttps://github.com/max-privatevoid/hackernews-docker-challen...
Nix’i zaten benimsediyseniz harika; Nix veya Guix gibi bildirimsel paket yönetiminin daha yaygınlaşması iyi olurdu.
Zaten Docker kullanıyor ama Nix’i kademeli olarak devreye almak istiyorsanız, bu sunumdaki yaklaşım da var: https://youtu.be/l17oRkhgqHE
Yapılandırmayı ve container build’lerini doğrudan tamamen Nix’e taşımak yerine, Dockerfile’ı koruyup Nix yapılandırmasını build ettirebilirsiniz. En büyük dezavantajı layer’lardan hiç yararlanamaması; avantajı ise Dockerfile’ı kademeli olarak değiştirirken mevcut Docker altyapısını veya otomasyonunu yeniden kullanabilmeniz.
[1] https://mitchellh.com/writing/nix-with-dockerfiles
Ama bu yeniden üretilemezliğin önemli bir kısmı, Docker layer’larından birinin kullanıma açık kalacağının garanti edilmemesinden kaynaklanmıyor mu diye düşünüyorum. Öyleyse Nix’te paket sürümlerinin depoda sonsuza dek kalacağına dair bir garanti olup olmadığını da merak ediyorum.
Konudan bağımsız ama, bu slayt çizimini yapan illüstratör Annie Ruygt, iki YC startup’ı olan RethinkDB (rethinkdb.com) ve Pachyderm’in (pachyderm.io) logo ve marka görsellerini de yapmış.
Pachyderm’de çalışmıştım; Pachyderm de eski RethinkDB mühendislerinin kurduğu bir şirket. İşleri gerçekten çok iyi.
Görece yakın zamanda, altyapı ekibinin önerisiyle Nix kullanarak CI base image’ı build etmeye yarım gün kadar harcadım; image devasa çıktı ve link sorunları yüzünden bazı şeyler çalışmadı.
Özellikle can sıkıcı olan, çok mimarili image oluştururken başka bir mimariye ait bir şeyi gerçekten çalıştırmaya çalışması ve qemu’nun yalnızca donanım sanallaştırmasını desteklemesiydi. Build makinem ve workstation’ım VM olduğu için bu yok;
binfmt-miscise var. arm64mkdir’ı fork/exec edip/tmpoluştursaydı çalışabilirdi; ama Docker layer’ları sonuçta yalnızca tar dosyası olduğundan, aşağıdaki gibi dizin oluşturabilirsiniz:echo "tmp uid=0 gid=0 time=0 mode=0755 type=dir" | bsdtar -cf - @-Bu tam layer’ın bir yerlerde zaten bulunma ihtimali de yüksek; dolayısıyla kullanıcının indirmesine bile gerek kalmayabilir.
Nix’i her denediğimde, birkaç ay daha geçerse düzenli kullanabileceğim hissine kapılıyorum. nixpkgs’te istediğim paketlerin neredeyse hepsi var ve workstation’a sorunsuz kuruluyor. Ama “bash, python, build-essential, Bazel gerekiyor” talebi, bir Docker image builder’ın hedefi gibi görünmüyor. Tek bir Go binary’sini Docker image’ına koymak için Nix’e gerek yok. distroless’i alıp uygulamayı bir tar dosyasına koyarsanız container olur. Ben şahsen Bazel’in
rules_oci’sini kullanıyorum; içeride yaptığı iş de aşağı yukarı bu kadar, yalnızca birkaç mimari için binary build edip image index YAML’ı oluşturarak registry’ye push edecek kadar ek zekâ var.Elbette paketin build dosyasının bunu desteklemesi gerekir. qemu’nun yalnızca donanım sanallaştırmasını desteklediği sözü de doğru görünmüyor. Yalnızca yazılım emülasyonu yapılabilen mimarilerde de qemu kullanılabilir.
Minimal örnek burada ele alınıyor: https://discourse.nixos.org/t/how-do-i-get-a-shell-nix-with-...
pkgCrosskullanmak kadar basit olması gerektiğini söyleyecek değilim, ama olağan süreçte hangi somut sorunla karşılaştığınızı merak ediyorum.https://nix.dev/tutorials/cross-compilation.html
Birkaç projede yıllardır kullandım; ama boyut sorun ise, yazıda bahsedilen yöntemle yalnızca belirttiğiniz şeyleri içeren çok küçük image’lar oluşturabilirsiniz.
[1] https://hub.docker.com/r/nixos/nix/tags
musl bile kullandık; herhangi bir araçla yaptığımızdan daha küçük image’ları CI’da hızlı ve tutarlı biçimde build ettik, cache de iyi çalıştı. Neyin çalıştırıldığını pek anlayamadım.
buildFHSEnvkullanmanız gerekip gerekmediğini merak ediyorum.Nix’in, mevcut sistemlerden parça parça ve yumuşak geçişi anlatan daha fazla yazıya ihtiyacı var gibi görünüyor.
Bir platform mühendisi olarak Nix’i sevmek istiyorum, ama herkes için kolay değil
Geliştirici deneyiminin de hâlâ epey kötü olduğunu düşünüyorum. Örneğin
devbox add python@3.11gibi paket ekleyebildiğim için devbox’ın geliştirici deneyimini daha çok tercih ediyorum120 satırlık bir
flake.nixgörünce tam olarak “daha kolay” demek de zorhttps://github.com/Xe/douglas-adams-quotes/blob/main/flake.n...
Bağlantı verilen flake, bir Go ikilisinin nasıl derleneceğini tanımlıyor; bu ikiliyi giriş noktası olarak kullanan Docker imajını tanımlıyor; ayrıca Go ikilisini çalıştıran bir systemd servisi oluşturan NixOS modülünü de tanımlıyor. Bunun yanında, o NixOS modülünün beklendiği gibi systemd servisi oluşturduğunu doğrulayan bir NixOS testi de içeriyor
NixOS test framework’ü oldukça etkileyici ve test, NixOS’u birlikte çalıştıran bir QEMU VM içinde çalışıyor. Bağlantıdaki yazıyla ilgili olan kısımlar yalnızca Go ikilisi ve Docker imajı tanımı ile çevresindeki boilerplate’in bir bölümü
Ayrıca satırların çoğu inline systemd servis açıklamasıyla 1:1 örtüşüyor, yani hangi sistemi kullanırsanız kullanın ortadan kalkmayacak. Birden fazla sistemi override ile tanımlamanın hoş bir yolu da içinde var
Bu örnek daha çok “önemsiz bir işi büyük ve ciddi bir projede yapar gibi yapalım”a benziyor; tek seferlik ele alınsaydı yaklaşık 40 satıra indirilebilirmiş gibi görünüyor
O ikili ve yapılandırma dosyası, Linux’ta elde edilebilecek “flat pack”e en yakın biçim; bu örnek, ormanı mı ağaçları mı kaçırdığımızı iyi gösteriyor
Guix’te de
guix pack -f dockerdiye kolay ve iyi bir Docker seçeneği varGuix’in, kendi özel dili yerine zaten kullanılan bir dil olan Guile/Scheme’i kullanması gibi bir avantajı da var
[1] https://guix.gnu.org/manual/en/html_node/Invoking-guix-pack....