Docker kullanımı ve genel özellikleri


Bu laboratuvarda popüler, ücretsiz, az kaynak tüketen bir konteyner çalıştıracak ve konteynerlerin nasıl çalıştığını anlayacaksınız. Docker Engine’in konteynerleri nasıl çalıştırdığı ve birbirinden ayırdığına ilişkin temel bilgileri keşfedeceksiniz.

Konteyner ve docker çalıştırmak nedir, konteyner çalışırmak için gerekli temel konmutlar nelerdir diye biliyorsanız bu eğitimi atlayabilirsiniz.


Zorluk seviyesi: Başlangıç

Zaman: Yaklaşık 25 dakika

İçerik:


İpuçları:

Ortamımız içersindeki kod parçacıkları, üç yoldan biriyle gösterilir:

  1. Bu gibi görünen kod, genellikle bir açıklamanın parçası olan örnek kod parçacıklarıdır.
  2. Aşağıdaki gibi görünen kod tıklanabilir ve çalışacağı terminal penceresine otomatik olarak yazılır.
    uname -a
    
  3. Aşağıdaki gibi pencerelerde görünen kod, sizin yazmanız gereken koddur. Genellikle size sağlayamayacağımız benzersiz bir kimlik veya girmeniz gereken başka bir bit olacaktır. <> İçinde görünen öğeler, talimatlara göre değiştirmeniz gereken parçalardır.
    docker konteyner start <konteyner ID(kimliği)>
    

1.0 İlk Konteyneri çalıştırmak

Yazılım dünyasında her zaman “Hello World” uygulaması ile başlama geleneğine uyalım. Artık docker olan bir ortam nasıl çalışıyor bunu canlı olarak tecrübe edelim. İlk Docker konteynerinizi çalıştırmak için aşağıdaki kodu yazın veya tıklayın:

docker container run hello-world

Peki burada ne oldu? Ekranda çıkan hello-world yazısı bize ne olduğu hakkında bir ipucu veriyor aslında. Esasen, terminalinizde çalışan Docker komutu, hello-world adlı bir image bulmaya çalıştı. Bu yüzden komutu çalıştırdığımızda gelen (Unable to find image...) çıktısı, yerel disk üzerinde bu imajın olmadığını bize bildiriyor. Bu nedenle Docker engine, varsayılan Docker registry olan Docker Hub üzerinden “hello-world” isimli bir imaj aradı. İmajı orada buldu, indirdi ve ardından bir konteyner içersinde çalıştırdı. hello-world konteynerinin tek görevi terminalinizde gördüğünüz çıktıyı oluşturmak ve konteynerden çıkmaktır.

Hello world explainer

Sanal makinelere aşina iseniz, sanal makine görüntülerinin merkezi bir deposu dışında, bunun sanal bir makineyi çalıştırmaya benzediğini düşünebilirsiniz. Buradaki basit örnek için bu yaklaşım doğrudur. Ancak bu alıştırmaları gerçekleştirirken Docker ve container’ların VM’lerden farklı olduğu önemli yollar görmeye başlayacaksınız. Şimdilik basit açıklama şudur:

  • VM sanal bir donanım yaratır: fiziksel CPU’ları ve RAM’i bir ana bilgisayardan alır ve birkaç küçük sanal makineye böler ve paylaşır. Sanal makinenin içinde çalışan bir işletim sistemi ve uygulama vardır, ancak sanallaştırma yazılımının genellikle bununla ilgili bir bilgisi ve yönetiminde bir etkisi yoktur.
  • Konteyner ise sanal bir uygulama yaratır: Konteyner çalıştırıldığı işletim sistemi ve çalıştırılan uygulama ile direkt etkileşim içindedir. Çalıştırılan donanımın hiçbir önemi yoktur. Konteyner’lar çoğunlukla sanal sunucular içinde çalıştırılır. Sunucu üzerine önce bir hipervizör kurulur, sonrasında sanal sunucular içinde docker servisleri aktive edilir. Yani çoğu çözüm Donanım -> Sanal -> Konteyner şeklindedir.

1.1 Konteyner ve İmaj(kalıp) nedir?

İmaj(image) olarak bahsi geçen kavramı anlamamız çok önemli. Burada imaj olarak bahsedilen şey aslında bir anlık görüntü veya heykel yapmak için kullandığınız bir kalıptır. İmaj kalıcı ve değişmeyen bir ortamdır, her seferinde aynı imaj ile aynı işlemi yaparsınız, imajın farklı işlemler yapabilmesi için imajı çalıştırırken bazı parametreler ile haberleşmeniz gerekir. Docker için image kelimesi geçtiğinde aklınıza herzaman heykel yapmak için kullanacağınız değiştirilemez bir kalıp düşünün lütfen.

Labaratuarın geri kalan kısmında Alpine Linux bir konteyner kullanacağız. Alpine çok az kaynağa ihtiyaç duyan bir Linux dağıtımıdır, bu nedenle hızlıca indirilip çalıştırılabilir. Alpine Linux genellikle Docker imajlar için oldukça fazla tercih edilir. Örnek vermek gerekirse ubuntu bir imaj 700MB iken aynı işi yapabileceğiniz Alpine imaj 30MB olabilir.(vpn-image)

Başlamak için terminalimizde aşağıdaki komutları yazalım:

docker image pull alpine

pull komutu alpine image imajını Docker registry üzerinden indirerek sisteminize kaydeder. Hiçbir registry tanımı yapmadığınızda varsayılan registry kaydı Docker Hub olacaktır. Docker registry değiştirebilirsiniz. Canlı bir ortamda çalışan imajlarınızı kendi registry ortamınızı kurarak kendi yönetmenizi öneririm.

docker image komutunu kullanarak sisteminiz üzerindeki indirilmiş imajları listeleyebilirsiniz.

docker image ls
REPOSITORY                                  TAG                 IMAGE ID            CREATED             SIZE
alpine                                      latest              d6e46aa2470d        3 weeks ago         5.57MB
hello-world                                 latest              bf756fb1ae65        10 months ago       13.3kB

SIZE sütununa bakarsanız alpine imajı’nın(kabı’nın) sadece 5.57 MB olduğunu görebilirsiniz.

2.1 Docker Konteyneri çalıştırma

İmajı indirdiğimize göre artık çalıştırabiliriz. Çalışacak olan konteyner indirmiş olduğumuz imajı (kabı) kullanarak bir container oluşturacaktır. Oluşan Konteyner imajın birebir koypasıdır, fakat artık kaynak imajlan bağımsız olarak çalışmaktadır. Konteyner’i çalıştırabilmek için docker container run komutunu kullanmamız gerekir.

docker container run alpine ls -l
total 56
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 bin
drwxr-xr-x    5 root     root           340 Nov 17 16:33 dev
drwxr-xr-x    1 root     root          4096 Nov 17 16:33 etc
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 home
drwxr-xr-x    7 root     root          4096 Oct 21 09:23 lib
drwxr-xr-x    5 root     root          4096 Oct 21 09:23 media
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 mnt
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 opt
dr-xr-xr-x  171 root     root             0 Nov 17 16:33 proc
drwx------    2 root     root          4096 Oct 21 09:23 root
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 run
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 sbin
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 srv
dr-xr-xr-x   11 root     root             0 Nov 17 16:33 sys
drwxrwxrwt    2 root     root          4096 Oct 21 09:23 tmp
drwxr-xr-x    7 root     root          4096 Oct 21 09:23 usr
drwxr-xr-x   12 root     root          4096 Oct 21 09:23 var

ls çıktısı çok karmaşık ve heyecan verici bir çıktı değil, fakat bu çıktının oluşabilmesi için arka planda birsürü operasyon gerçekleşti.. run komutunu çağırdığınızda, Docker istemcisi imajı bulur (bu örnek için alpine imajını), konteyneri oluşturur ve sonrasında komutu bu konteyner içerinde çalıştırır. docker container run alpine dediğinizde, (ls -l) şeklinde bir komut verirsiniz, böylece Docker bu komutu konteyner içersinde çalıştırabilir. ls komutu işlemini bitirdiğinde konteyner de işini bitirmiş olur ve durur.

docker run explainer

Komutumuzu çalıştırdıktan sonra konteynerin durmuş olması oldukça önemlidir. Şimdi daha başka komutlar çalıştırıp, bu durumu incelemeye çalışalım:

docker container run alpine echo "Bu cikti ALPINE icersinden gelmektedir"

Yukarıdaki komutu yazdığınızda aşağıdaki çıktıyı üretecektir:

Bu cikti ALPINE icersinden gelmektedir

Çalışan komutun container içinde olduğunu anlamanın başka bir yolu da aşağıdaki gibi, işletim sistemi dosyasını görüntülemektir. Şuan çalıştığınız işletim sisteminin çıktısı

cat /etc/issue

Konteyner(alpine) içerisinden gelen dosya çıktısı

docker container run alpine cat /etc/issue

Gördüğünüz gibi docker içersinde çalıştırdığımız komut, Kontainer içersindeki ortama göre çıktı üretmektedir. İlk örnekte gördüğünüz gibi Docker istemcisi, alpine konteynırı içinde echo komutunu bir işlem olarak çalıştırdı ve sonra konteynırı sonlandırdı. Fark ettiyseniz, tüm bunlar oldukça hızlı gerçekleşti ve konteynırımız tekrar kapandı. Birazdan açıklayacağımız gibi, echo komutu ayrı bir konteyner içersinde çalıştı.

Docker ile yapılan işlemi bir sanallaştırma ortamında yaptığımızı düşünelim. Bir sanal makineyi (VM) başlattığınızı, bir komut çalıştırdığınızı ve ardından onu durdurduğunuzu hayal edin. Komutu çalıştırmadan önce sanal makineyi başlatmak bir veya iki dakika sürer. Bir sanal makinenin tam bir donanımı kaynaklarıyla hipervizör üzerinde oluşturması, bir işletim sistemini başlatması ve ardından uygulamanızı başlatması gerekir.

Docker konteynerleri uygulama katmanında çalışır, böylece sanal makinelerin gerektirdiği adımların çoğuna ihtiyaçları yoktur ve yalnızca uygulama için gerekli olanı betikleri çalıştırırlar. Artık konteynerlerin neden hızlı olduğunu daha iyi görebilirsiniz.

Beraberce daha ilginç bir komut deneyelim.

docker container run alpine /bin/sh

Çok ilginç, hiçbirşey gerçekleşmedi! gerçektenmi? aslında birşeyler gerçekleşti, fakat biz farkedemedik. Alpine konteynırının 3. ayrı bir örneğini başlattınız ve /bin/sh komutunu çalıştırıp çıktınız. /bin/sh e herhangi bir ek komut vermediğimiz için sadece kabuğu başlattı, kabuktan çıktı ve sonra konteyneri durdurdu.

Eminim sizin Beklediğiniz şey bazı komutları yazabileceğiniz etkileşimli bir shell ortamıydı. Docker, konteyneri etkileşimli bir terminalde çalıştırmak için bir parametre ister. bu parametresi verdiğinizde sizi interaktif bir terminal ekranı içersinde konteyner’a bağlar.

Konteyner’i interaktif bir şekilde çalıştırmak için:

docker container run -it alpine /bin/sh

veya sadece docker run -it alpine /bin/sh diyebilirsiniz. container varsayılan olarak kabul görecektir.

Şuanda bir konteyner bağlattınız ve onun içindesinde çalışıyorsunuz. ls -l, uname -a ve cat /etc/issue gibi birkaç komutu deneyebilirsiniz. Alpine’ın küçük bir Linux işletim sistemi olduğunu ve bu nedenle birkaç komutun eksik olabileceğini unutmayın. Exit komutunu yazarak kabuk ve konteynerden çıkabilirsiniz.

Yukarıdaki komutlarımızın her birini ayrı bir konteyner üzerinde çalıştırdığımızı söylemiştik. Bu konteynerleri docker container ls komutunu kullanarak görebiliriz. docker container ls veya docker ps komutu size şu anda aktif olarak çalışan tüm konteynerleri gösterir(peki çalışmış ve durmuş olanlara ne oldu?):

docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS
 NAMES

Gördüğünüz gibi hiçbir aktif çalışan konteyner olmadığı için liste boş geliyor, peki çalışmış ve durmuş olanlar nerede: docker container ls -a veya ``docker ps -a` komutunu deneyelim

docker container ls -a
CONTAINER ID        IMAGE                                             COMMAND                  CREATED             STATUS
      PORTS                               NAMES
d897c07b904b        alpine                                            "/bin/sh"                10 minutes ago      Exited (0) 10 minutes ago                                          priceless_clarke
611a7c62444d        alpine                                            "cat /etc/issue"         22 minutes ago      Exited (0) 22 minutes ago                                          nervous_bell
d8e7981abfcc        alpine                                            "ls -l"                  59 minutes ago      Exited (0) 59 minutes ago                                          quizzical_kirch
b2bb2a758528        hello-world                                       "/hello"                 About an hour ago   Exited (0) About an hour ago                                       beautiful_satoshi

Şuanda gördüğünüz liste, çalıştırdığınız tüm konteynerlerin bir listesidir. STATUS sütununun, bu konteynerlerin bir süre önce durduğunu gösterdiğine dikkat edin. Artık çalışmasalar da yaratılmış olan konteynerler duruyor, ve hepsi aynı imajdan yaratıldılar. Nesne tabanlı programlama ile uğraştıysanız konteynerleri Class lara benzetebilirsiniz. Yaratılan her obje Class’ın birebir kopyasıdır ama Class değildir.

İşte şematik olarak gösterilen docker container ls -a veya docker ps -a komutunun aynı çıktısı (konteyner ID’lerinin ve isimlerinin farklı olacağını unutmayın lütfen):

Docker container instances

Size tavsiyem docker run komutları ile biraz deneme ve test yapmanız, böylece komutun inceliklerini öğrenebilirsiniz. run hakkında daha fazla bilgi edinmek ve desteklediği tüm parametrelerin bir listesini görmek için docker container run --help komutunu kullanabilirsiniz. Docker komut satırı içerindeki help komutu oldukça faydalıdır ve size ilk kullanırken yol gösterici olacaktır. ilerledikçe, birkaç tane daha docker container run komutu varyantı göreceğiz. Size tavsiyem burada aklınıza gelen birkaç farklı kullanımı test etmeniz ve çalışan konteyner’in ortamını keşfetmeniz.

2.2 Konteyner İzolasyonu

Yukarıdaki gördüğümüz örneklerde docker container run komutu yardımıyla konteyner çalıştırdık. Docker container ls -a komutu bize beklediğimizden daha fazla konteyner listeledi. Hepsi alpine imajından oluşuyorsa, neden bu kadar çok konteyner listelendi?

Bu durum, Docker konteynerleri için kritik bir güvenlik konseptidir!

Her bir docker container run komutu aynı alpine imajını kullanıyor. Fakat her çalıştırma ayrı, izole bir konteynerdir ve liste içinde gördüğünüz gibi farklı bir Konteyner yaratmıştır. Her konteynerin ayrı bir dosya sistemi vardır ve farklı bir namespace içersinde çalışır. Bir konteynerin, aynı imajdan oluşsalar bile diğer konteynerlerle etkileşime girme yolu yoktur. İzolasyon hakkında daha fazla bilgi edinmek için başka bir alıştırma yapalım.

docker container run -it alpine /bin/ash

/bin/ash, alpine imajı içinde bulunan başka bir kabuk türüdür. Konteyner başlatıldığında ve konteynerin komut istemindeyken aşağıdaki komutları yazın lütfen:

 echo "herkese selam olsun!" > merhaba.txt

 ls

İlk echo komutu, içinde “herkese selam olsun” sözcüklerinin bulunduğu “merhaba.txt” adlı bir dosya oluşturur. İkinci komut size dosyaların bir dizin listesini verir ve yeni oluşturduğunuz “merhaba.txt” dosyanızı gösterecektir. Şimdi bu konteynerden ayrılmak için exit yazıp çıkalım.

İzolasyonun nasıl çalıştığını göstermek için aşağıdakileri çalıştırın:

docker container run alpine ls

Konteynırın interaktif /bin/ash kabuğu içinde kullandığımız ls komutunun aynısı, ancak bu sefer “merhaba.txt” dosyanızın olmadığını görmüşsünüzdür? Bu tecrit demektir!

Komutunuz aynı imaja dayalı olsa bile yeni ve ayrı bir konteyner‘da çalıştı. Docker Engine onları ayrı tuttuğundan ve bu iki örneğin etkileşime girmesini sağlayacak herhangi bir ekstra parametre ayarlamadığımız için 1. ve 2. örnekle etkileşim kurmanın bir yolu yoktur.

Docker kullanıcıları bu özellikten yalnızca güvenlik için değil, aynı zamanda uygulama üzerinde yapacakları değişiklikleri test etmek için de kullanırlar. İzolasyon, kullanıcıların bir uygulamanın veya hizmetin ayrı, izole edilmiş test kopyalarını hızlı bir şekilde oluşturmasına ve birbirlerini engellemeden yan yana çalıştırmalarına olanak tanır.
Docker veya container orkestrasyonu yaparken bu tip özellikler güncellemeler ve farklı sandbox ortamları yaratmak için kullanılır. Burada bahsedilen konu, sanallaştırma izolasyonu değildir. Çalıştırılan uygulamaların(Konteyner) birbirinden izole olmalarıdır.

Peki sorumuza geri dönelim, merhaba.txt dosyamızın bulunduğu konteyner’a nasıl geri dönebiliriz?

Bir kez daha çalıştırarak:

docker container ls -a

veya docker ps -a komutunu yazarak aşağıdakine benzer bir çıktı alırsınız:

CONTAINER ID        IMAGE                                             COMMAND                  CREATED             STATUS
  PORTS                               NAMES
3a64f8a778e0        ubuntu:groovy                                     "/bin/bash"              3 hours ago         Exited (0) 2 hours ago                                         angry_lalande
d897c07b904b        alpine                                            "/bin/ash"                3 hours ago         Exited (0) 3 hours ago                                         priceless_clarke
611a7c62444d        alpine                                            "cat /etc/issue"         3 hours ago         Exited (0) 3 hours ago                                         nervous_bell
d8e7981abfcc        alpine                                            "ls -l"                  4 hours ago         Exited (0) 4 hours ago                                         quizzical_kirch
b2bb2a758528        hello-world                                       "/hello"                 4 hours ago         Exited (0) 4 hours ago                                         beautiful_satoshi

Grafik olarak göstermek istersek Docker Engine ile işlem şu şekilde gerçekleşir:

Docker container isolation

merhaba.txt dosyasını oluşturduğumuz konteyner, COMMAND sütununda listelendiğini görebileceğimiz /bin/ash kabuğunu kullandığımız yerdi. İlk sütundaki CONTAINER ID numarası, söz konusu konteyner için unique bir tanımdır. Konteyner kimliğinin üzerindeki tanımlayıcı değer d897c07b904b dir. Docker’a bu konteyner tekrar çalışsın diye aşağıdaki komutu yazmamız gerekir:

docker container start <container ID>
  • İpucu: Tam kondeyner ID’sini kullanmak yerine, ilk birkaç harfini kullanabilirsiniz. Konteyner ID’leri benzersiz şekilde oldukları sürece yalnızca ilk birkaç karakteri kullanabilirsiniz. Dolayısıyla, yukarıdaki örnekteki konteyner örneğini tanımlamak için basitçe “d897” kullanabiliriz, çünkü bu listedeki diğer konteynerler bu karakterlerle başlamıyor.

Çalışan konteynerleri listelemek için docker container ls komutunu tekrar kullanabiliriz

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
d897c07b904b        alpine              "/bin/ash"                2 minutes ago       Up 14 seconds                        priceless_clarke

Bu sefer konteyner örneğimizin hala çalıştığını görebilirsiniz. Bu durum /bin/ash kabuğunu kullandığımız için , ash bir komut beklediği için bu şekilde çalışır. Oysa /bin/sh çalışıp çıktıyı geri döner ve programı sonlandırır.

Konteyner içersinde bir komutu çalıştırmak için Exec komutunu kullanabiliriz:

docker container exec <container ID> ls

Şimdi aldığımız çıktı içersinde “merhaba.txt” dosyamızı görebiliyoruz.

Docker container exec command

Şimdi, konteynerlar ile ilgili bazı önemli kavramları görmeye başlıyoruz. Bir sonraki alıştırmada, kendi Docker imajlarımızı nasıl oluşturabileceğinizi ve imajları standartlaştırmak için bir Dockerfile’ı nasıl kullanacağınızı göreceğiz. Böylece basit, otomatikleştirilmiş bir şekilde daha büyük, daha karmaşık imajlar oluşturmaya başlayacağız.

2.3 Terminoloji

Son bölümde, eğitim içersinde kafanızı karıştırabilecek birçok Docker’a özgü terim gördünüz. Bu yüzden daha fazla ilerlemeden önce, Docker ekosisteminde sıkça kullanılan bazı terminolojilere açıklık getirelim.

  • Image - İmajlar veya kalıp’lar, konteyner oluşturmak için kullanılan uygulamamızın dosya sistemi ve yapılandırmasını içerir. Docker imajları hakkında daha fazla bilgi edinmek için, docker image inspect alpine komutunu çalıştırabilirsiniz. Yukarıdaki örnek içersinde alpine imajını indirmek için docker image pull komutunu kullandık. Docker container run hello-world komutunu çalıştırdığımızda, hello-world görüntüsünü indirmek için arka planda bir docker image pull işlemi otomatik olarak gerçekleşir.

  • Container - Konteyner, Docker imajlarının çalışan halleridir. Konteynerlerin çalışması aynı zamanda uygulamaları çalıştırır. Konteyner içersinde uygulama ve tüm bağımlılıkları bulunur. Linux çekirdeğini diğer konteynerlar ile paylaşır ve ana işletim sistemindeki kullanıcı alanında izole bir işlem olarak çalışır. İndirdiğimiz alpine imajını kullanarak çalıştırdığımız docker run kullanarak bir konteyner oluşturulur. docker container ls komutu kullanılarak çalışan konteynerlerin bir listesi görebiliriz.
  • Docker daemon - Docker koneynerlarını oluşturmayı, çalıştırmayı ve dağıtmayı yöneten sunucu üzerinde çalışan çalışan arka plan servisi.
  • Docker client - Kullanıcının Docker daemon ile etkileşime girmesine izin veren komut satırı aracı.
  • Docker Hub - Docker görüntülerinin bulunduğu bir kayıt defteri ‘dir. Kayıt defterini(registry) tüm kullanılabilir Docker görüntülerinin bir dizini olarak düşünebilirsiniz. İnternet üzerinden bir hesap açıp imajları incelemenizi tavsiye ederim, piyasada bulunan neredeyse her yazılım için bir docker imajı vardır.


Konu tekrarı, kısa sınav

seçeneklerden doğru olanları seçtikten sonra Gönder butonuna basınız. Sonuçları doğru ve yanlış görebilirsiniz.

Docker imajları varsayılan olarak nereden indirilirler?

  • ( ) Docker Trusted Registry
  • (x) Docker Hub
  • ( ) Varsayılan yoktur
  • ( ) Docker Store

Docker imajlarını nasıl listelersiniz?

  • (x) docker image ls
  • ( ) docker run
  • ( ) docker container ls

Aşağıdakilerden hangisi ubuntu 20.10(groovy) bir konteyner içerisinde komut satırına bağlanır?

  • ( ) docker run ubuntu:groovy /bin/bash
  • (x) docker run -it ubuntu:groovy /bin/bash
  • ( ) docker pull ubuntu:groovy -c /bin/bash