Docker Registry Kurulumu ve SSL/TLS Aktivasyonu

Docker Registry, Docker image’leri depolayan ve dağıtmanıza olanak tanıyan, durum bilgisi olmayan, yüksek düzeyde ölçeklenebilir bir sunucu tarafı uygulamasıdır. Docker private / local registry ile imageleri kendi sunucunuzda depolayabilir, erişimi kısıtlayabilir ve internet band genişliğinizi rahatlatabilirsiniz.

Local/Private Docker Registry kullanarak şu imkanlara sahip olabilirsiniz;

  • İnternet erişimi olmayan ortamlarda istemcilerinizin kullanabilmesi için bir local docker repository oluşturabilirsiniz.
  • Registry’e parola ayarlayarak sadece yetkilendirilmiş kullanıcıların erişebilmesini sağlayabilirsiniz.
  • Sadece dilediğiniz image’leri yükleyerek belirli ortamlara özel registry’ler oluşturabilirsiniz.
  • Registry’i dilediğiniz yere taşıyabilirsiniz (internetsiz bir ortam gibi)

Öyleyse hemen kuruluma başlayalım. Docker local registry kurulumunu Centos 8 ortamına yapacağız. Siz OS seçimini özgürce yapabilirsiniz.

1. Local Docker Registry Kurulumu

İlk olarak Docker registry kurulumunu yapacağımız cihazda registry:2 image’ini run ederek local image’lerimiz arasına indiriyoruz ve aşağıdaki parametrelerle çalıştırıyoruz.

docker run -d -p 5000:5000 --restart=always --name registry registry:2

Docker run

Docker run komutu, pull komutunu da içerir. Önce pull edip ardından run etmek yerine tek seferde run komutu kullanarak daha pratik bir kullanım elde edersiniz.

Container çalışmaya başladığında tarayıcımızdan kurulumu yaptığımız cihazın ip adresi ile http://[IPADRESI]:5000/v2/_catalog adresine giderek registry’i kontrol edebilirsiniz. Buradaki 5000 portu, containerı ayağa kaldırırken map ettiğimiz porttur. Dilediğiniz şekilde değiştirebilirsiniz.

Docker Registry sayfası

Adreste gördüğünüz gibi private local registry artık hazır ve içi boş. Bu Docker Registry’i ilerleyen başlıklarda dolduracağız.

NOT: Docker registry local servera kurulmuş olsa da push veya pull etmeye çalıştığımızda hata verecektir. Önce hatayı yaratalım ve sebebi ile çözümünü açıklayalım.

2. Docker Registry Push ve Pull İşlemleri

Docker registry kurulum işlemini tamamladıktan sonra hemen ilk image’imizi local registry’imize push etmeye çalışalım. Bunun için push edeceğimiz image’e ilk olarak tag vermemiz gerekiyor.  Aksi halde kendi registry’imize push etmek yerine Docher Hub‘a push etmiş oluruz. Çünkü docker push kodunun default davranışı budur.

Localimize örnekte kullanmak için alpine image’ini pull edelim. İndirme işleminden sonradocker images komutu ile tüm image’leri görelim.

docker pull alpine
docker images
docker images komutu

Ardından kendi registry’imize push etmek için tag verme işlemini yapacağız. Tag formatı ise [IPADRESI]:[PORT]/[IMAGE ADI]:[TAG] şeklinde olmalıdır. Böylece push komutunu kullandığımızda image’i belirttiğimiz ip adresi ve portta yer alan Docker Regitry’e push etmiş olacak.

docker tag alpine 192.168.1.11:5000/alpine:latest
docker tag komutu

Artık image’imiz push etmeye hazır. Öyleyse hadi push edelim:

docker push 192.168.1.11:5000/alpine:latest 
Centos docker push komutu
Windows docker push komutu

Evet, bahsettiğimiz hataya geldik. Docker push ve pull komutları HTTPS üzerinden iletişim kurduğu ve bizimde aktif bir SSL/TLS sertifikamız olmadığı için resimdeki hatayı aldık. Zaten hata mesajının başındaki Get “https://… kısmında da durum açıkça gözüküyor. Öyleyse hemen bu sorunu çözelim.

Yukarıdaki hatayı çözmek için iki yöntemimiz mevcut;

  1. Client üzerindeki docker konfigürasyonunda güvenli olmayan bağlantılara yani HTTP üzerinden haberleşmeye izin vermek.
  2. Docker registry kurduğumuz sunucuya SSL/TLS sertifikası kurmak ve registry container’ımıza bu sertifikayı eklemek.

Her iki yönteme de tek tek bakalım.

2.1 Docker Registry Güvenli Olmayan Bağlantılara İzin Vermek

Docker Registry Güvenli Olmayan Bağlantılar

Bu başlıkta anlatılan yöntemi kullanmanızı tavsiye etmiyoruz. Registry sunucunuz ile aranızdaki güvensiz bağlantı man-in-the-middle saldırılarına açıktır ve verileriniz tehdit altında olabilir.

Docker Registry’e yapılacak olan bağlantı ve istekler default olarak HTTPS üzerinden yapılır. Fakat sunucunuzda SSL/TLS sertifikası mevcut değilse push ve pull komutu çalıştıracak istemcilerin Docker konfigürasyonunda güvensiz bağlantılara izin vermemiz gerekir.

Docker Registry güvensiz bağlantılara Windows üzerinde izin vermek için Docker Client programına giriniz ve Ayarlar sayfasından Docker Engine sekmesine gelerek konfigürasyonun sonuna aşağıdaki parametreyi ekleyiniz. IP adresini ve portunu Docker Registry kurduğunuz cihazın IP adresi ve portuyla değiştirip kaydediniz ve Docker servisini yeniden başlatınız.:

"insecure-registries" : ["IPADRESI:PORT"]
Docker konfigürasyon sayfası

Tekrar deneyelim.

Windows docker komutu

Tebrikler! Windows tarafını hallettik. Şimdi de Docker Registry sunucusuna güvensiz bağlantılara Centos istemcide izin verelim. Bunun için /etc/docker/ dizininde daemon.json isimli bir dosya oluşturalım ve vim/nano gibi bir editörle dosyayı açalım. Dosyaya aşağıdaki içeriği ekleyelim ve kendi IP adresimiz ve portumuzla değiştirelim.

{
  "insecure-registries" : ["IPADRESI:PORT"]
}
Centos docker konfigürasyonu

Ardından docker servisimizi restart edelim.

systemctl restart docker

Hemen teste geçelim.

Centos docker push komutu

Tekrardan tebrikler! Artık Docker private / local registry’inizi özgürce kullanabilirsiniz.

2.2 Self-Signed Sertifikalar İle Docker Registry Sunucusuna SSL/TLS Eklemek

Bir önceki başlıkta yer alan yöntemin aksine Docker Registry sunucunuza SSL/TLS sertifikası ekleyerek bağlantılarınızın HTTPS üzerinden yapılmasını sağlayabilirsiniz.

Eğer sunucunuz bir domaine bağlıysa direkt CA (Certificate Authorites) üzerinden bu domaine geçerli bir sertifika alabilir ve güvenli bir bağlantı ile iletişim kurabilirsiniz. Fakat bir domaine sahip olsanız bile CA’ya ücret ödemeden domaininizi Self Signed sertifikalar ile imzalayabilirsiniz.

Sunucunuz eğer domaine bağlı değil ve sadece IP adresi ile bağlantı kuruyorsunuz mecbur olarak  Self Signed sertifika kullanmanız gerekecek. Çünkü CA’lar sadece DNS üzerindeki domainleri imzalayabilir, IP adreslerini sertifikalandıramaz. Fakat IP adreslerini Self Signed sertifikalar ile imzalayabiliriz.

Self Signed Sertifikalar

Self Signed Sertifikalar, kendinden imzalı sertifikalardır. Kayıtlı bir dijital sertifika otoritesi yerine bizzat sertifikayı üreten tarafından imzalanmıştır. Bu nedenle imzalayanın güvenilirliğini teyit etmenin mümkün olmadığı, kendisinin güvenilirliği de teyit edilemeyen dijital sertifika çeşididir.

Self Signed Sertifika Kurulumu

Self signed sertifika oluşturabilmek için OpenSSL kullanacağız. Bunun için CentOS’ta bulunduğumuz dizinde (örnekte işlemleri registrycerts isimli dizinde gerçekleştireceğim) config isimli dosya oluşturalım ve vim/nano editör ile açalım. Ardından aşağıdaki satırları içine ekleyerek kendinize göre düzenleyiniz.

[req]
default_bits = 4096
default_md = sha256
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = TR
ST = AN
L = ANKARA
O = Kerteriz
OU = Blog
CN = 192.168.1.11

emailAddress = bilgi@kerteriz.net
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]

DNS.1 = kerteriz-dockerregistry.net
IP.1 = 192.168.1.11

DNS alanını IP adresi yerine domain kullanacaksanız ekleyebilirsiniz.  Aksi halde yazmasanız da olur. Ek olarak CN ve IP alanı ise Docker Registry’nin kurulu olduğu cihazımızın IP adresi olmalıdır.

config dosyası konumu ve içeriği

Dosyamız artık hazır olduğuna göre aşağıdaki openssl komutu registrycerts  dizininde çalıştıralım ve imzalarımızı oluşturalım.

openssl req -new -nodes -x509 -days 365 -keyout domain.key -out domain.crt -config config
imza oluşturma

Artık sertifikamızı elde ettik. Önceki çalışan registry container’ını durdurup siliniz ve aşağıdaki komutlar ile sertifikalarımızı da belirterek image’i yeniden çalıştırınız.

docker run -d -p 5000:5000 --restart=always --name registry \
-v /home/dataserver/registrycerts:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key registry:2

Bu komuttaki mount ettiğimiz dizin daha yeni oluşturduğumuz imzaların olduğu dizin (registrycerts ) olmalıdır. Container çalıştıktan sonra  https://[IPADRESI]:5000/v2/_catalog adresini hem Windows hem CentOS cihazda ziyaret edelim.

Windows Docker registry sayfası
CentOS registry sayfası

Kısmen bravo! HTTPS bağlantısı ile Docker registry sayfamıza ulaştık fakat tarayıcımız sertifikanın güvenli olmadığını söylüyor. Şimdilik  görüntülemeye devam et diyerek _catalog sayfamıza bakalım ama birazdan bunu da düzeltmiş olacağız.

Docker registry HTTPS bağlantısı

Sorunu düzeltmeden önce birde docker push ve pull komutu deneyelim.

Windows docker push komutu
CentOS docker push komutu

Artık yeni bir hatayla karşı karşıyayız. Hata metnimiz ise “x509: certificate signed by unknown authority”. Hatanın sebebi tarayıcıda gördüğümüz hata ile aynı sebepten kaynaklanıyor. Çünkü Self-signed sertifikalar tanınan CA’lar tarafından imzalanmadığı için işletim sistemlerindeki Trusted Root Certification Authorities tarafından tanınmaz ve güvenilmez. Çözüm olarak ise bu sertifakaları OS ve docker servisimize tanıtacağız.

2.2.1 Windows – Self Signed Sertifikaların Os ve Docker Servisine Eklenmesi

Yukarıda gördüğünüz  “x509: certificate signed by unknown authority”  hatasını OS ve Docker tarafında çözerek pull ve push komutlarımızı çalışır hale getireceğiz.

Sorunu Windows tarafında çözebilmek için Docker Registry adresine giderek tarayıcıdaki güvenlik simgesine ve ardından Certificate yazısına tıklayınız. Açılan pencerede Details sekmesine eliniz ve Copy to File butonuna tıklayarak Next butonlarıyla sonuna kadar ilerleyiniz. Ardından sertifikayı dışarı aktarınız. Aşağıdaki gif ile nasıl yapacağınızı görebilirsiniz.

Server sertifikasının dışarı aktarılması

Windows Başlat menüsünden Manage User Certificates (certmgr) ayarlarına gidiniz. Açılan pencereden Trusted Root Certification Authorites ayarının altında yer alan Certificates‘e sağ tıklayınız ve All Tasks menüsündeki Import‘a tıklayınız.

Açılan pencereden kaydettiğiniz sertifikayı seçerek import ediniz. Aşağıdaki gif ile nasıl yapıldığını izleyebilirsiniz.

Server sertifikasının içe aktarılması

Bu işlemlerin geçerli olabilmesi bilgisayarınızı yeniden başlatınız. Kontrol için tekrar sayfamıza giriş yapalım.

Güvenilir sertifika

Bravo! Windows artık sertifikamıza güveniyor ve güvenli olarak işaretliyor. Şimdi ise Docker pull ve push işlemini kontrol edelim.

Windows docker push komutu

Çok iyi gidiyoruz. Artık CentOS tarafında nasıl çözeceğimizi görelim.

2.2.2 CentOS – Self Signed Sertifikaların Os ve Docker Servisine Eklenmesi

Aynı sorunu CentOS tarafında da çözebilmek için iki işlem gerçekleştireceğiz. İlki CentOS için OS seviyesinde bu sertifikayı eklemek, ikincisi Docker servisine ilgili sertifikayı eklemek. İlk olarak Docker servisine oluşturduğumuz sertifikayı ekleyelim. Bunun için aşağıdaki komuttaki ip adresini ve portu düzenleyerek çalıştırınız ve ilgili dizini oluşturunuz. Ardından domain.crt dosyasını bu dizine kopyalayıp docker servisini restart ediniz.

mkdir -p /etc/docker/certs.d/ip_address:5000
cp domain.crt /etc/docker/certs.d/ip_address:5000
systemctl restart docker
CentOS docker servisine sertifika eklenmesi

Şimdi push komutumuzu tekrar deneyelim.

Centos docker push komutu

CentOS için OS seviyesinde oluşturduğumuz sertifikayı Trusted Authorities’e eklemek için ise aşağıdaki iki basit komutu uygulamanız yeterlidir.

cp domain.crt /usr/local/share/ca-certificates/ca.crt
cp domain.crt /etc/pki/ca-trust/source/anchors/
update-ca-trust

2.3 Docker Registry Erişimini Parola İle Kısıtlama

Kurduğumuz Docker Local Registry’nin public olmasını istemiyor ve push/pull işlemlerini kısıtlamak gibi bir düşünceniz varsa Basic Authentication ile bunu yapabiliriz. Daha önceki HTTP Authentication methodlarında anlattığımız bir yöntem olan Basic Auth. burada işe yarayacak.

Erişim kısıtlamasına ulaşmanın en basit yolu, temel kimlik doğrulamadır [Basic Authentication] (bu, diğer web sunucularının temel kimlik doğrulama mekanizmasına çok benzer). Bu örnek, secret’ları depolamak için htpasswd kullanan yerel temel kimlik doğrulamasını kullanır.

Centos makinede ilk olarak test kullanıcısı için testuser kullanıcı adı ve testpassword parolası ile tek girişli bir şifre dosyası oluşturalım:

mkdir auth
docker run \
  --entrypoint htpasswd \
  httpd:2 -Bbn testuser testpassword > auth/htpasswd

Windows’ta çıktı dosyasının doğru şekilde kodlandığından emin olmak için yukarıdakini değil, aşağıdaki kodu kullanın.

docker run --rm --entrypoint htpasswd httpd:2 -Bbn testuser testpassword | Set-Content -Encoding ASCII auth/htpasswd

Eski çalışan registry container’ini durdurunuz.

docker container stop registry

Registry’i temel kimlik doğrulama ile başlatalım.

docker run -d \
  -p 5000:5000 \
  --restart=always \
  --name registry \
  -v "$(pwd)"/auth:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -v "$(pwd)"/registrycerts:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  registry:2

Registry’den bir image pull ve push tmeyi deneyin. Bu komutlar başarısız olur.

Docker push komutu

Kimlik doğrulamasından geçerek hatayı çözmek için önce login olmamız gerekiyor.

Docker login komutu

Artık push ve pull komutlarını başarıyla gerçekleştirebilirsiniz.

2.4 Docker Registry Storage Alanını Değiştirme

Docker Registry oluşturduğunuzda image’leriniz container’in içinde depolanır ve bu container silindiğinde registry’e şimdiye kadar push ettiğiniz tüm image’ler de silinmiş olur. Bunun önüne geçebilmek için Registry’e özel bir depolama alanı mount edeceğiz. Mount edebilmek için özel bir NAS veya HDD/SSD disk alanı verebilirsiniz. Karar tamamen sizin.

Örnekte CentOS /mnt/registry dizinimi container’in içindeki /var/lib/registry/ dizinine mount edeceğiz.

docker run -d \
  -p 5000:5000 \
  --restart=always \
  --name registry \
  -v /mnt/registry:/var/lib/registry \
  registry:2

Artık tüm imageleri bu dizin altında görebiliriz.

2.5 Docker Registry Default Port Değiştirme

Docker registry kurduktan sonra container içindeki default port 5000 olarak gelir. Siz port mappingte container’ın içindeki 5000 portunu map eden kısmı dilediğinizce değiştirebilirsiniz (Ör: -p 8000:5000). Fakat container’ın içindeki portu değiştirmek isterseniz ne yapacaksanız?

Docker registry container içindeki default 5000 portu değiştirmek için REGISTRY_HTTP_ADDR parametresini kullanıyoruz. Böylece sadece dışarıya map ettiğiniz portu değil, aynı zamanda container içindeki portu da değiştirmiş olursunuz.

docker run -d \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:5001 \
  -p 5001:5001 \
  --name registry-test \
  registry:2

3. SONUÇ

Docker Registry kurulumuna ait tüm detayları detaylıca ve örnekleriyle sizlere sunduk. Takıldığınız yerler ve sorularınız için aşağıdaki yorum kutusunu kullanabilirsiniz. İyi bloglar.

Docker serimizin sıradaki yazısı için aşağıdaki bağlantıyla devam edebilirsiniz.

Docker Volume ve Bind Mount Nedir? Farkları Nelerdir?
Docker volume ve bind mount yöntemlerini kullanarak container içindeki verilerinizi kalıcı hale getirebilirsiniz.