Siber güvenlik alanında çalışıyorsanız oldukça geniş bir yelpazede derin bir bilgi birikimine sahip olmanız ve bunların yanı sıra gelişiminize sürekli olarak devam etmeniz gerekiyor.
Geçtiğimiz yıl, yazılım geliştirme trendlerini takip ettiyseniz, Docker‘ı çokca duymuş olabilirsiniz. DevOps alanında çalışan geliştiricilerden, konteynerlerden, izole edilmiş makinelerden, hypervisor’lardan bahsettiklerini ve bunları çoğu zaman dillerinden düşürmediklerini fark edebilirsiniz. İşte bu yazıda, yukarıdaki ifadelerden biri olan “Konteynerlere neden ihtiyacımız var“, ondan bahsedeceğiz.
Docker Nedir?
Docker’ın gerçekte yaptığı, uygulama kodunu altyapı gereksinimlerinden ayırmaktır. Bunu, her uygulamayı “konteyner” adı verilen yalıtılmış bir ortamda çalıştırarak yapar. Docker, kapsamlı uygulamalar oluşturmak için geliştirilmiş bir yazılım çözümüdür.
Docker’ın kendi sitesinde Docker şu şekilde tanımlanmaktadır:
“A container image is a lightweight, stand-alone, executable package of a piece of software that includes everything needed to run it: code, runtime, system tools, system libraries, settings.“
Neden Docker?
Bunu örnekle açıklamak gerekirse; çevremizde, kurumların geliştirdiği yazılımların herkesin kullanması için canlı olarak yayına çıkması aşamasında sorun yaşanabiliyor. Geliştirilen kodun sistemde çalışmaması durumunda yazılım geliştiricinin “ama benim bilgisayarımda çalışıyordu” şeklinde yorumlarını duymuş olabilirsiniz. Bu tür problemlerin sebepleri genel olarak, projenin çalışması için gerekli olan bazı gereksinimlerin/yan programların unutulmasından kaynaklanmaktadır. İşte Docker çözümünün en temel nedenlerinden biri buydu.
Her bir Docker konteyneri hayatına hiçbir şey bilmeyen saf bir bebek gibi başlar. Daha sonra, konteynerlere bilmesi gereken her şeyi söyleriz ve öğrenirler. Öğrenmesini ve yapmasını istediğimiz tüm her şeyi Dockerfile dosyasında belirtiriz.
Docker’a dünyasına dalmadan önce Docker’ın yapısal araçlarını biraz inceleyelim.
Docker, kendisinden istenilenleri yapabilmek için dört ana araca sahiptir:
- Docker Engine (https://docs.docker.com/engine/)
- Docker Compose (https://docs.docker.com/compose/overview/)
- Docker Machine* (https://docs.docker.com/machine/overview/)
- Docker Swarm (https://docs.docker.com/engine/swarm/)
Docker Engine
Docker Engine, Dockerfile veya docker-compose.yml‘den bilgileri alarak imajları oluşturur ve çalıştırır. Docker CLI üzerinden bir “docker” komutunu kullandığında, yapılması gereken işlemleri yapması için Docker Engine ile iletişime geçer.
Docker Compose
Docker Compose; çoklu mikro servisler, veritabanları ve benzeri bağımlılıklardan oluşan yapıların çalıştırılması için kullanılır. docker-compose.yml, gerekli olan tüm servisleri tek bir yerden konfigüre etmemize ve hepsini tek bir komut ile oluşturup, çalıştırmamızı sağlar.
Docker Machine
Docker içerisinde birden fazla Docker Engine motoru yönetilebilir. Docker Machine, Docker Engine’i uzaktaki yer alan makinelerine yüklemenize ve kendi bilgisayarınızdan, uzaktaki yer alan Docker Engine motorunun yönetilmesini sağlar.
Docker Swarm
Docker Swarm, Docker platformu için konteyner orkestrasyon aracıdır. Veritabanı, uygulama sunucuları, web sunucuları gibi bileşenlerden oluşan büyük kapsama sahip uygulamalarınızı Docker Swarm ile yönetebilir, yük altında kolaylıkla ölçekleme yapılabilmektedir.
Sanal Makine Nedir?
Sanal makine (Virtual Machine (VM)) gerçek bir makinenin sanallaştırılmış versiyonudur. Bir makinenin donanımını daha büyük bir makinenin içerisinde simüle eder. Yani, birçok sanal makineyi daha büyük bir sunucuda çalıştırabilirsiniz. Inception filmini izlediyseniz daha iyi bir canlandırma olabilir. Hatırlarsınız ki filmde, rüya içinde rüya görülmekteydi. Burada yapılan işlem de makine içerisinde (farklı) makine(ler) çalıştırmaktır. VM’lerin çalışmasını sağlayan şey, Hypervisor olarak bilinen harika bir yazılımdır.
Hypervisor Nedir?
Sanal makineler sadece Hypervisor programına sahip oldukları için çalışabiliyorlar. Fiziksel bir makinenin birkaç farklı veya aynı özelliğe sahip sanal makinelere ev sahipliği yapmasını sağlayan özel bir yazılımdır. VM’lerin hepsi kendi içlerinde kendi programlarını çalıştırabilir ve ana bilgisayarın sahip olduğu donanımı kullanabilirler. Ancak, burada bilinmesi gereken önemli bir konu var, VM’lere kullanmaları için gerekli olan kaynakların belirlemesi kısmını Hypervisor yapmaktadır.
Not: VirtualBox, VMware gibi bir sanallaştırma yazılımı kurmanıza rağmen sanal makine oluşturamıyorsanız bunun iki sebebi olabilir. İlk neden, sahip olduğunuz işlemcinizin sanallaştırma özelliğinin bulunmamasından kaynaklı olabilir. İkinci neden ise, BIOS üzerinden Hyper-V özelliğinin aktif edilmemesinden kaynaklı olabilir.
“Sanal makineler uzun zamandır hayatımızda ve oldukça fazla kullanıyoruz, neden konteynerlar aniden çıkmasına rağmen çok fazla tercih ediliyorlar?” şeklinde sorular ile çok karşılaşıyoruz. Sanal makineleri tamamen hayatımızdan çıkartmak iyi ve kötü sonuçlar doğurabilir. Sanal makinelerin kötü veya gereksiz olduğunu tabi ki savunamayız fakat yönetimleri oldukça zor ve maliyetli olduğu aşikardır.
DevOps alanında çalışan biriyseniz veya bu alanda çalışan kişileri tanıyorsanız işlerinin fazlasıyla zor olduğu fikrine kapılmış olabilirsiniz. Sanal makineler çok fazla depolama ve RAM kaynağına ihtiyaç duyarlar. Bunların haricinde çok daha önemli olan konu ise zaman konusudur. Sanal makinelerin kurulum aşamaları normal bir makineye işletim sistemi kurmaktan farklı olmadığından ötürü kurulumlarını yapılması, oluşturulup kullanıma hazır olabilmeleri için oldukça fazla zamana ihtiyaç duymaktadırlar.
Hackerlar ve DevOps mühendisleri, (teşbihte hata olmaz) aslında çok tembellerdir. Bir şeyin bir çok kez tekrarlanması gerekiyorsa bunu otomatize hale getirmek ve arkamıza yaslanarak keyfimize bakmak isteriz. Bu yüzden bir şeyi otomatize etmek bizler için çok önemlidir.
Docker ile geliştirme, test vb. ortamların kurulumlarını çok hızlıca oluşturabilir ve eskiden bu ortamların kurulumu için kaybettiğiniz tüm zamanı geliştirmelerinize odaklanarak geçirebilirsiniz. Docker Hub ile sizin ihtiyacınız olan imajları bulabilir ve bunları en fazla 3-5 dakika içerisinde kullanmaya başlayabilirsiniz.
Önceleri, uygulamanızın çalışması gereken yardımcı paket programları veya kütüphaneleri de sanal makine üzerine kurmanız gerekiyordu. Uygulamayı başka bir yere taşıdığınızda bu programlardan veya kütüphanelerden birini unutursanız saatlerce problem hakkında düşünüp durabiliyordunuz. Docker ile artık tüm program ve kütüphaneler bir imaj olarak paketlenip sorunsuz bir şekilde istenildiği kadar çoğaltılıp kullanılabilir.
Docker, kendisine verilen kaynakları (CPU, RAM vb.) paylaşımlı olarak kullanır. Docker, CPU paylaşımı yaptığında herkes tüm kaynağı kullandığını düşünür. Bu durum, Docker hakkında bilinen yanlışların başında geliyor. Docker’a CPU kullanım izni verildiğinde tüm CPU kaynağını kullanmaz ve sistemi yük altında bırakmaz. Dosya sistemleri, Docker imajları içerisinde hazırlanmış olan özel işletim sistemlerine göre değişiklik gösterebilir. Hazırlanan konteynerlar farklı isimlere ve farklı ağ ara yüzlerine sahip olabilir. Docker ile hazırlanmış konteynerlar bilgisayar üzerinde kendilerini tek çalışan sistem olarak tanırlar ve diğer çalışan konteynerlardan haberleri olmaz.
Docker Kurulumu Nasıl Yapılır?
Docker’ı yüklemek fazlasıyla kolaydır. Neredeyse tüm sistemler (*Unix, Windows, MacOS) için desteği bulunmaktadır. Biz bu anlatımda, Linux Ubuntu 16.04 işletim sistemi dağıtımı üzerine kurulumunu yapacağız.
Kurulum yapmadan önce repomuzu güncelleyelim.
$ sudo apt-get update
Daha sonra, Docker’ı yüklemek için aşağıdaki komutu kullanalım:
$ sudo apt-get install -y docker.io
Yukarıdaki komutlar ile Docker’ı Ubuntu işletim sistemine kolayca kurmuş olduk.
Docker kurulumunun tamamlanıp, servisinin çalıştığından emin olmak için aşağıdaki komutu çalıştırabilirsiniz:
$ sudo systemctl status docker
Komutun çıktısı aşağıdaki gibiyse, Docker servisimiz de artık sıkıntısız çalışıyor demektir.
● docker.service – Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Paz 2019-04-14 14:55:05 +03; 4h 42min ago
Docs: https://docs.docker.com
Main PID: 1778 (dockerd)
Tasks: 14
Memory: 116.0M
CPU: 9.358s
CGroup: /system.slice/docker.service
└─1778 /usr/bin/dockerd -H fd:// –containerd=/run/containerd/containerd.sock
Docker servisi çalışmıyor (yani “Inactive” ise) ve başlangıçta servisin çalışmasını istiyorsanız aşağıdaki komutu kullanabilirsiniz:
$ sudo systemctl start docker && sudo systemctl enable docker
Docker komutunu “sudo” ile çalıştırmanız gerekir. Ancak, mevcut kullanıcınızı Docker grubuna eklerseniz “sudo” komutunu kullanmadan çalıştırabilirsiniz. Bunun için kendi kullanıcınızla terminaldeyken:
$ sudo usermod -aG docker ${USER}
$ su – ${USER}
Yukarıdaki komut, mevcut kullanıcınızı Docker grubuna ekleyecektir. Yapılan işlemin doğruluğunu test etmek amacıyla ve genel olarak da kullanıcınızın dahil olduğu grupları öğrenmek için “id -nG” komutunu kullanabilirsiniz.
MacOS kurulum dosyasına buradan https://docs.docker.com/docker-for-mac/install/
Windows kurulum dosyasına ise buradan ulaşabilirsiniz https://docs.docker.com/docker-for-windows/install/
İmaj ve Konteyner
Docker imaj ve konteyner terimlerinin bazen birbirlerinin yerlerine kullanıldıklarını görebilirsiniz ancak terim olarak ikisi de farklı açıklamaları ifade ederler.
Docker imajları, bir uygulamayı çalıştırmak için gerekli olan her şeyi içeren çalıştırılabilir paketlerdir. İçerisinde kodlar, kütüphane dosyaları, değişkenler ve yapılandırma dosyaları yer alır.
Docker konteyner, bir imajın çalışması sonrasında oluşur.
Kısacası; Docker imajları, Dockerfile dosyasının içerisinde yer alan tüm işlemlerin gerçekleştirilip paketlenmesidir. Docker konteyner ise hazırlanmış olan imajın alınarak izole bir ortamda çalıştırılması durumunda oluşur. Docker konteynerinin oluşturulabilmesi için bir imaja ihtiyaç vardır.
Elimizi Kirletelim!
Docker’ı öğrenmek için artık biraz elimizi kirletmemiz gerekiyor. Docker’ı kullanmak için ihtiyacımız olan bazı parametreler vardır, bunları inceleyelim;
- create: Docker imajlarını bir konteyner olarak çalıştırmamızı sağlar.
- ps: Çalışan konteynerları listeler. -a parametresini eklersiniz, çalışan ve çalışmayan tüm konteynerlar listelenecektir.
- start: Oluşturulmış olan konteyneri başlatır.
- attach: Terminalinizi standart giriş/çıkış’ını (I/O) konteynera bağlar.
- build: Dockerfile dosyasını alarak imaj haline getirir.
- images: Makineniz içerisinde çalıştırılabilir Docker imajlarını gösterir.
- run: Konteyneri çalıştırır ve belirtilirse konteyner içinde komut çalıştırır.
- rmi: Bir veya birden fazla Docker imajını silmek için kullanılır.
- rm: Bir veya birden fazla konteyneri silmek için kullanılır.
- kill: Bir veya birden fazla çalışan konteyneri durdurmak için kullanılır.
- ps: Çalışan konteynerleri listelemek için kullanılır.
- tag: Oluşturulan imajlara tekrar ulaşabilmek için etiketleme yapar. (Versiyonlama için kullanılabilir)
- login: Docker Registery (Hub)’a bağlanmak için gerekli olan doğrulamayı yapar.
Docker Hub’dan bir Ubuntu imajını alalım ve bunu kendi bilgisayarımızda konteyner haline getirelim.
$ docker create -it ubuntu:16.04 bash
Burada bizlere farklı gelen iki komut bulunuyor. “-it” parametresi, terminaliniz ve oluşturduğunuz konteynerın arasında eş zamanlı bir bağlantı sağlar. En sonda yer alan “bash” argümanı ise konteyner başladığında çalıştırılmasını istediğiniz komuttur. Biz burada Ubuntu içerisinde “bash” komutunun çalıştırılmasını istiyoruz. Bunların dışında “ubuntu:16.04” kısmı ise Docker Hub içerisinde yer alan Ubuntu imajının 16.04 sürümünü konteyner haline getirmek istediğimizi belirtiyoruz.
$ docker ps -a
Yukarıda yer alan komutu kullanarak konteynerlarımızın durumunu öğrenebiliriz. “docker ps” komutu sadece aktif olarak çalışan konteynerleri bizlere listeler. “-a” parametresini kullanmamız durumunda oluşturulan ve durdurulan konteynerlarıda listeleyebiliriz.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
200e7e34d036 ubuntu:16.04 “bash” 4 seconds ago Created compassionate_lumiere
Konteynerı oluşturduk ve artık çalıştırmamız gerekiyor, bunun için sadece “start” yazmamız yeterlidir.
$ docker start 200e7e34d036
Tekrar listeleyerek konteyner durumunu görebiliriz. (Bu sefer “-a” parametresi olmadan konteynerimizi görebiliriz.)
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
200e7e34d036 ubuntu:16.04 “bash” 4 seconds ago Created compassionate_lumiere
$ docker attach 200e7e34d036
Yukarıdaki “attach” komutu ile konteynera bağlanabiliriz. Artık içerisinde Ubuntu işletim sisteminin bulunduğu konteynerimiza bağlıyız ve içerisinde istediğimiz işlemi yapabiliriz. Giriş sonrasında çıkış yapmak için “exit” komutunu kullanabilirsiniz.
Not: Docker konteynerları varsayılan olarak “sudo” olarak çalışmaktadır. Bu, konteynerlar içerisinde sudo komutunun bulunmadığı anlamına geliyor. Konteyner içerisinde çalıştırdığınız her komut otomatik olarak sudo yetkileri ile çalışacaktır.
Docker Kullanım Örneği, Docker Nasıl Kullanılır?
Docker genellikle web uygulamaların yayınlanmasında çokça kullanılmakta. Basit ve hızlı bir örnek yaparak inceleyeceğiz.
Docker ile oluşturduğumuz tüm konteynerlar izole olarak çalıştığını söylemiştik. Konteynerı sildiğinizde ise her şey silinir.
“$ docker rm 200e7e34d036” komutu, oluşturulmuş olan konteynerın silinmesini sağlar.
Konteynerda Olan Konteynerda Kalır!
“Konteynerda olan konteynerda kalır” felsefesi, bazı durumlarda can sıkıcı olabiliyor. Her şey siliniyorsa verileri nasıl saklayacağız? Burada bir can kurtarana ihtiyacımız var ve Docker imdadımıza yetişerek bu konuda bizi yalnız bırakmıyor. Docker, kendi bilgisayarınız üzerinde yer alan dizinler ile konteyner içerisinde yer alan dizinleri eşleyebilmemize imkan sağlamaktadır. Bu son cümlenin yüreğinize su serptiğini düşünüyoruz.
$ docker create -it -v $(pwd):/var/www ubuntu:latest bash
Yukarıda yazmış olduğumuz komut, “-v” parametresi vasıtasıyla bulunduğumuz dizin ile konteyner içerisinde yer alan “/var/www” dizinini bağlar.
Artık “run” komutunu öğrenme zamanımız da geldi. Docker üzerinde en çok kullanacağımız komut, “docker run” komutudur. Run komutu, “create” ve “start” komutlarının yaptığını tek başına yapar. Run komutununu kullandığımızda ilk öncelikle “create” komutu gibi konteyner oluşturulur ve sonrasında “start” komutu gibi oluşturduğu konteyneri çalıştırır.
$ docker run -it -d ubuntu:16.04 bash
“-d” parametresi oluşturulan konteynerin arka planda çalıştırılmaya başlamasını sağlar.
Duvarları Yıkalım!
Konteynerda olan konteynerda kalır felsefesini uygulamalı olarak esnetme zamanımız geldi. Şimdi fiziksel makine üzerinde bulunan küçük bir statik sayfayı konteyner içerisinde yer alan Nginx HTTP web sunucu yazılımı ile yayına alacağız. Bir dizin oluşturun ve aşağıda yer alan HTML kodlarını oluşturduğunuz dizine index.html ismiyle kaydedin.
<html>
<head>
<title>Docker Demo Page</title>
</head>
<body>
<div class=”container”>
<h1>Biraz Docker Ogrenelim</h1>
<p>Bu sayfa nginx kullanilarak yayinlanmaktadir.</p>
</div>
</body>
</html>
Sırada bu statik dosyayı konteyner içerisinde yer alan Nginx ile yayınlamak kaldı. Aşağıdaki komut bunu yapmamızda bize yardımcı olacak.
$ docker run –name seccops_nginx -v $(pwd):/usr/share/nginx/html -d -p 8080:80 nginx
Yukarıdaki komutta farklı parametreler görüyorsunuzdur. “–name” parametresi konteynera isim vermemizi sağlıyor. “-p” parametresi ile konteyner içerisinde kullanılan 80 portuna, ana makinenizde 8080 portu üzerinden ulaşılabilmesini sağlar.
Bilgisayarımızda oluşturduğumuz index.html dosyası içerisinde yapacağımız tüm değişiklikler eş zamanlı olarak konteyner içerisinde de değişecektir. Aynı şekilde konteyner içerisinde “/usr/share/nginx/html” dizinine eklenebilecek herhangi bir dosya fiziksel bilgisayarınıza da aktarılacaktır.
Oluşturduğunuz Docker konteynerini aşağıdaki komutla durdurabiliriz.
$ docker stop <konteyner id>
Bu yazıda, herkesin Docker kullanmaya başlayabilmesi ve hızlıca bir kaç örnek deneyebilmesi için oldukça sade olarak aktarmaya çalıştık.
Yazının devamı: Sızma (Penetrasyon) Testi Uzmanları için Docker Kullanımı
Bu blog yazısıyla veya Docker ile ilgili sorularınız olursa bizlere ulaşabilirsiniz.