Docker için Yardımcı Bilgiler

Serkan Bingöl
AWS Certified User Group Turkey
10 min readJan 12, 2019

Merhabalar tekrardan önceki yazılarımızda docker ile ilgili bir çok konuyu örnekleri ile birlikte anlatmaya çalışmıştık. Bu yazımızda daha önceki örneklerimiz içinde kullanmaya fırsat bulamadığımız ama docker kullanarak geliştirdiğimiz alt yapılar için önem seviyesi yüksek olan komutlar üzerinde duracağız. Docker compose file versiyonları ile ilgili genel bilgileri bu link üzerinden takip edebilirsiniz. Bu yeni özellikleri anlatmaya çalışırken, docker secrets, çoklu compose dosyası kullanımı ve healthcheck başlıkları altında 3 ana konuya odaklanacağız.

Docker Secrets Kullanımı

Docker secrets ,docker containerlar içinde kullanılmak istenen veri bloğu tanımlamalarıdır. Bir Dockerfile içine,sunucuda belli bir alana ya da uygulamamızın kaynak koduna saklanmak istenen ve network aracılığı ile paylaşılması sağlanan tüm verileri içerebilir (Örneğin kullanıcı adı, şifre, ssl sertifikası, ssh anahtarı vb…).

Bu kısımda postgre-sql veritabanımızı Docker Swarm kullanarak bir docker servis üzerinden yayına alacağız. Postgre kurulumu için gerekli olan default “kullanıcı adını” sunucu üzerinde bulunan bir txt dosyasından ve “şifresini” uygulamamızın kaynak dosyası üzerinden okuyarak oluşturacağız. Sonrasında kurulum bizim belirlediğimiz kullanıcı adı ve şifreyi kullanarak aynı sunucu üzerinde bulunan “pgAdmin” containerını kullanarak web üzerinden bu veritabanı’na ulaşmayı deneyeceğiz.

Öncelikle $ docker node ls ile 3 adet node’un ayakta olduğunu ve $ docker service ls ile henüz hiçbir servisin yayında olmadığını kontrol edebiliriz.

$ docker node ls ve $ docker service ls

Node 1 üzeinde docker-secrets adlı bir klasör içine generic_user adında bir txt dosyası oluşturuyoruz. Bu dosya içinde “serkanbingol” kullanıcı adını tutuyoruz.

Burada $ cat generic_user.txt komutunu kullanarak txt dosyasının içindeki kullanıcı adını ekrana yazdırabiliriz.

Docker Secrets kullanım amaçlarından birisi de containerlar ile kimlik bilgileri (credentials) arasında soyutlama sağlamaktadır. Key-Value gibi çalışan bu sistemde $ docker secret create [isim] [saklanacak_bilgi] komutu ile gerekli bilgiyi bir referans ismi ataması gerçekleştirerek kripte edilmiş bir vaziyette “Raft logları” arasında tutmaktadır. Biz burada $ docker secret create db_user generic_user.txt komutunu kullanarak db_user referansını belirledik.

$ docker secret create [isim] [saklanacak_bilgi]

Bir başka secret oluşturma biçimi de echo komutu ile oluşturduğumuz “12345” şifremizi docker secret create db_password - komutunu kullanarak db_password referans adı ile kaydediyoruz.

$ echo “12345” | docker secret create db_password -

Burada oluşturduğumuz ve referans olarak kullanacağımız secretlarımızı görüntülemek için $ docker secret ls ve detaylı olarak incelemek için $ docker secret inspect [secret_ismi] komutlarını kullanabiliriz.

$ docker secret ls ve $ docker secret inspect [secret_ismi]

Artık postgre imajını kullanarak bir container çalıştırabiliriz. $ docker service create — name POSTGRE_SQL — secret db_user — secret db_password -e POSTGRES_PASSWORD_FILE=/run/secrets/db_password -e POSTGRES_USER_FILE=/run/secrets/db_user postgres -c ‘listen_addresses=*’ komutunun kullanarak containerımızı docker swarm üzerinde servis yapısı olarak oluşturuyoruz. Bu kısım içinde — secret db_user — secret db_password ile secretlarımız için hangi referans isimlerini kullanacağımızı ve sırası ile e POSTGRES_PASSWORD_FILE=/run/secrets/db_password -e POSTGRES_USER_FILE=/run/secrets/db_user postgres komutları ile ise postgre imajı için kullanıcı adı ve şifre için bu referansların kullanılması gerektiğini belirtmiş oluyoruz.

Bu kısım için dikkat edilmesi gereken yer -c ‘listen_addresses=*’ komutudur. Offical Postgre imajı kendi içindeki Dockerfile ile localhost:5432 adresini dinlemek üzere koşullandırılmıştır. Biz bu komutu kullanarak container çalışma zamanında tüm dışarıdan gelen istekleri dinleyebileceğine dair bir bildirimde bulunuyoruz.

$ docker service create — name POSTGRE_SQL — secret db_user — secret db_password -e POSTGRES_PASSWORD_FILE=/run/secrets/db_password -e POSTGRES_USER_FILE=/run/secrets/db_user postgres -c ‘listen_addresses=*’

İmajlarımızın içine $ docker images komutu ile baktığımız takdirde postgre yi kullamak üzere tasarlanmış pgadmin imajı gözükmemektedir. Web arayüzü sayesinde belirlediğimiz postgre sql veritabanlarını incelemek için kullanılan bir docker container uygulaması olan dpage/pgadmin4 imajını çalıştırmak için $ docker container run -p 80:80 -e “PGADMIN_DEFAULT_EMAIL=user@domain.com” -e “PGADMIN_DEFAULT_PASSWORD=SuperSecret” -d dpage/pgadmin4 komutunu kullanıyoruz. Burada uygulamanın standart kullanıcı adı ve şifresini -“PGADMIN_DEFAULT_EMAIL=user@domain.com” -e “PGADMIN_DEFAULT_PASSWORD=SuperSecret” komutu ile vermiş olmaktayız. Postgre containerımız 5432 portunu dinlediği için $ sudo ufw allow 5432/tcp portuna ve protokolüne izin vermiş oluyoruz.

docker container run -p 80:80 -e “PGADMIN_DEFAULT_EMAIL=user@domain.com” -e “PGADMIN_DEFAULT_PASSWORD=SuperSecret” -d dpage/pgadmin4

Artık Node 1 makinesine ait public ip üzerinden pgAdmin web uygulamasına ulaşmış bulunmaktayız.

Bu kısım için postgre veri tabanımız ile pgadmin web uygulamamız aynı node üzeride yayında olduklarından ve aynı network’ü kullandıklarından dolayı Postgre taskına ait containerımızın private IP ’sini öğrenmek için $ docker container inspect [postgre_container_ismi] komutunu kullanarak uygulamanın IP’sinin 172.17.0.2 olduğunu öğreniyoruz.

Bu bilgiyi ve secretlarımızı oluştururken kullandığımız serkanbingol kullanıcı adı ve 12345 şifresini kullanarak postgre veritabanı uygulamasına bağlanmayı deniyoruz.

Sonuç olarak postgre veritabanına , pgAdmin web arayüzü üzerinden ulaşmayı başarmış bulunmaktayız.

Docker Secrets Kullanım Senaryosu aşamaları :https://1drv.ms/b/s!AskWoAU3NqUug_97-QBnWiHT_kWU-Q

Çoklu Compose Dosyası Kullanımı

Uygulamalarımız için birden fazla compose.yml dosyası planlayarak geliştirme, test ve production ortamları için farklı ayarları farklı şekilde yansıtabiliriz. Bu uygulamada dikkat edilmesi gereken bir durum en temel compose dosyası içinde sadece container imajları barındırıyoruz. Override.yml uzantılı dosyamız, her compose up komutunda aksi belirtilmedikçe temel compose.yml dosyasını ezecektir. Örneğimizi aşağıda kısaca açıklamaya çalışacağız.

Docker compose kullanımı için bir base compose dosyası oluşturuyoruz ( docker-compose.yml ) ve burada sadece imajlarımızın neler olduğunu “services” kırılımı altında belirtiyoruz.

Bir önceki adımda oluşturmuş olduğumuz docker-compose dosyasından kalıtım alarak development ortamımızın ayarlarının yapılacağı dosyamız olan docker-compose.override.yml dosyasının içinde postgre servisi için şifremizi referans vereceğimiz secret dosyalarımızı, drupal için volume alanını ve yayın portu olan 8080 portunu belirtiyoruz.

Test ortamındaki ayarlarımızı barındıran docker-compose.test.yml dosyamızda , geliştirme ortamımızdan farklı olarak volumelarımızı kaldırıyoruz ve dış port olarak drupal uygulamamızın yayın portunu farklı bir port üzerinde konumlandırıyoruz.

En son olarak production ortamımız için docker-compose.prod.yml dosyası ile hem drupal uygulamamız hem postgre uygulamamız için volumelarımızı tekrardan ayarlıyoruz. Bu sayede aslında geliştirme,test ve production ortamları için farklı ayarlarımızın olmasını sağlıyoruz.

Uygulamamızın bulunduğu klasör içinde bir listeleme yaparak tüm yml dosyalarımızı, Dockerfile dosyamızı şifremizin içinde bulunduğu txt dosyamızı ve uygulama dosyalarımızı görüntülüyoruz.

Compose dosyamızı kullanarak tek komut ile tüm containerlarımızı ayaklandırmak için $ docker-compose up -d komutunu kullanarak drupal ve postgre containerlarımızı ayağa kaldırıyoruz.

Ayakta bulunan drupal containerımızı kontrol etmek amaçlı $ docker container inspect [container_ismi] komutunu kullanarak detaylı bir inceleme yaptığımızda docker-compose.yml dosyasında belirtmemiş olsak bile aslında 4 temel volume’un oluştuğunu görebiliyoruz. Burada override uzantısı base compose dosyasını ezerek gerekli ayarlamaları yansıtmış bulunmaktadır.

Docker compose kullanarak tek komutla ayaklandırdığımız sistemi $ docker-compose down ile ortadan kaldırmış bulunmaktayız.

$ docker-compose -f docker-compose.yml -f docker-compose.test.yml up -d komutu ile docker-compose dosyasının ayarlamalarının docker-compose.test dosyası ile ezilerek yeni den yapılması gerektiğini bildiriyoruz.

Test ortamı ayarlamaları için kullanılan docker-compose.test.yml dosyası bir volume içermediği için inspect komutu ile gerekli kontrolleri yaparak volume ayarlamalarının yapılmadığını inceliyoruz.

Production ortamı için ise docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d ile production ayarlamaları ile containerlarımızı kaldırmış bulunuyoruz.

Production ortamında drupal uygulamamız için volume ayarlamaları yapılmıştır. Bunu inspect komutu ile incelediğimizde gerekli ayarlamaların yansıtıldığını görebilmekteyiz.

Çoklu Compose Dosyası Kullanım Senaryosu aşamaları :https://1drv.ms/b/s!AskWoAU3NqUug_96c-E9NH4BSWhWGg

Docker Rolling Update , Healthcheck ve Rollback Kullanımı

Bu kısımda anlatacağımız örneğimizi daha iyi anlamak adına öncelikli olarak healthcheck, Rolling Update ve Rollback kavramlarına değinmemiz gerekecektir. Tanımlamaların üzerine tıklayarak docker offical dökümanlarından daha detaylı bilgilere ulaşabiliriz.

Healthcheck:Servis içinde bulunan container’ ın hala çalışıp çalışmadığını test etmek üzere kullandığımız komut tipidir. Burada 3 ana durum üzerinden gerekli kontroller yapılmaktadır ( starting, healty ve unhealty ).

Deploy - Update_Config: Deploy komutu altında bulunan ve servisin ne gibi koşullar üzerinden update edileceğini belirlediğimiz alt komut tipidir.

Deploy-Rollback_Config: Deploy komutu altında bulunan ve fail olmuş bir servisin ne gibi koşullar üzerinden rollback edileceğini belirlediğimiz alt komut tipidir.

Configs: Non-sensitive verilerin tutulabileceği yada uygulama içindeki container dışından veri alışverişinde bulunabileceği dosyalar için gerekli ayarlamaları barındıran komut tipidir.

Docker hub üzerinde docker tarafından yayınlanan “example-voting-app-vote” uygulamasını ve ilgili Dockerfile ‘ ı indirerek üzerine RUN apk update && apk add --no-cache apache2-utils curl komutunu dahil ediyoruz. Bu kısımda yapmak istediğimiz alpine sürümünde bulunmayan ve bizim stack.yml dosyasında kullanmak istediğimiz curl CLI uygulamasını containerımızın içine dahil etmek. Aynı işlemleri “example-voting-app-result” uygulaması içinde gerçekleştirmemiz gerekmektedir. Oluşturmuş olduğumuz yeni Dockerfile üzerinden ilgili klasör içinde $ docker build -t srknbngl/vote_app komutunu kullanarak yeni imajımızı oluşturmuş oluyoruz.

Oluşturmuş olduğumuz yeni imajı docker registry’e göndermek için $ docker image push srknbngl/vote_app komutunu kullanıyoruz.

Tüm imajlarımız için (vote_app , result_app ve worker_app) bu işlemleri yaptıktan sonra ilgili imajlara bu link üzerinden ulaşabilirsiniz.Aşağıdaki resimden tüm imajların docker registry’e gönderildiğini takip edebilirsiniz.

Artık stack compose dosyası olarak kullanacağımız example-voting-app-stack.yml dosyasını kurgulamaya başlayabiliriz. Daha önceki docker-stack yazımızda bahsettiğimiz üzere servis, network, volume ve genel ayarlamalarımızı bu dosya üzerinde nasıl oluşturacağımıza değinmiştik.Bu örnek üzerinde Redis ve Postgre servislerimiz aynı kurguda tasarlandığı için tek örnek üzerinden gerekli ayarlamaları anlatmaya çalışacağım. Configs sekmesinde belirlediğimiz redis uygulamamıza ait olan redis-healthcheck dosyasındaki komutları çalıştırdığımız takdirde redis cli üzerinden bir ping işlemi gerçekleştiriyoruz.

Compose dosyamız içinde redis servisinde healthcheck alanı altında test:[“CMD”,”redis-healthcheck”] komutu ile configs alanında redis için referans olarak belirlenen dosyanın içindeki komutları çalıştırıyoruz. interval: 5s ile bu test işleminin container çalıştıktan 5 saniye sonra gerçekleştirileceğini, timeout: 5s ile bu test işlemin tamamlanması için maksimum 5 saniye süreli izin verildiğini, retries:3 ile bu işlemin gerçekleşmemesi durumunda containera unhealty durumu atanmadan maksimum 3 kez denenmesi gerektiğini, start_period: 60s ile ise containerın çalışmasının 60 saniyede hazır olacağını dolayısı ile bu saniyeler arasındaki başarısız denemelerin maksimum 3 olan hata sayımızdan düşmemesi gerektiğini tanımlamış olmaktayız. Ayrıca update-config altındaki failure_action: rollback ile update işleminde bir sıkıntı ile karşılaşır isek bu işlemi bir rollback ile geri alacağımızı belirtmiş oluyoruz.

Bu kısımda “vote” ve “result” uygulamalarımız üzerinde , “redis” ve “postgre” uygulamalarımız için kullandığımız aynı ayarları kullanıyor olacağız. Aşağıdaki resim üzerinden bu ayarları takip edebiliriz.

Worker uygulamamız içinde gerekli ayarlamaları YAML dosyasının içine kaydederek stack kullanımı için gerekli “example-voting-app-stack.yml“ dosyamızı oluşturmuş olmaktayız.

Bu kısıma kadar oluşturmuş olduğumuz “example-voting-app-stack.yml“ dosyasının tamamını bu link üzerinden indirebilirsiniz. $ docker stack deploy -c example-voting-app-stack.yml vote_stack komutu ile ayarlamalarını yaptığımız tüm uygulamaları tek compose dosyası ile ayağa kaldırmış olacağız.

Tüm servislerimizi ayağa kaldırdıktan sonra $ docker service ls komutu ile servislerimizdeki son durumu inceleyebiliriz. Gerekir ise $ docker service ps [servis_ismi] gibi bir komut yardımı ile servislerin içindeki taskları görüntüleyebiliriz.

Buradaki senaryomuzu incelemek adına öncelikli olarak vote_stack olarak isimlendirdiğimiz sistemimiz içindeki tüm taskları bir görüntülemek adına $ docker stack ps vote_stack komutu ile toplamda 7 adet taskımızın (2 worker , 2 vote ,1 result , 1 db ve 1 adet redis) hepsinin running durumunda olması gerektiğini (desired state) fakat db ve redis servilerimiz hariç diğer 5 taskın running olduğunu görebiliyoruz (current state). Bu iki servise ait containerlar’ın healthcheck ayarlarında 60 ar saniye bekleme süresi olduğunu belirttiğimiz için hala starting durumunda olduğunu görmekteyiz.

Çalışan sistemimiz hakkında genel bilgi almak için $ watch stack ps vote_stack komutu ile her 2 saniyede bir durum değişikliklerini monitör edebileceğimiz ekranda değişiklikleri takip edebilmekteyiz. Burada db ve redis servislerimizin tasklerinin 1 dakika sonra çalışmadıklarından dolayı shutdown durumuna çekildiklerini görmekteyiz. Ve compose dosyamızda belirtildiği üzere bir failure durumunda bu güncellemenin rollback işlemi ile geri alındığını takip edebilmekteyiz.

Bir yazımızın daha sonuna geldiğimizde artık docker ortamında geliştirme, test yada production ortamlarımızda güncelleştirmelerimizi ayrı ayrı compose dosyaları üzerinden yapabileceğimiz, bu güncellemeler sırasında downtime ‘ı nasıl daha kısaltabileceğimiz ve herhangi bir aksaklık durumunda bir önceki sürüme nasıl geri dönüş sağlayabileceğimiz gibi konularda genel bir kaç deneme yapmış bulunmaktayız.

Bir daha ki yazımızda görüşmek dileği ile…

Vote-App Stack Healthcheck Senaryosu aşamaları :https://1drv.ms/b/s!AskWoAU3NqUug_95MikgSN5xKKUTyA

--

--

Serkan Bingöl
AWS Certified User Group Turkey

Muzur bir oğlan babası, hayvan sever, Harry Potter hayranı, bazen maceracı düz yazılımcı.