# İçindekiler
Docker öğrenirken aldığım notlar.
Genellikle Özgür Öztürk'ün Docker eğitimini izlerken not aldım.
Elimin altında Türkçe kaynak olması için Docker ve Konteyner Uygulamaları kitabını almıştım ve bazen buradan faydalandım.
*Metinlerin bir bölümünü Özgür Hoca'nın sunumundan aldım.
*Naçizane; eğitimi şiddetle önerebilirim
Yeni nesil IT sistemleri Docker üzerinde koşuyor. En çok kullanılmak istenen platformlar listesinde üst sıralarda yer alıyor. İş ilanlarında aranan bir özellik 😜
- Temelde bir fiziksel makina üzerinde birden fazla sanal makina kurup, kaynak dağıtımını ve ortak kaynak kullanımını sağlayan sisteme verilen isimdir.
- Bu sayede fiziksel sunuculardaki atıl kapasiteyi minimuma indirebiliriz.
- Kaynak israfı önlenir
- Her uygulama izole edilmiştir, bu sayede bir uygulamada çıkan sorun diğer uygulamaları etkilemeyecektir
- Sanallaştırma her ne kadar kaynak israfını minimuma indirse de yine de kaynak israfı mevcuttur. Bu sebeple container'lar hayatımıza girdi.
- Linux containerlar sayesinde uygulamalar izole bir şekilde çalıştırılabildi fakat bu kolay bir işlem değildi.
- Namespaces
- Linux çekirdeğinde bulunan yapı taşlarındandır. Prensibi çekirdek kaynaklarrının bölümlere ayrılmasıdır. Container izolasyonunun sağlanmasındaki birincil yapıdır.
- Bazı namespaces'ler
- Net: Ağ arayüzlerini yönetir
- PID: Süreçlerin izolasyonunu sağlar
- Mnt: Dosya sistemindeki mount noktalarını yönetir
- Cgroups
- Linux çekirdeğinin kullandığı temel bileşenlerdendir. Donanım kaynaklarının sınırlandırılması, kısıtlama ve limit özelliklerinin sağlanması için kullanılır
- Container'lar; host makinede izole olarak çalışan, kullanıcı tarafından her şekilde müdahale edilebilen sanal birimdir.
- Aynı sistem üzerinde çalışırlar, o sistemin çekirdeğini kullanırlar fakat birbirlerinden tamamen izole durumdalardır.
- Docker engine; client-server mimarisinde bir uygulamadır
- Docker platformunun kalbidir
- Docker Daemon, Docker Client, REST API bileşenlerinden (temel) oluşur
- Docker Daemon
- REST API isteklerini karşılar
- Docker objelerini üretmemizi ve yönetmemizi sağlar (Container, image, volume vb bileşenler)
- Rest API
- Diğer uygulamalar rest api sayesinde docker daemon ile konuşur
- Docker CLI (Client)
- Rest API'nin en önemli kullanıcısı Docker CLI'dır
- Bir docker engine kurduğumuzda o makinede hem docker server (daemon) hem de docker client (docker cli) kurulmuş olur
- İstersek bu client (docker cli) uygulamasını localimize kurarak, cloudda kurduğumuz bir server (docker daemon)'ı yönetebiliriz. Yani bu 2 uygulama birbirinden farklıdır.
- Docker image'lerde kernel'e gerek yoktur
- Image'ler birer şablondur
- Bir image'i bir yerde depolayabilirsem, docker engine sayesinde bu image'i çalıştırabilirim
- Container'lar sayesinde image'leri depolayabiliriz
- Container dediğimiz şey aslında bir nevi image'lerin çalışır halidir. Container image şablonunun çalışan kopyasıdır olarak düşünebiliriz
- Bu sayede her sistemde her seferinde aynı sonucu alırız. Bir yerde çalışan container her yerde çalışır
- Container Registry, Container Image Registry, Docker Registry olarak da bilinir
- Docker imajlarını depolayıp dağıtabildiğimiz bir alt yapı servisidir
- En bilineni Docker Engine'ın default olarak baktığı yer olan Docker Hub'dır
- Play With Docker hizmeti sayesinde cloud ortamında Docker denemeleri yapabiliriz
- Tek kötü yanı bir oturumda en fazla 4 saat kullanmamıza izin vermesidir
- Docker Daemon'u yönetmemizi sağlar
docker version-> Docker kurulumu ile ilgili temel bilgilere erişirizdocker info-> Docker ile ilgili temel bilgilere erişiriz (kaç container çalışıyor, drivers vb.)docker-> Docker CLI'da kullanabileceğimiz komutları listeler- Options
- Docker Daemon'a bağlanırken kullanacağımız parametreler gözükür
- Management Commands
- Yönetebileceğimiz bileşenlerin listesi
- Commands
- Yönetmek istediğimiz bileşen için çalıştırmak istediğimiz komut
- Options
docker image --help-> image bileşeni ile kullanabileceğimiz komutları listeler
docker container --help-> container bileşeni ile kullanabileceğim komutlardocker container run-> parametre olarak verdiğimiz isimde bir container varsa başlatır yoksa önce oluşturur sonra başlatırdocker container run --name ilkcontainer ozgurozturknet/app1-> ilkcontainer adında bir container oluşturdu ve docker hub'da ozgurozturknet altındaki varsayılan (app1) uygulamasını çalıştırdıdocker container ls -a-> sistemdeki tüm container'ları listeler. -a olmasaydı sadece çalışan container'ları listelerdi- Container içerisindeki varsayılan olarak çalışması için ayarlanan uygulama durduğunda container'da kapatılır
docker container run <IMAGE>docker container run -p 80:80 ozgurozturknet/adanzyedocker- 80:80 portunda çalışan bir web servisi çalıştırır (hazır imaj)
docker container lskomutu ile bu container'ı görebiliriz. Çünkü bu çalışıp kapanan bir uygulama değildir
docker container logs <ContainerID>-> ID'si verilen container'a ait logları gösterirdocker container stop <ContainerID>-> ID'si verilen container'ı durdururdocker container start <ContainerID>-> ID'si verilen container'ı başlatırdocker container run -d -p 80:80 ozgurozturknet/adanzyedocker- -d detach'ten gelmektedir. Container direkt arka planda çalışmaya başlar (terminalimize bağlamaz)
docker container rm <ContainerID>-> ID'si verilen container'ı siler- illa tam id vermek zorunda değiliz id'nin ilk harflerini versek de olur
- Çalışan bir container silinemez bunu öncelikle durdurmamız gerekir ya da -f parametresi kullanılarak force ederek sileriz
docker container prune- sistemdeki çalışmayan tüm container'ları siler
docker container run --name websunucu -p 80:80 -d ozgurozturknet/adanzyedocker- websunucu adında bir container'ı adanzyedocker imajından oluşturdu ve arka planda çalıştırdı (127.0.0.1'e giderek görebilirsiniz)
docker container exec -it <ContainerName> <command>it-> interaktif olarak container'a bağlan demekdocker container exec -it websunucu sh- websunucu container'ına bağlan ve sh komutunu çalıştır (shelle bağlanır)
ctrl + p qkombinasyonu ile Container'ı kapatmadan arka plana alabiliriz
docker cp basitapp:/app .-> container'ın kapanmış olması önemli değil yeter ki silinmemiş olsun. basitapp adındaki container'ın app klasörünü host makinadaki bu dizine kopyala dedik.
- Docker depolama alt yapısında union file system adı verilen bir yapı kullanır
- Docker imajları mevcut bir base imaj üzerine inşa edilir
- Bu imaj üzerine yapılan her değişiklik birer katman olarak eklenir ve bu katmanlar birer dosya olarak saklanır
- Tüm ayarlamalar image oluşturma aşamasında yapılandırılır
- Tek bir uygulama çalıştırması için dizayn edilir
- Bir sorun olursa saniyeler içerisinde yeni bir kopya oluşturulabilir
- Sorun container'a bağlanılarak çözülmez
- Container içerisinde çalışan ana uygulama durduğu zaman container'da durdurulur
- Container'da bir sorun ile karşılaşılırsa bu container'a bağlanılarak değil yeni bir container oluşturularak çözülür
- Container'lar yeniden oluşturulduğunda container içerisindeki veriler sıfırlanır, bunları container dışında tutmamız gerekir
- Ne demiştik? Docker lifecycle sonlandığında container içerisindeki her şey sıfırlanır, yani yazdığımız dosyalar vb hiç olmamış gibi ilk hale döner
- Volume'ler Container'lar dışında veri saklamak istediğimiz zaman çok kullanışlıdır
docker volume create <VolumeName>-> parametre olarak verilen isimde bir volume oluştururdocker volume create ilkvolume
docker volume inspect <VolumeName>-> volume detaylarını verirdocker volume inspect ilkvolume
docker container run -it -v ilkvolume:/uygulama alpine sh- alpine imajından bir container oluşturuyorum
- -it ile container'a interaktif olarak bağlanıp sh komutunu çalıştırıyorum
- -v ile ilkvolume adındaki volume'u container içerisindeki /uygulama adındaki klasöre bağlıyorum
-v <VolumeName>:<ContainerİçindekiKlasör>
- Örneğimiz gereği aşağıdaki işlemleri gerçekleştiriyoruz
cd uygulamatouch testecho "naber nasılsın?" > test
exitile conteiner'dan çıktık ve container'ı siliyoruz (volume'u test edeceğiz bakalım yeni bir container ile oluşturduğumuz test dosyasına ulaşabilecek miyiz)docker volume ls-> komutu ile volume'leri listelerizdocker container run --name mydebiancontainer -it -v ilkvolume:/uygulama debian sh- debian imajından mydebiancontainer adında container oluştur, /uygulama klasörüne ilkvolume volume'unu bağla ve sh ile container'a bağlan
- burdan aynı şekilde klasöre gidip cat ile dosya içerisine bakarsak yazdığımız verinin orda bulunduğunu görebiliriz
- Container içerisinde volume adında bir klasör yoksa, o isimde bir klasör oluşturulur ve içerisine mount edilir. Peki volume'leri bir klasör içerisine mount etmek istersek?
- Eğer volume imaj içinde bulunan mevcut klasöre mount edilirse:
- Klasör boşsa o anda volume içinde hangi dosyalar varsa bu klasörde de o dosyaları görürüz
- Klasörde dosya varsa ve volume boşsa klasördeki dosyalar volume'e kopyalanır
- Klasörde dosya var ya da yok fakat volume boş değilse, klasörün içinde volume'de ne varsa onu görürüz
- Host makinada (kendi local makinamız) bulunan bir klasörü veya dosyayı Container içerisinde map etmeye Bind Moun denir
docker container run -d -p 80:80 --name mynginx nginx-> basit bir web sunucu oluşturdukdocker container exec -it mynginx sh-> container'a bağlanıyoruzcd /usr/share/nginx/html-> bize default olarak serve edilen dosya- Şimdi bu container'ı siliyoruz ve aşağıdaki komutu çalıştırıyoruz
docker container run -d -p 80:80 -v /Users/mebaysan/Desktop/mydockertest:/usr/share/nginx/html nginx- -d ile container'ın arka planda çalışmasını sağlıyoruz
- -p ile port set ediyoruz
- -v ile aynı Volume bağlar gibi local makinamızdaki klasör path'ini veriyoruz ve dedik ki; container içerisindeki /usr/share/nginx/html klasörü localimdeki ilgili path'ten çeksin
- nginx -> imaj adı
- Unutmamalıyız ki bu yöntem development aşamasında kullanılır, kesinlikle production ortamında kullanmamalıyız!
- Ek protokol vb getirmeden ağ işlemlerini gerçekleştirebiliriz
- Container sistemlerinin iletişim altyapısını network driver'ları ile sağlıyoruz
- Temel 5 driver vardır
- Bridge
- Varsayılan driver'dır
- Network objesi oluşturulurken özellikle başka bir driver belirtilmezse bridge driver ile oluşturulur
- Her Docker kurulu host üstünde bridge driver ile oluşturulmuş "Bridge" adında network bulunur ve container oluşturulduğunda farklı bir driver belirtilmediği sürece default olarak buna bağlanılır
- Host
- Her sistemde host driver ile oluşturulmuş "Host" adında bir driver vardır
- Bu network'e bağlı container'da network izolasyonu olmaz. O host üzerinde çalışan bir process'mişcesine host'un ağ kaynaklarını kullanır
- Macvlan
- Bu driver ile oluşturulan network objeleri ile container'lar fiziksel ağlara kendi mac adreslerine sahip birer fiziksel ağ adaptörüne sahipmişcesine bağlanabilir
- None
- Container'a hiç bir şekilde ağ bağlantısı olmasın istersek None driver kullanılır
- Overlay
- Ayrı hostlar üzerindeki container'ların aynı ağda çalışıyormuş gibi çalışması istendiği zaman Overlay network'ler kullanılır
- Bridge
docker network ls-> sistemdeki kurulu network objeleri listelerdocker network inspect bridge-> bridge NAME'ine sahip objenin özelliklerini listelerdocker container run --net <NetworkObject> <CONTAINER>--netile network objesini vererek ilgili network'e bağlanabilirizdocker container run --net none <CONTAINER>-> container'a ağ bağlantısı olmaz (none)
- Ayni bridge üzerindeki container'lar birbirleriyle iletişim kurabilirler Fakat biz dış dünyadan container içerisindeki servislere erişmek istersek port publish denilen işlem sayesinde erişebiliriz.
- Örnek olarak container içerisindeki servis 80 portundan dinliyor. Biz
-pya da--publishparametresi ile bu portu belirleriz ve bu sayede host makineye 80 portundan gelen istekleri container'ın 80 portuna iletiriz. - Bu işleme port publish denir. Notasyon şu şekildedir
-p <HostPort>:<ContainerPort>-p 80:80-> örnek-p 8080:80 -p 8043:443-> birden fazla port publish yapabiliriz- Default olarak TCP portları açılır. Eğer istersek UDP portları açabiliriz
-p 80:80/udp
- Container'lar arası network izolasyonu sağlamak istersek ayrı bridge'ler oluşturarak bunu sağlayabiliriz
- Default bridge network içerisinde dns çözümlemesi yok
- Varsayılan dışında ip aralıkları tanımlayabiliriz
- Kullanıcı tanımlı bridge network'e bağlı container'lar birbirleriyle isimler üzerinden haberleşebilirler. Dns çözümlemesi sağlar
- Container'lar çalışır durumdayken de kullanıcı tanımlı bridge network'lere bağlanıp, bağlantıyı kesebilirler
docker container run -d --name websunucu ozgurozturknet/adanzyedocker-> websunucu adında bir container oluşturuyorumdocker container run -it -d --name database1 ozgurozturknet/adanzyedocker sh-> database1 adında bir container oluşturup içine giriyorum.ping websunucu1ile ilk container'a erişmeye çalışıyorum/usr/src/myapp # ping websunucuping: websunucu: Name does not resolve-> o container'a direkt container adı ile erişemiyorum; çünkü default bridge network'de dns çözümlemesi yok- Fakat IP adresi üzerinden erişebiliriz yani aralarında bağlantı var
- Şimdi container'ları siliyoruz ve kendi bridge'mizi oluşturup container'ları yeniden oluşturacağız
docker network create mybridge-> mybridge adında bir bridge network oluşturduk. Opsiyon girmediğimiz için default olarak bridge oluşturdudocker network create --driver=host myhost-> host network'u oluştururdocker network ls-> network driver'lar listelenir
docker network inspect mybridge-> network driver'ımızı inceliyoruzdocker container run -d --name websunucu --net mybridge ozgurozturknet/adanzyedocker-> websunucu adında bir container oluşturduk ve mybridge driver'ına bağladıkdocker container run -d --name database --net mybridge ozgurozturknet/adanzyedocker-> database adında bir container oluşturduk ve mybridge driver'a bağladıkdocker network inspect mybridge-> mybridge adındaki driver'a bakıyoruz ve bağlı olan container'ları görüyoruzdocker container exec -it websunucu sh-> websunucu container'ına bağlanıyoruzping database-> database adındaki container'ı pingliyoruz ve bu sefer başarılı oluyoruz. Çünkü kendimiz bir bridge oluşturduk ve bunun üzerinde container'ları iletişime geçiriyoruz
docker network create --driver=bridge --subnet=10.10.0.0/16 --ip-range=10.10.10.0/24 --gateway=10.10.10.10 mybridge2-> istersek oluşturduğumuz bridge'in ağ özelliklerini belirleyebiliriz- Kullanıcı tanımlı bridge'lerin en önemli özelliklerinden birisi de container'lar çalışırken bu bridge'lere bağlanabilirler
- Notasyon şu şekildedir:
docker network connect <BridgeName> <ContainerName>docker network connect mybridge2 database-> yukarda oluşturduğumuz database container'ını mybridge2 adındaki network'e bağlıyoruz. Unutmayalım şu an hala çalışan bir container!
docker attach database-> çalışan bir container olan database'e bağlanıyoruzifconfig-> yazdığımızda göreceğiz ki eth1 (mybridge2) gelmiş
docker network disconnect mybridge2 database-> database container'ı mybridge2'den düşürüyoruzdocker network rm mybridge2-> driver'ı sildik (bağlı bir container olmaması gerek)
- Docker araçlarını kullanarak loglara erişebiliriz
docker container run -d --name mycont1 ozgurozturknet/app1-> arka planda mycont1 adında bir container oluşturdocker logs mycont1-> mycont1 adındaki container'a ait loglardocker container run -d --name mycont2 -p 80:80 nginx-> container oluşturup 127.0.0.1 adresine gidip 3-5 kere refresh yapıyorumdocker logs mycont2-> container'a ait loglar
- Container; tek bir uygulamanın ya da servisin paketlenmiş halidir, sürekli olarak container içerisine girmeyiz.
docker top <ContainerName>-> ilgili container içerisinde çalışan process'leri listelerdocker stats <ContainerName>-> ilgili container'ın ne kadar kaynak kullandığını gösterirdocker stats-> tüm container'ların kaynak kullanımını gösterir
- Eğer container oluştururken limitler koymazsak her container; sistem kaynaklarını sınırsız olarak kullanır
docker container run -dit --name mycont alpine-> bir container oluşturuyorumdocker attach mycont-> komutu ile container'a bağlanabilirimctrl + p qkombinasyonu ile arka plana atabilirim (çalışmaya devam eder)
docker container run -d --memory=100m alpine-> max 100mb kullanabilecek bir container oluşturdudocker container run -dit --name mytest --memory=100m alpine-> mytest adında bir container oluşturuldu, max 100m kullanabilecekm-> megabyteg-> gigabytek-> kilobyteb-> byte
docker container run -dit --memory=100m --memory-swap=200m alpine-> eğer memory limiti aşılsa bile swap olarak 200m daha kullanabilecekdocker container run -dit --cpus="1.5" alpine-> oluşturduğumuz container sistem içerisinde ne kadar core varsa onun sadece 1.5 tanesini kullanabilecekdocker container run -dit --cpus="1.5" --cpuset-cpus="0,3" alpine-> sadece cpu 0 ve cpu 3'ü kullanabil dedik
- İşletim sistemi bazında tanımlanan ve her yerden çağrılabilen değişkenlerdir
- Linux sistemlerde:
printenvile tüm ortam değişkenlerini gösterirecho $<EnvName>-> ilgili değişkenin değerini verirexport <EnvName>=<EnvValue>-> değişken tanımlamamızı sağlar
docker container run -it --env VAR1=deneme1 --env VAR2=deneme2 alpine sh-> container'a 2 adet environment tanımladık. Environment'ler büyük küçük harf duyarlıdır.- Container içerisinde
printenvkullanırsak (alpine linux olduğundan) tanımladığımız değişkenleri görebiliriz
- Container içerisinde
docker container run -it --env HOME alpine sh-> eğer environment'e değer atamazsak sistem üzerinde o environment'i arar ve onun değerini atayıp container'a gönderir- Eğer istersek bir dosya içerisinde tüm ortam değişkenlerini tanımlayıp tek komut ile de bunu gönderebiliriz
touch env.listecho "VAR1=deneme1" >> env.listecho "VAR2=deneme1" >> env.listecho "VAR3=deneme1" >> env.list- Değişkenleri dosya içerisine ekledim
docker container run -it --env-file ./env.list alpine sh-> --env-file parametresi sayesinde liste olarak environment'leri gönderdik
- Docker imajına verilen isim aynı zamanda o imajın nerede depolandığını da belirtir
- Docker imaj adı ile container oluşturabildiğimiz gibi imaj ID'sini de kullanarak imajlardan container oluşturabiliriz
- Docker imaj yapısı:
<RegistryURL>/<repository>:<tag>docker.io/mebaysan/test:latest- docker.io olmasının sebebi varsayılan olarak docker hub registry'den imaj çekilmesidir. Eğer istersek farklı registry'leri belirtebiliriz:
docker image pull gcr.io/google-containers/busybox-> örnek olarak google image registry'den busy box adındaki imajı çektik
- docker.io olmasının sebebi varsayılan olarak docker hub registry'den imaj çekilmesidir. Eğer istersek farklı registry'leri belirtebiliriz:
- Tag'ler sayesinde tek repository içinde birden fazla versiyon tutabiliriz
docker image pull <ImageName>-> komutu sayesinde local sistemimize bir imajı çekeriz- Tag belirtmediğimiz müddetçe default olarak
latesttag'ı kullanılır
- Tag belirtmediğimiz müddetçe default olarak
docker tag ubuntu mebaysan/deneme-> çektiğimiz ubuntu imajını localde yeniden adlandırdık (öncesinde pull edilmeli tabii). Artık aynı imaja mebaysan/deneme diyerek erişebiliriz.
- Docker imajı oluşturmak istersek öncelikle Dockerfile adında bir dosya oluşturmamız gerekir
- Daha detaylı bilgi için buraya Özgür hocanın repository'sine bakınız. Bu parametreleri ve açıklamalarını onun reposundan aldım.
- FROM
- Oluşturulacak imajın hangi imajdan oluşturulacağını belirten talimat. Dockerfile içerisinde geçmesi mecburi tek talimat budur. Mutlaka olmalıdır.
- Ör: FROM ubuntu:18.04
- LABEL
- İmaj metadata’sına key=value şeklinde değer çiftleri eklemek için kullanılır. Örneğin team=development şeklinde bir etiket eklenerek bu imajın development ekibinin kullanması için yaratıldığı belirtilebilir.
- Ör: LABEL version:1.0.8
- RUN
- İmaj oluşturulurken shell’de bir komut çalıştırmak istersek bu talimat kullanılır. Örneğin apt-get install xxx ile xxx isimli uygulamanın bu imaja yüklenmesi sağlanabilir.
- Ör: RUN apt-get update
- WORKDIR
- cd xxx komutuyla ile istediğimiz klasöre geçmek yerine bu talimat kullanılarak istediğimiz klasöre geçer ve oradan çalışmaya devam ederiz.
- Ör: WORKDIR /usr/src/app
- USER
- gireceğimiz komutları hangi kullanıcı ile çalıştırmasını istiyorsak bu talimat ile onu seçebiliriz.
- Ör: USER poweruser
- COPY
- İmaj içine dosya veya klasör kopyalamak için kullanırız
- Ör: COPY /source /user/src/app
- ADD
- COPY ile aynı işi yapar yani dosya ya da klasör kopyalarsınız. Fakat ADD bunun yanında dosya kaynağının bir url olmasına da izin verir. Ayrıca ADD ile kaynak olarak bir .tar dosyası belirtilirse bu dosya imaja .tar olarak sıkıştırılmış haliyle değil de açılarak kopyalanır.
- Ör: ADD https://wordpress.org/latest.tar.gz /temp
- ENV
- Imaj içinde environment variable tanımlamak için kullanılır
- Ör: ENV TEMP_FOLDER="/temp"
- ARG
- ARG ile de variable tanımlarsınız. Fakat bu variable sadece imaj oluşturulurken yani build aşamasında kullanılır. Imajın oluşturulmuş halinde bu variable bulunmaz. ENV ile imaj oluşturulduktan sonra da imaj içinde olmasını istediğiniz variable tanımlarsınız, ARG ile sadece oluştururken kullanmanız gereken variable tanımlarsınız.
- Ör: ARG VERSION:1.0
- VOLUME
- Imaj içerisinde volume tanımlanamızı sağlayan talimat. Eğer bu volume host sistemde varsa container bunu kullanır. Yoksa yeni volume oluşturur.
- Ör: VOLUME /myvol
- EXPOSE
- Bu imajdan oluşturulacak containerların hangi portlar üstünden erişilebileceğini yani hangi portların yayınlanacağını bu talimatla belirtirsiniz.
- Ör: EXPOSE 80/tcp
- ENTRYPOINT
- Bu talimat ile bir containerın çalıştırılabilir bir uygulama gibi ayarlanabilmesini sağlarsınız.
- Ör: ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
- CMD
- Bu imajdan container yaratıldığı zaman varsayılan olarak çalıştırmasını istediğiniz komutu bu talimat ile belirlersiniz.
- Ör: CMD java merhaba
- HEALTHCHECK
- Bu talimat ile Docker'a bir konteynerin hala çalışıp çalışmadığını kontrol etmesini söylebiliriz. Docker varsayılan olarak container içerisinde çalışan ilk processi izler ve o çalıştığı sürece container çalışmaya devam eder. Fakat process çalışsa bile onun düzgün işlem yapıp yapmadığına bakmaz. HEALTHCHECK ile buna bakabilme imkanına kavuşuruz.
- Ör: HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
- SHELL
- Dockerfile'ın komutları işleyeceği shell'in hangisi olduğunu belirtiriz. Linux için varsayılan shell ["/bin/sh", "-c"],Windows için ["cmd", "/S", "/C"]. Bunları SHELL talimatı ile değiştirebiliriz.
- Ör: SHELL ["powershell", "-command"]
- Aşağıdaki örnek senaryo için buraya bakabilirsiniz. Comment line'lar ile desteklenmeye çalışıldı.
- Ubuntu 18.04 yüklü bir sistem kur
- İşletim sistemini güncelle
- Python kur
- Uygulamayı sisteme kopyala
- Sistem başladığında uygulamanın başlamasını ayarla
docker image build -t <ImageTag> -f <DockerFileName> .docker image build -t mebaysan/ilkimaj .- ilkimaj adında bir imaj oluşturur
- . -> build context'i belirtiyoruz, eğer Dockerfile içinde COPY vb bir komut varsa bunlar için gerekli dosyaları sen bu çalıştığın klasör içerisinde ara
- Dockerfile'ın olduğu dizinde bir adet Dockerfile olduğundan ekstra -f parametresini girmeme gerek yok
docker image lskomutu ile sistemimizdeki mevcut imajları görebilirizdocker container run mebaysan/ilkimajkomutu ile oluşturduğumuz imajdan bir container oluşturduk ve ekran çıktısnı gördükdocker image history <ImageTag>komutu ile imajın geçmişini görebilirizdocker image history mebaysan/ilkimaj
- Localde oluşturduğumuz bir Docker imajını hub'a göndermek için öncelikle CLI'da login olmamız gerekir
docker login-> komutu ile login olabiliriz
docker image push <Image>komutu ile localdeki istediğimiz image'i hub'a pushlayabilirizdocker image push mebaysan/ilkimaj-> ilgili imajı pushlar
- Bir flask uygulamasını container'da çalıştırıyoruz. Daha detaylı bilgi için buraya bakabilirsiniz.
- O klasördeki Docker imajı oluşturmak için:
docker image build -t mebaysan/basitflaskimaj .komutunu kullanıyorum
- Oluşturduğum imajdan bir container oluşturmak için:
docker container run --rm -p 80:5000 mebaysan/basitflaskimaj--rm-> container kapanınca otomatik olarak sil (bir daha silmekle uğraşmayalım)-p-> bu makinaya 80 portundan gelen istekleri container'ın 5000 portuna yönlendir. Flask uygulaması 5000 portundan ayağa kalktığı için
- O klasördeki Docker imajı oluşturmak için:
echokomutu sayesinde bir değeri çıktı olarak verir>sayesinde bir komutun çıktısını yönlendiririzecho "deneme" > deneme.txt
&komutun sonuna eklersek komutu arka plana atar, arkada çalışır|1. komutun çıktısını 2. komuta iletmeye sağlarcat dosya | grep "naber"dosya içeriğini okur çıktıyı grep'e yollar, içerisinde naber geçenleri filtrelerls ; date-> ; sayesinde aynı anda birden fazla komut çalıştırmamızı sağlar&&-> VE||-> VEYA
- Healthcheck konusunu gördüğümüz dosyaya buradan bakabilirsiniz
- İmaj oluşturmak için:
docker image build -t mebaysan/basichealthcheck .
- Bu imajdan container oluşturmak için:
docker container run -d --name mycont -p 80:80 mebaysan/basichealthcheck
- ENV örneği ile container oluşturmak için:
docker container run -d --name mycont --env KULLANICI="BAYSAN" --env HOSTNAME="MyHOST" -p 80:80 mebaysan/basichealthcheck-> ortam değişkenleri set ederek container oluşturuyoruz, detaylı açıklama Dockerfile içerisindedir
- COPY -> belirttiğimiz dosya veya klasörü belirttiğimiz PATH'e atar
- ADD -> COPY ile aynı işlevi yapar fakat dosya kaynağının bir url olmasına izin verir. Aynı zamanda kaynak dosya bir .tar dosyası ise bunu hedef klasöre decompress olarak atar
- Detaylar için buraya bakabilirsiniz
- Oluşturduğumuz Dockerfile ile imaj oluşturup aşağıdaki komut ile container oluşturuyoruz ve ADD sonucunu görüyoruz
docker container run -it mebaysan/wpadd sh
- CMD için buraya bakabilirsiniz
- ENTRYPOINT için buraya bakabilirsiniz
- CMD runtime'da değişebilirken ENTRYPOINT runtime'da değiştirilemez
- Her image'de en az 1 adet CMD veya ENTRYPOINT olmalıdır
- Eğer hem CMD hem de ENTRYPOINT varsa, CMD'de yazılanları ENTRYPOINT'e parametre olarak geçer
- Exec Form =>
CMD ["python", "app.py"] - Shell Form =>
CMD python app.py - Eğer komut Shell formunda girilirse bu imajdan container oluşturulduğu zaman bu komutu varsayılan shell'i çalıştırarak onun içerisinde çalıştırır. Bu nedenle container'da çalışan 1. process (pid 1) bu shell process olur
- Eğer komut Exec formunda girildiyse herhangi bir shell çalıştırılmaz ve komut direk process olarak çalışır. Container'ın pid 1'i o process olur
- Exec formunda çalıştırılan komutlar herhangi bir shell processi çalışmadığı için Environment Variable gibi bazı değerlere erişemezler.
- Eğer ENTRYPOINT ve CMD birlikte kullanılacaksa Exec form kullanılmalıdır. Shell formda CMD'deki komutlar ENTRPOINT'e parametre olarak aktarılmaz
- İmaj oluştururken, oluşturma aşamalarını kademelere bölmemize ve ilk kademede yarattığımız imaj içerisindeki dosyaları bir sonraki kademede oluşturacağımız imaja kopyalayabilmemize imkan sağlar. Bu sayede son imajımızın boyutunun küçülmesi sağlanır.
- Ör: Bir Go uygulaması yazdık ve bunu derleyip sunucuya göndereceğiz, imaj oluştururken önce kodu derler çalışan bir halini hazırlarız. Sonrasında bu çalışan derlenmiş dosyayı 2. aşamada nihai imaja koyar ve imajı oluştururuz. Bu sayede gereksiz yere kaynak kodlarını veya go derleyicisini imaj içerisinde tutmamıza gerek kalmaz
- Örnekler için buraya bakabilirsiniz
- İmaj oluştururken kullanbildiğimiz bir diğer parametre ise ARG'dır. Sadece build aşamasında kullanılabilir ve sonrasında container ayağa kalktığında erişilemez.
- Örnek için buraya bakabilirsiniz.
- Örnek bir Build Arg gönderimi
docker image build -t mytest2 --build-arg VERSION=3.8.1 .
- Dockerfile olmadan da docker imaj oluşturabiliriz
- Doğru kullanım Dockerfile olsa da tek yöntem bu değildir
- Öncelikle localimizde bir container oluşturur ve içerisinde gerekli kurulumları vs yaparız
- Ardından
docker commit <LocalContainerName> <NewImageTag>komutu ile o container'dan bir imaj oluşturmuş oluruz- Ör:
docker commit localcont1 mebaysan/prodcont1:latest
- Ör:
docker commit -c 'CMD ["command 1", "command 2"]' <LocalContainerName> <NewImageTag>-> -c parametresi ile CMD, EXPOSE vb. komutları bu imaja ekleyebiliriz
- Save komutu sayesinde localde oluşturduğumuz bir imajı
.tardosyası olarak kayıt edebiliriz, ve internet erişimi olmasa bile (hub'dan çekemiyor demektir) sunucuya atabilirizdocker save <LocalImage> -o <filename>.tardocker save mebaysan/test -o mebaysantestimaj.tar
- Load komutu ile
.tarolarak gelen docker dosyasını sisteme imaj olarak yükleyebilirizdocker load -i <TarFile>docker load -i mebaysantestimaj.tar
- Kendi ağımızda ücretsiz olarak bir docker deposu oluşturabiliriz
- Bunun için yine Docker Hub üzerinden 😊 registry imajını kullanacağız
- Bu imaj sayesinde bir container çalıştıracağız. İçerisinde docker hub'a benzer bir yazılım çalıştırıyor. 5000 portundan ayağa kalkıyor.
docker pull registryimajı locale çekiyoruzdocker container run -d -p 5000:5000 --restart always --name registry registry- restart parametresi container down olduğunda ne yapılacağını alır
always-> down olunca ne olursa olsun restart atno-> down olunca bir şey yapmaon-failure-> sadece hata olur da kapanırsa yeniden başlat fakat biz elimizle manuel kapatırsak yeniden başlatmaunless-stopped-> manuel olarak stop edersek başlatmaz fakat geri kalan her durumda başlatır
- 5000 portunu 5000 portuna publish ettik
- registy adındaki container'ı registry imajından oluşturduk
- restart parametresi container down olduğunda ne yapılacağını alır
http://127.0.0.1:5000/altında çalışmaya başlarhttp://127.0.0.1:5000/v2/_catalogaltında kayıtlı repoları gösterir,localcont1adında bir imaj oluşturduğumuzu varsayalımdocker push localhost:5000/localcont1-> localdeki imajı registry'e kayıt ettidocker pull localhost:5000/localcont1bu adrese erişebilen makinalar; komutu ile local registry'deki imajı çekebilir
