Docker yolculuğu — 1

Semih Saydam
8 min readFeb 8, 2022

--

Merhaba,

Uzun bir aradan sonra yeni bir yolculukla yine beraberiz. Bu yolculukta beraber Docker’ı öğrenmeye çalışacağız. Yolumuz biraz uzun ama beraber öğreneceğimiz çok şey var :)

Docker ile yolculuğumuzun başında biraz kavramlardan bahsedelim. Bu kavramlar şimdilik size çok fazla şey ifade etmeyebilir. Ama kullandıkça zaten aklınızda yer edecektir. Öncelikle container kavramını anlamaya çalışalım :

Docker image, uygulamanızın gerekli tüm bağımlılıkları ve konfigürasyonları ile paketlenmiş halidir. Docker container ise, oluşturmuş olduğumuz image’ın çalıştırılabilir halidir.Siz uygulamanızı bu şekilde paketledikten sonra artık bu uygulama tahmin edebileceğiniz üzere her yerde(ortam bağımsız) çalışabilir olacaktır. Bu da sizin geliştirme ve deployment ihtiyaçlarınızı daha verimli şekilde yönetmenizi sağlayacaktır.

Basitçe düşünmemiz için bir örnek vereyim. Örneğin siz MongoDb’ye bağlanan java kullanan vb. bir ödev uygulaması yaptınız. Bu uygulamayı iş başvurusu yaptığınız yere gönderdiğiniz de, ödevinizi kontrol eden kişi bu uygulamayı çalıştırabilmek için tüm gerekli kurulumları yapmalı. Fakat eğer siz uygulamanızı dockerize etmiş olsaydınız(paketleseydiniz), ödevi kontrol eden kişi 1–2 küçük komut ile bu paketi kendi bilgisayarında açıp ödevinizi çalıştırabilir. Docker sadece bunu yapabilir diye düşünmeyin, yaptıklarını gördükçe Docker’ı çok seveceksiniz ! :)

Bir de Docker hub kavramı vardır. Docker Hub, bir image deposudur. Burayı github gibi hayal edebilirsiniz. Docker image’larınızı buraya depolayabilir, ihtiyacınız olan image’ları buradan çekebilir ve kullanabilirsiniz. Varsayılan olarak kullanılan image registery, Dockerhub’dır. Fakat şirketler kendi private depolarını oluşturabiliyorlar. Buradaki kavramları bir çizim ile açıklayalım :

Daha önceki yazılarımı takip ettiyseniz eğer benim biraz benzetmeleri sevdiğimi bilirsiniz :) Şimdi yukarıdaki akışı da bir benzetme ile daha iyi anlamaya çalışalım. Yukarıdaki akışı nefis bir yemek üzerinden anlatalım :

Dockerhub’ı yemek tarifini bulduğumuz bir websitesi gibi düşünelim. Bu yemek tarifi sitesinde binlerce yemek tarifi bulunuyor. Hatta ünlü şeflerin yemek tarifleri de bulunuyor(Docker hub’da official image’lar bulunur, örneğin jenkins, mongoDb vb. onaylanmış image’lar bulunur). Siz bu yemek tarifi sitesinden tarifler indirebileceğiniz gibi(pull), kendi tariflerinizi de yükleyebiliyorsunuz(push). Örneğin siz siteden bir tarhana çorbası tarifi indirdiniz ve artık bu tarif sizin için kullanılmaya hazır(Docker image). Siz bu tarif üzerinden her gün aynı yemeği yapabilirsiniz. Siz ne zaman bu tarifi çalıştırırsanız aynı özelliklere sahip bir yemek ortaya çıkar. Bu yemekler de Docker container’lardır. Kendi yaptığınız tarifleri de image haline getirip(Dockerfile), yemek tarif sitesine yükleyebilirsiniz(push). Ve dünyanın her yerinden o websitesine girip kendi tarifinizi indirip, yemeğinizi yapabilirsiniz.

Buraya kadar kavramları biraz da olsa anladık. Artık bilgisayarımıza Docker kurup bu kavramları derinlemesine öğrenmeye başlayalım.

Google üzerinde “docker download” araması yaptıktan sonra ;

Gelen sitede ben MacOs için bir kurulum yapacağım. “Docker.dmg” kurulum dosyası indikten sonra sürükle bırak yaparak “Applications” içine “Docker.app”i atıyoruz(Bende yüklü olduğu için üzerinde o şekilde bir işaret var). Docker.app’i açtıktan sonra gördüğünüz üzere laptop’unuzun üst kısmında Docker’ın simgesi oluşuyor ve tıkladığınızda “Docker is running” ifadesini görüyoruz.

Terminal’i açtıktan sonra, “docker container run hello-world” komutunu yazalım ve kurulumu başarılı bir şekilde yaptığınızı teyit edelim. Telaş yapmayın bu komutların hepsini beraber derinlemesine öğreneceğiz.

“This message shows … installation appers to be working correctly” mesajını gördüğümüze göre başarılı bir şekilde kurulumu gerçekleştirebilmişiz. Bu mesajı gördükten sonra “docker container ls” ve “docker container ls -a” komutlarını yazdık. “docker container ls” ile bize çalışan container’ları getirmesini istedik fakat gördüğünüz üzere getiremedi. “docker container ls -a” komutu ile hello-world image’ından oluşturulan container’ı bize getirdi. “-a” option’u ile çalışan çalışmayan (tüm) container’lar bize getirilir. “-a” yı girmezseniz sadece çalışanları getirir.

Ama “docker container run hello-world” ile biz container’ı çalıştırdık, neden çalışan container’ları getiren “docker container ls” komutunda gözükmedi ? diye sorarsanız eğer, bunun açıklaması aslında docker’ın güçlü bir yönünü gösteriyor. Docker container’lar bir amaç için oluşturulur. Bir container işini yapar sonra işi biterse şayet kapanır. Bizim yukarıdaki container’ımız çalıştı ve işini yapar yapmaz kapandı, işi bize aşağısındaki yazıyı yazdırmaktı. Siz ona ne iş yüklerseniz onu yapar. Uzun süreli açık kalmasını istediğiniz container’lar da olacaktır. Örneğin nginx ile bir websitesi yayını yaptığınızı düşünün, o websitesi hep açık olmalı değil mi? İşte bu websitesini yayınlayan container kapatmadığınız sürece, sürekli ayakta kalıyor olacaktır. Uygulama çalıştığı sürece container ayakta kalır.

Peki container sadece tek bir uygulama mı çalıştırabilir ? diye sorarsanız eğer, bunun cevabı da “Hayır” olacaktır. Çünkü container başlatılırken tek bir uygulamayı çalıştıracak şekilde ayağa kalkar ama bu sizin bu container içinde farklı uygulamalar çalıştıramayacağınız anlamına gelmez. Bu kısım şimdilik biraz ayrıntı bilgiye giriyor, ilerledikçe bunu zaten kendimiz de göreceğiz.

Bu arada değinmeden geçmeyelim, docker’ı biz bu yazı serisi boyunca terminalden kullanacağız. Fakat sizin yaptığınız bu işlemler aynı zamanda bir GUI üzerinden de yönetilebilir :

Docker simgesi üzerinden “Dashboard”a gittikten sonra “Images” tabında local’inize indirdiğiniz image’leri görebilirsiniz. Burada aynı zamanda Dockerhub deponuzda olan image’leri de görebilirsiniz. “Containers/Apss” tab’ında ise bu image’den üretilen container’ları görebilirsiniz. Yukarıda gördüğünüz üzere hello-world image’ından “loving_mcnulty” adında bir container üretilmiş(isim vermezseniz otomatik bir isim verir). Üzerine tıkladığınızda, terminalde çalıştırdığımızda gördüğümüz log’ların aynısını burada da görebiliyoruz. Aynı zamanda container’ın sağ tarafındaki butonlardan container’ı çalıştırabiliyor, silebiliyor vb. işlemler yapabiliyorsunuz.

Images tab’ına tekrar dönerseniz, “bir yemek tarifinden istediğiniz kadar yemek yapabilirsiniz” söylemimizi doğrulayalım ve bu “hello-world” image’inden başka bir container daha oluşturalım :

“Run” butonuna tıkladıktan sonra :

Container’ımıza bir isim vermemizi istiyor. “semih” ismi verip çalıştırıyorum ve gördüğünüz üzere önceki container ile aynı çıktıyı veren başka bir container oluşturduk. Yani tek bir yemek tarifi(image) ile birden fazla yemek(container) oluşturabiliriz.

Peki terminalde yazdığımız bu komutları ezberlememiz mi gerekiyor ? Kesinlikle hayır. Şöyle ki :

Terminalde sadece “docker” yazdığınızda docker size bir kullanım klavuzu sunuyor. Buradan bakarak tüm komutları yazabilirsiniz. Örneğin “docker container run hello-world” örneğindeki komutta demekki “container” kısmı “management commands”tan kullanılıyormuş ve “run” kısmı da “commands”tan kullanılıyormuş. Ben bu yazı serisinde komutları bu düzenekte yazıyor olacağım. Örneğin bir image build edeceğimiz zaman “docker image build …” şeklinde komut giriyor olacağım. Burada managament commands sayesinde ne ile işlem yapacağımızı söylemiş oluyoruz ve komutumuz daha anlamlı oluyor.

Bunun yanında siz eğer komutu bir yere kadar getirdiniz ama yapacağınız işlem için girmeniz gereken option’u unuttunuz diyelim. İşte böyle bir durumda da tıkandığınız yerde hemen “--help” yazıyoruz :

docker container run --help” yazdıktan sonra bu komutun nasıl kullanılacağını, hangi option’larla beraber kullanılacağını bize gösteriyor. Yani gördüğünüz üzere komutları ezberlememiz gerekmiyor. Yine de not almak isterseniz diye yazıda kullanılan komutları yazının sonunda toplu halde, açıklamalarıyla beraber bırakıyor olacağım :)

İlk yazıda kavramlardan ve kullanacaklarımızdan bahsediyoruz. Burada sizlere bir de “play with docker”dan bahsetmek istiyorum. Bu size online docker çalışabileceğiniz bir lab ortamı sağlıyor. Bunu ara ara kullanıyor olacağız. Dört saatlik bir session sunuyor :

Sol taraftaki menüden birden fazla instance oluşturmamıza izin veriyor. Hadi burada da bazı temel komutları uygulayalım :

Öncelikle “docker image pull hello-world” komutu ile başladık. Bu komut ile dockerhub’dan bir image’i local’imize indiriyoruz. Yani bir yemek tarifi indirdik. Artık bu tariften bir sürü yemek yapabiliriz.

Ardından “docker container create hello-world” ile bu image’dan bir container oluşturduk ve “docker container start container_id” komutu ile de bu container’ı çalıştırdık(Burada container_id için ilk 4-5 haneyi yazmanız yeterli olur hepsini yazmanıza gerek yok). Ardından “docker container logs container_id” komutuyla da çalışan bu container’ın log’larına baktık.

Çizimde de belirttiğim üzere “docker container run” komutu aslında bu işlemleri kapsıyor. “docker container run hello-world” dediğinizde eğer image yoksa “pull” işlemini yapıyor ve bunun yanında container create ve start işlemlerini de yapıyor.

“docker ps” komutunu ben çok kullanmıyorum. Management commands’a sadık kalarak “docker container ls -a” şeklinde kullanıyorum ama yine de çizime ekledim.

Şimdi bir adım daha ileri gidelim ve silme işlemlerini nasıl yapabiliriz bakalım:

Bu yazı serisi boyunca farklı farklı image’lar inceliyor olacağız. Image’leri ve container’ları local’imizde tuttukça epey yer kaplıyor olacaktır. Bunları nasıl sileceğimizi de öğrenelim.

Burada gördüğünüz üzere 3 adet senaryo gerçekleştirdik. 1nci senaryomuzda bilgisayarımızda çok fazla container birikti ve kullanmıyoruz. Bunları toplu halde silmek istiyoruz. Bunun için “prune”u kullanıyoruz :

Prune size, “tüm container’lar silinecek emin misiniz?” diye soracaktır. “Y” veya “n” ile son onayı verebilirsiniz. Ardından 2nci senaryomuzda belirli container’ları silmek istiyorsunuz. Aralarından bazıları hala size gerekli. İşte bu durumda “rm” command’ını kullanıyoruz :

Açıklamasından da göreceğiniz üzere “one or more containers” ifadesi var. Biz burada 1 tane container için komut uyguladık ama “docker container rm -f 324s20af5 2321sfasg 23042df…” şeklinde arada bir boşluk bırakarak birden fazla container’ı da silebilirsiniz.

3ncü senaryomuzda da yine container’ları toplu olarak sileceğiz. “prune” sadece durdurulmuş container’ları siliyordu. Burada “prune”dan farklı olarak, çalışan çalışmayan tüm container’ları siliyor oluyoruz. Bunu yapmak için önce tüm container’ları durduruyoruz, ardından siliyoruz. docker stop ve docker rm komutları sonrası çalışan çalışmayan tüm container’ları getirmek için $() ile command substitution(nedir?) kullanıyoruz.

Burada management command olarak container’ı kullandık. Ama benzer senaryolar image, volume vb. diğer management commands için de geçerli olacaktır.

Böylelikle Dockerhub’dan bir image’ı indirmeyi, o image’dan container oluşturmayı, çalıştırmayı, log’larına bakmayı ve o image’ı/container’ı silmeyi öğrenmiş olduk. Sonraki yazıda görüşmek üzere :)

Yazıdaki komutlar :

Kaynakça :

  • https://unix.stackexchange.com/questions/390026/what-does-mean-in-the-shell
  • https://www.youtube.com/watch?v=3c-iBn73dDE&list=PLFaWgoMmhApO4Xszv9ojddcW-ATW7Z6t7&index=18
  • Udemy [A’dan Z’ye Docker — Özgür Öztürk]
  • Udemy [Docker Mastery]

--

--