Docker Multistage Build Örneği: Caddy Web Sunucusunun Dockerlaştırılması

Docker’ın şu an(Haziran 2017) sadece son birkaç CE Edge sürümünde yer alan (Güncelleme) 17.06 CE’den itibaren stabil olarak açıklanan multistage build özelliği, imaj boyutlarının küçülmesi ve build işleminin kısalması/optimizasyonu için kolaylık  sağlıyor. Bu yazıda, Caddy Web sunucusunun Docker imajını, eski ve yeni yöntemler ile gerçekleştirip, multistage build kavramını karşılaştırmalı olarak inceleyeceğiz.

1. Giriş

Caddy Web sunucusu, Go diliyle yazılan, TLS aktif olarak gelen, Let’s Encrypt üzerinden sertifikası olmayan alan adları için otomatik sertifika alan, HTTP/2 desteği direkt olarak aktif ve şu anlık (Haziran 2017) deneysel QUIC desteği ile oldukça ilgi çekici bir Web sunucusu. Caddy aynı zamanda Apache-2.0 lisansına sahip.

Continue reading Docker Multistage Build Örneği: Caddy Web Sunucusunun Dockerlaştırılması

WordPress + MySQL with Isolated Network Deployment in 30 Seconds with Docker Swarm Mode

WordPress is using as a blog CMS for a long time. As a result, it is a huge project and it can be classified as monolithic WEB application. Due to this reason, its deployment could be a little bit different than new fashion deployments with microservices. In this post, we will see how to deploy a WordPress application with a brand new MySQL server(actually, we will use MariaDB) and a proxy in front of them. There are some network configuration which allows us the change of restricting access to database engine outside the system and even inside the system, only WordPress containers can reach the database. Continue reading WordPress + MySQL with Isolated Network Deployment in 30 Seconds with Docker Swarm Mode

Traefik Proxy Temelleri

Bu yazıda, mikroservisler özelinde hazırlanmış olan Traefik ters vekil sunucunun temel kavramlarından bahsedeceğim. Traefik, Docker, Mesos, Consul, Kubernetes gibi birçok altyapı ile birlikte çalışabilen ve dinamik olarak servis ekleme/çıkarma olanağına sahip olarak tasarlanmış; yük dengeleme(load balancing) ve healthcheck işlemlerini gerçekleştirebilen, kendi tanımıyla bir modern HTTP ters vekil sunucusu ve yük dengeleyici olarak mikroservislerde işimizi kolaylaştırıyor. Benzer çözümlere göre baktığımızda şu an açık ara ilerde olduğunu söyleyebilirim(Haziran 2017). Continue reading Traefik Proxy Temelleri

Docker Swarm, Telegraf, InfluxDB, Grafana ile Metrik İzleme (MQTT Örneğiyle)

Bu yazıda sunucuların, servislerin yada çok farklı gözükse de aslında yakın olan sensörlerin verilerini canlı olarak takip edip görselleştirmeye, görselleştirmeleri de özelleştirmeye olanak sağlayan birkaç teknolojiden bahsedeceğiz. Kullanacağımız teknolojiler isim olarak Telegraf ile metrik toplama, InfluxDB ile zaman serisi veritabanında depolama, Grafana ile görselleştirme ve bu işlemleri Docker Swarm Modu üzerinden gerçekleştirmeyi içeriyor. Örnek olarak sunucunun işlemci ve hafıza kullanımıyla alakalı birkaç veriyi ve rastgele üretip MQTT’den göndereceğimiz verileri nasıl görselleştireceğimize bakacağız. Benzer şekilde Nginx, HAProxy, Graylog, Kubernetes, Docker, MySQL, MongoDB, Redis, Apache, RabbitMQ gibi yaygın kullanılan birçok servis hakkındaki kullanım bilgilerini toplayabilir, istediğimiz sürede saklayabilir ve görselleştirme/analiz yapabilir ve istediğimiz durumlarda uyarı oluşturabiliyoruz. İstediğimiz servis desteklenenler arasında olmasa ya da kendi yazdığımız bir servis olsa bile herhangi bir programlama dilinde yazacağımız ufak bir kod ile istediğimiz metrikleri Telegraf’a TCP üzerinden gönderebiliriz. Continue reading Docker Swarm, Telegraf, InfluxDB, Grafana ile Metrik İzleme (MQTT Örneğiyle)

Docker 1.13 Swarm Mode with Raspberry Pi: Setting up a Cluster

Intro

Docker 1.13 has been released recently. It includes a lot of improvements and new features. There is a new compose file format which allows deployment on swarm with a YAML file and making rolling updates with the same file, Docker Secret which is intended to store valuable data, service logs (experimental), metric output (in Prometheus style) and so on.

This post will include installation of latest stable version of Docker on Raspbian Jessie which is 1.13 at the time this post is written, setting up a Docker Swarm with 3 Raspberry Pi and Portainer which is an alternative control option to command line interface and has a web gui. Continue reading Docker 1.13 Swarm Mode with Raspberry Pi: Setting up a Cluster

Python ve Selenium Denemeleri

Selenium ile karşılaşmışken, nasıl kullanılır diye biraz kurcalamak istedim. Yaptığım aşamaları, aldığım sonuçları falan da ufaktan paylaşayım dedim.

Selenium, WebDriverları kullanarak farklı tarayıcılarda, sürekli tekrar ettiğimiz testleri otomatikleştiren, sonuçlarını kontrol eden ve günün sonunda hem bizi tekrar tekrar aynı testleri yapmaktan kurtaran hem de sürekli yaparken gözümüzden kaçabilecek noktaları engelleyen yapısıyla öne çıkıyor.

Continue reading Python ve Selenium Denemeleri

Creating Local CentOS Repository

In many Linux distros, package management tools are utilized for getting new packages and their dependencies. They are also used for  In environments that has many boxes, updating packages and installing new packages may lead tremendous bandwidth consumption. In order to avoid this, it is possible to create a local CentOS Repository and add it all the machines. By using this ability, all other machines can get packages locally, means without consuming any bandwidth from outside Internet connection.

Since traffic inside a network for a limited time for updates does not lead to a problem for many local networks, it results in a observable gain in bandwidth usage of Internet connection. Especially, when local network and number of boxes getting bigger, the ratio is becoming more and more profitable. Continue reading Creating Local CentOS Repository

Python, Dict, Hash ve Doğum Günü Problemi

Python’da yer alan dictionary, yani Türkçe’ye çevrilen haliyle sözlüklerle uğraştıysanız, yeni başladığınızda şöyle bir hata almış olmanız oldukça muhtemel:
Bu hatayı biraz araştırdıysanız da, bu veri türünde(sözlüklerde) anahtar olarak listelerin ve bazı farklı veri türlerinin kullanılamayacağına denk gelmişsinizdir.
Eğer böyle bir durumla daha önce karşılaşmadıysanız, şimdi ne yapınca karşılaşabileceğinize bir örnek görelim. Önce boş bir sözlük tanımlayalım. Birden fazla yol ile sözlük oluşturabiliriz. Burda herhangi bir tanesini kullanıyoruz:
Haliyle artık boş bir sözlük oluşturduk. İkinci satırda da bunun içerisinin boş olduğunu gördük. İsterseniz type() ile de bunu doğrulayabilirsiniz.
Şimdi hemen bir değişken oluşturalım. Kendi adımızı yazacağımız değişken şu formatta olsun:
Haliyle bu noktada oluşturduğumuz isim adlı değişkene kendi adımızı değer olarak aktardık. Şimdi, bunu elimizdeki anahtar ile örnek bir tanımlama yapalım:
Artık sözlük içerisinde bir anahtar-değer çifti var. Bunu tabii ki kısaca şöyle de yapabilirdik:
Buraya kadar bir sorun yok. Peki anahtar olarak bir liste vermek istersek ne olacak? Hemen deneyelim:
Son satıra bakarsanız, en başta bahsettiğim hatayı aldık. Peki liste yerine anahtar olarak bir demet (tuple) veya bir sayı kullanabilir miydik? Hemen ona da bakalım:
Bu durumda ortaya çıkan sonuç, elimizde bir liste varsa bunu anahtar olarak kullanamazken, demet, string ve sayıyı kullanabiliyoruz.
Şimdi esas soru geliyor. Neden liste bir anahtar olarak kullanılamadı?
Bu sorunun cevabı aslında verilen hatada yazıyor. Hash alınamaz (unhashable) bir tür olarak liste belirtilmiş.
Şimdi yeni birkaç soruya daha geçiyoruz. Hash nedir? Python’da hash nedir? Hash ile listenin anahtar yapılamaması arasında nasıl bir ilişki var?
Türkçe anlamına bakınca hash, doğramak veya karıştırmak gibi anlamlara geliyor. Bizim konumuzda da, kendisine gönderilen bilgileri karıştırıp, sabit uzunlukta bir çıkış vermesine denk geliyor. Yani örneğin, siz 100 karakterli bir metin de gönderseniz, koca bir kitabı da gönderseniz hash fonksiyonu bunların çıktısını sabit uzunlukta veriyor. Bu uzunluk yerine göre değişken olabiliyor. Örnek bir hash algoritması olan MD5’i bu konuyu test etmek için kullanabiliriz. Hatta Python’un içerisinde zaten MD5 kütüphanesi bulunduğu için kolayca kullanabiliriz:
hash1 isimli değişkende oluşturulan MD5 için 5 harfli bir giriş vermişken, hash2 için ‘uzun bir metin olacak’ ifadesinin 1000 defa yan yana yazılmış halini giriş olarak gönderiyoruz. Ancak hexdigest ile onaltılık sistemde (hexadecimal’in kısaltması) sonuca baktığımızda 32 karakterlik sabit uzunlukta bir çıkış görüyoruz. İşte hash algoritmaları bize basit anlamda böyle bir çıktı sağlıyor. Bu şeklide düşününce aslında bir özet çıkardığı sonucuna varabiliriz. Tek bildiğimiz bu özetin sabit bir uzunluğa sahip olduğu. Şu an çok anlamlı durmuyor olsa da kullanım alanlarını araştırırsanız büyük bir şaşkınlığa kapılacaksınız :)
Hash’in ne olduğundan bahsettik. Peki koca bir kitabı bile verdiğimizde 32 karakterlik bir çıktı oluşmasını kabul ettiğimize göre, iki farklı kitap için aynı çıktı oluşamaz mı? Hash fonksiyonlarında, aynı girişi tekrar gönderdiğimizde, yani tekrar ‘selam’ yazıp gönderdiğimizde aynı çıktıyı alacağımızı biliyoruz. Ancak ‘selam’ yazınca aldığımız çıktıyı hiç tahmin etmediğimiz koskoca bir kitabı yazınca da alabiliriz. Yani bir sonucu birden fazla girişten elde etmemiz mümkün. Zaten düşününce de, hayal edebileceğimiz her veriyi 32 karaktere sığdırmak ve başka hiçbir veri ile karışmaması pek mantıklı olmaz. Son olarak da, elimizde hash değeri bulunan bir veriyi ilk haline çevirmemiz normal şartlarda mümkün değil. Yani ‘selam’ kelimesine karşılık gelen sonuçtaki 32 karakteri kullanarak ‘selam’ ifadesini elde edemiyoruz. Zaten biraz önce dediğimiz birden fazla girişin aynı çıktıyı verebilmesini de düşününce sonuçtan girişe geri gidebilsek bile hangi girişi elde edeceğimiz belli olmayacaktır. Bu konuda daha detaylı bilgi için hash algoritmalarını araştırabilirsiniz.
Böyle bir konsepti Python’a nasıl bağlıyoruz? Bunun için internette biraz daha araştırma yapınca, Python’un dökümantasyonunda hashable olan bir nesnenin, varolduğu sürece değişmeyen bir hash değerine sahip olması gerektiği yazıyor. Bunu yaparken de __hash__() methoduna sahip olması gerektiğini söylüyor[1]. Bir nesnenin ‘hashable’ yani hash değeri alınabilir olması da Python’da bir sözlükte anahtar olarak ya da bir küme (set) içerisinde kullanılabileceği anlamına geliyor[1]. Bu nesnelerin sahip olması gereken diğer özelliklere de dökümantasyondan ulaşabilirsiniz.
Bu durumda karşımıza programlama dillerinde hash kullanımı gibi bir kavram çıkıyor. Sonra bunu araştırmaya koyuluyoruz. Bu da bizi ‘hash table’ yani hash tablosu sonucuna yönlendiriyor. Hash tablolarının ise, anahtar ve değer çiftlerini temsil ederken kullanılan veri yapılarından biri olduğunu görüyoruz [2]. Python’daki dict, yani sözlük türü bunun bir örneği [3]. Bunun avantajı, sözlük gibi türlerde anahtar olarak verilen bilgiden değer bulunurken, anahtarın sadece hash değerinin alınmasıyla ve oluşturulan hash tablosundan karşılığına düşen değerin nerede olduğunun bulunmasıyla, istenilen anahtar-değer çiftinin çok hızlı bir şekilde elde edilmesi. Bu yüzden de dictionary veri yapısının Python’da sıkça önerildiğini görüyoruz.
Kendi tanımladığımız sınıflar için hash fonksiyonlarını da kendimiz tanımlayabiliyoruz. Eğer bir tanımlama yapmazsak, bu amaçla id() değeri alınıyor ve onunla hesaplanan bir hash değeri kullanılıyor. Haliyle aynı sınıftan oluşturduğumuz ve içeriği aynı olan iki nesneyi sorguladığımızda eşit olmadığını görüyoruz [4].
Esas konuya dönecek olursak, listeler üzerinde istediğimiz zaman değişiklik yapabiliyorduk. Örneğin, append ile eleman ekleme şansımız vardı. Demetler üzerinde ise böyle bir işlem yapamıyorduk. Şimdiye kadar bahsettiğimiz kavramlara göre, liste içerisinde bir değişiklik olursa farklı bir hash değeri elde etmemiz gerekiyor. Haliyle artık hash table içerisindeki ilgili veriyi bir türlü elde edemiyoruz çünkü eski girişi veremiyoruz.
Son bahsettiğimiz durum, neden listelerin sözlüklerde anahtar olamadığını açıklıyor. Biraz daha araştırmaya devam edince, bu hash table’ların oluşturulurken karşılaşılan sorunlar arasında ‘collision’ yani çakışmaya denk geliyoruz. Hatırlarsanız hash leri anlatırken, farklı girişlerden aynı çıkışın elde edilebileceğini söylemiştik. Bu noktada ise, programlama dilini yazarken, veya programlama diline hash table uyarlarken çakışmayı azaltmak gerekiyor.
Çakışma olma ihtimali ise ‘Doğum Günü Problemi’ ile açıklanıyor. Bu probleme göre, aynı ortama konulan rastgele 23 kişiden en az 2 tanesinin doğum gününün aynı güne denk gelme olasılığı %50 olarak ortaya çıkıyor. Hatta eğer 70 kişi olursa bu olasılık %99.9’a kadar çıkıyor. Haliyle 365 günlük yıl içerisinde o an bulunan topluluktan en az 2 kişinin doğum gününün aynı olma olasılığını hesaplamış oluyoruz. Şimdi daha inandırıcı bir hale getirmek için bunu nasıl hesapladığımıza da bakalım [5]:
Ortamda yer alacak ilk kişi için zaten bir gün çakışma ihtimali yok. O yüzden onun olasılığına 365/365 diyebiliriz. Diğerleri için;
  2. kişinin doğum gününün,  1. kişiden farklı olma olasılığı 364.0/365
  1. kişinin 2.’den farklı olma olasılığı 363.0/365

Şeklinde ortaya çıkıyor. Haliyle bu sayıların hepsini birbirine çarptıktan sonra, %50 gibi bir oran kalıyor. Hemen görelim:

Yaptığımız işlem sonucunda, ele aldığımız 23 kişinin doğum günlerinin farklı olma olasılığını, ya da aynı olmama olasılığını 0.4927… şeklinde bulduk.
1 – ‘olmama olasılığı’ dediğimizde ise, bu kişilerin doğum günleri için en az 2 kişinin aynı gün doğmuş olma ihtimalini bulabiliriz:

Yani elde ettiğimiz olasılık, %50’den daha büyük, %50.7297 gibi bir sonuca sahip. Burdan da, doğum günü probleminin nasıl oluştuğunu görüyoruz.

Hatta olayı biraz daha ilerletir ve 70 kişi üzerindeki olasılığı hesaplarsak, artık çok daha yüksek bir olasılıkla aynı gün doğan insanların çıkabileceğini görürüz:

Yani artık %99.9’luk bir olasılıkla bir doğum günü çakışması olduğunu biliyoruz.

Hatırlarsanız hash değerlerinin aynı çıkabildiğini söylemiştik. Seçeceğimiz hash alma fonksiyonu her ne kadar düzgün dağılımlı ve rastgele sonuçlar veriyor olursa olsun, doğum günü paradoksu burda devreye giriyor ve elimizdeki giriş kümesi büyüdükçe programlama dillerindeki uyarlamalarda çakışma olma ihtimalini artırıyor.

Bu konuyu çözmek de programlama dillerinde hash tablolarını uyarlayan kişilere bırakılmış durumda. Bu konuda incelemiş olduğumuz Python, ‘collision list’ adı verilen bir çözüm kullanıyor. Bu çözümde, aynı hash çıkışını veren anahtar-değer çiftleri, o hash değerinin gösterdiği yerde bulunan bir listeye konuluyor. Daha sonra bu listenin elemanları arasında(ki çakışma çok beklenmediği için bu sayı bütün sözlüğe göre çok çok daha az) anahtar bulunarak karşılık gelen değere bakılıyor.

Bunu yapmak yerine, en baştan bütün anahtar-değer çiftlerini bir liste içerisinde tutmak da tabii ki bir çözüm. Hem düşününce, bu şekilde anahtar yerine bir liste de konulması mümkün. Ancak burdaki problem, erişmek istediğimiz anahtar-değer çiftini bulabilmek için her anahtarın teker teker kontrol edilmesi gerekliliği. Bu da elimizdeki ‘dictionary’ çözümüne göre çok daha yavaş çalışıyor. (Meraklısı için, dictionary genellikle O(1) karmaşıklığında çalışırken listeye uyarlayarak teker teker bakmak O(n) karmaşıklığında çalışıyor.)
Esas sorunun cevabı da aslında ortaya çıkmış bulunuyor. Listeler, üzerinde değişiklik olabildiği için her değişiklikte farklı hash değerleri üretiyor. Haliyle listeyi anahtar yapmak, ona ait değere geri ulaşmayı her an imkansız hale getirebiliyor. Demetler üzerinde değişiklik yapılamadığı için onlar anahtar olarak kullanılabiliyor. Ve evet, Python’da aslında String türünden değişkenler üzerinde de değişiklik yapılamıyor(detaylı bilgi için bkz. mutable ve immutable objects in Python)
[1] https://docs.python.org/2/glossary.html
[2] https://en.wikipedia.org/wiki/Hash_table
[3] https://wiki.python.org/moin/DictionaryKeys
[4] https://docs.python.org/2/reference/datamodel.html#object.__hash__
[5] https://en.wikipedia.org/wiki/Birthday_problem

IoT, MQTT ve Mosquitto – Devfest Düzce Sunum Videoları

Geçen hafta Devfest için Konya ve Düzce’de iki oturumda konuşmacıydım. Ufak farklılıklar olması dışında, konu olarak MQTT ve Mosquitto’yu seçtim. Internet of Things’de uygulama geliştirirken sıkça kullandığımız protokol olan MQTT’yi ve bu protokolün en yaygın kullanılan broker’larından biri olan Mosquitto’yu, kurulumlarını, ayarlarını ve yayın yapma/takip etme örneklerini elimden geldiğince anlatmaya çalıştım. Sunum videolarını değerli bir abim çekti ve ben de onları yükledim. Videolar aşağıda, sormak istedikleriniz olursa yazmaktan çekinmeyin.

Yaptığım sunumun slaytlarını sunum yaptığım gün burada paylaşmıştım. Videolardan takip etmekte zorlanırsanız veya bulundurmak isterseniz tarayıcınızdan doğrudan görüntüleyebilirsiniz.

Video 3 kısımdan oluşuyor. 1. kısım:

2. Kısım:

3. Kısım:

 

Ücretsiz ESP8266 ile Nesnelerin İnterneti Kitabı

Nesnelerin interneti (Internet of Things, IoT) konusunda uzun zamandır projeler geliştiriyorum. Bunları yaparken birçok farklı teknolojiyle birlikte çalışmak gerekebiliyor. Sağladığı yenilikleri ve kolaylıkları da göz önüne alınca birçok farklı ve üretken fikrin de her geçen gün ortaya çıktığına şahit oluyoruz.

Projeleri gerçekleştirirken düşük maliyetli çözümler arasında yer alan ESP8266 modülü ile ilgili Türkçe yazılmış bir kitap bulamayınca, ben yazmaya karar verdim. Basılı, uzun ve detaylı bir hali önümüzdeki aylarda hazır olacak, ama bu süreçte kaynak ihtiyacı duyanların başlangıç yapabilmesi, hatta daha ileriye giderek ThingSpeak üzerinden grafikler çizdirip, sensör verilerini Tweet atan uygulamalar yapabilmelerini sağlayan örnekleri hazırladım. Arduino ve ESP8266’yı birlikte kullanarak kablosuz internet ağınıza bağlanmanız veya ESP8266 ile kablosuz internet ağı kurarak telefonunuzdan ya da bilgisayarınızdan bu ağa bağlanmanız için gereken her şeyi bu kitap içerisinde bulabilirsiniz.

Kitaba ulaşmak için tıklayın (~750KB, PDF formatında)

(Kitabın güncel haline ve yapılan değişikliklere bu sayfadan ulaşabilirsiniz.)

Kitap hakkında her türlü yapıcı eleştiriyi, geliştirmeleri vb. heyecanla bekliyor olacağım. İster bu sayfaya yorum olarak, isterseniz e-posta ile bunları bildirebilirsiniz. Okumaktan mutluluk duyacağım. Gelen geri dönüşlere göre bu kitap güncelliğini koruyacak. Olmasını istediğiniz konuları da belirtirseniz, en çok istenenleri zamanla içerisine eklemeye veya en kötü ihtimalle basılı çıkan kitaba eklemeye çalışacağım.

ARDUINO, Python, LINUX, Matlab, C/C++, Raspberry