Bu yazımda Work with remote images registries - retrieving information, images, signing content sloganlı Skopeo aracı üzerine konuşmak istiyorum.

Yakın zamanda Gitlab Container Registry ve Nexus gibi ortamlarda tutulan çeşitli container imajları üzerinde işlem yapmam gerekti, kopyalama, taşıma, silme gibi. Kopyalama gibi işlemleri genelde bilgisayarıma çekip, hedef registry’ye push etme şeklinde yapıyordum. Bu sefer işlem yapmam gereken imajlar sıkıştırılmış halleri 50-60 GB, açılmış halleri de 110 GB olan büyük imajlardı. Bu sefer Daha hızlı ve akıllıca yapabilir miyim? diye araştırırken Skopeo’yu buldum. Bu yazıda deneyimlerimi aktaracağım.

Bu kadar büyük imajlar nasıl oluyor?

Merak edenler için bahsettiğim imajlar ağırlıklı olarak Embedded Box, EBox projesi ile oluşturulmuş AMD/Xilinx ISE, Vivado, Vitis, PetaLinux imajları. Bu tarz araçlar gerçekten büyük yer kaplıyor.

Kurulum

Debian ve Ubuntu temelli Linux dağıtımlarında apt install skopeo şeklinde kurulabiliyor. Windows tarafını bilmiyorum. Linux dağtımınızın sürümüne göre kurulan versiyon değişecektir ama benim basit kullanımımım için Ubuntu 22.04, Debian 12 ve 13’teki varsayılan sürümler işime yaradı.

Kopyalama

Temel kullanım amacım Gitlab Container Registry içerisinde kopyalama yapmak oldu. Temel kullanımına bakalım:

skopeo --copy all docker://<source> docker://<destination>

Buradaki docker kısmı kafanızı karıştırmasın. Bilgisayarınızda Docker yoksa bile, ya da normalde sudo ile çalıştırmanız gerekse bile, Skopeo çalışacaktır. Buradaki docker:// kısmı bir protokol belirtiyor aslında.

Kaynak yani source URL Gitlab Container Registry’den pull ederken kullandığınız URL. destination ise istediğiniz hedef URL, bunun karşılığı Container Registry’de olmayabilir, yaratılacaktır.

Kopyalama yaptıktan sonra Gitlab üzerinde de her iki imajın Digest SHA256 sum değerini aynı görmeniz lazım. Sonra isterseniz skopeo inspect ile de bakabilirsiniz.

Giriş Yapma

Gitlab Container Registry’ye login olmanız gerekiyorsa Personal Access Token (PAT) kullanmanızı öneriyorum. read_registry ve write_registry hakları olan bir token yeterli olmaktadır. Genel kural olarak bunu süreli yaratmanızı öneririm. Örneğin birkaç gün taşıma işlemi yapacaksanız 1 haftalık bir token yaratabilirsiniz. Giriş yapmak için

skopeo login <gitlab registry URL>

kullanabilirsiniz.

Burada interaktif olarak kullanıcı adı ve şifre soracaktır. PAT kullanırken kullanıcı adını rastgele bir şey yazabilirsiniz. Şifre kısmına da Gitlab’tan aldığınız PAT’ı girmelisiniz.


skopeo login olmadan işlemlerinizi skopeo copy --creds=testuser:testpassword gibi tek seferlik işlemler ile de yapabilirsiniz. Eğer expire olan bir token oluşturamıyorsanız, mesela Nexus registry’de başınıza gelebilir, çalıştığınız bilgisayarda giriş bilgilerinizi kayıtlı unutma riskine karşın hiç login olmadan da bu şekilde işlem yapabilirsiniz.

BASH geçmiş kaydetmeyi kapatma

Eğer vereceğiniz komutlarda giriş bilgileri gibi kritik bilgiler olacaksa bunun öncesinde BASH’in (ya da hangi shell’i kullanıyorsanız) history dosyasına komutlarınızı kaydetmesini kapatmanızı şiddetle öneririm.

Bunun için BASH’te:

export HISTCONTROL=ignoreboth
skopeo <op> --creds=testuser:testpassword <...>

veya

set +o history     # history kaydını durdur
skopeo <op> --creds=testuser:testpassword <...>
set -o history     # history kaydını devam ettir

kullanabilirsiniz. Başka bir shell kullanıyorsanız onun komutlarını kullanmanız gerekecektir.

Bunu atlama ihtimalinize karşın üşenmeyip eğer kullanabiliyorsanız süreli dolan (expire olan), süresi çok uzun verilmemiş PAT benzeri token kullanmanız her zaman daha iyi olacaktır. En azından bunu unutsanız ve history dosyanız çalınsa bile hesabınızı çaldırdığınız süre sınırlı olur…

Giriş yaptıktan sonra işlemlerinizi yapabilirsiniz.

Diğer İşlemler ve Nexus

copy dışında Skopeo’nun delete ve inspect komutlarını da kullandım, onlarda da bir problem yaşamadım. Ayrıca Nexus hosted docker registry’de de düzgün çalıştığını gözlemledim. Karmaşık bir kullanım senaryom olmadı.

Hayaller ve Gerçekler 🫤

Amacım Gitlab Container Registry’de büyük imajları taşımaktı. Beklentim ise aynı Gitlab instance’ında kopyalamanın akıllıca yapılmasıydı. Container layer’larını doğrudan yeni adrese mount etmesini beklerdim fakat Gitlab Container Registry tam olarak beklediğim gibi davranmadı. Bunun sebebi çalıştığım Gitlab sunucusunun konfigürasyonu olabilir ya da bir şeyleri eksik yapmış olabilirim. Gözlemim şu şekilde:

Gitlab’ta bir projenin altında Deploy → Container Registry şeklinde birden fazla registry olabiliyor. Bunu URL’den de anlayabilirsiniz. URL’de registry id kısmını en sonunda bir sayı olarak görüyorsunuz, mesela 42 gibi. Eğer kopyalama yapılan kaynak ve hedef aynı ID’li registry içererisinde ise kopyalama anlık oluyor, Gitlab otomatik olarak yeni container’a layerlerı taşıyor. Bu aslında aynı imaja birden fazla tag vermekle eşdeğer mesela imaj:latest vardı aynı registry içerisinde bunu imaj:v1 olarak tag’lediğiniz zaman bu işlem anlık oluyor. Fakat aynı proje altında olsa bile ID’si farklı bir registry’ye taşırsanız Skopeo’nun tüm katmanları lokal’e çekip tekrar push etmesi gerekti. Bu asında docker pull sonra docker tag ve docker push yapmak ile kabaca aynı süre alıyor. Ama hala Skopeo kullanımı anlamlı olabilir çünkü imajı bilgisayarınızda tutmuyorsunuz bir de görebildiğim kadarıyla diske indirip tekrar push etmiyor. Yani imajınız 100 GB ise önce diskinizde 100 GB harcayıp sonra geri vermiyor, doğrudan indirip belki birkaç MB buffer alanı harcaypı hedefe koyuyor yani hala avantajlı.

Sonuç

Gitlab Container Registry’de kopyalama işlemleri için beklediğim kolaylığı bulamadım, tüm layerların indirilmesi gerekti. Bunu Gitlab’ın iç yapısından kaynaklı bir durum olarak değerlendiriyorum. Yine de remote container registry’de veya iki registry arası işlem yapılacaksa Skopeo kullanmak mantıklı.

1️⃣ User olarak sudo ile Docker vs kullanmadan işlem yapabiliyorsunuz.

2️⃣ Gözlemlediğim kadarıyla kopyalama sırasında eğer imajın indirilmesi gerekiyorsa indirilirken aynı anda yükleniyor, diskinizi doldurmuyor.

3️⃣ Kopyalama sırasında doğrudan remote’ta layer’lar kopyalanabilecekse Skopeo bunu yapıyor, bilgisayarınıza imajı indirip tekrar yüklemiyor. Böyle bir durumda imajınız saniyeler içerisinde kopyalanmış oluyor. Bu imkan yoksa mecburen ağ bağlantı hızınıza göre arka planda indirme/yükleme işlemi yapılıyor.

4️⃣ inspect gibi komutlar imajı indirmeden doğrudan bilgi almak için faydalı oluyor.


Alternatif olarak docker buildx imagetools create gibi araçlar da kullanılabilir ama denemediğim için bir yorum/karşılaştırma yapamayacağım.