├── .gitignore ├── README.md ├── static ├── compose │ └── Screen Shot 2021-01-17 at 12.17.21.png └── giris │ └── giris-1.png └── uygulamalar ├── ADD-COPY-FARKI └── Dockerfile ├── ARG └── Dockerfile ├── Compose └── intro │ └── docker-compose.yml ├── DockerSecret ├── password.txt └── username.txt ├── DockerStack └── docker-compose.yml ├── Dockerfile-2 ├── Dockerfile └── myapp │ └── app.py ├── Dockerfile-4 └── pythonapp │ ├── Dockerfile │ ├── app.py │ └── requirements.txt ├── Dockerfile-5 ├── Dockerfile └── index.html ├── ENTRYPOINT-CMD-FARKI ├── cmd │ └── Dockerfile └── entrypoint │ └── Dockerfile └── MultiStageBuild ├── Dockerfile └── source └── uygulama.java /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # İçindekiler 2 | 3 | 4 | - [Giriş](#giriş) 5 | - [Neden Docker](#neden-docker) 6 | - [Sanallaştırma](#sanallaştırma) 7 | - [Container (Linux)](#container-linux) 8 | - [Docker Engine](#docker-engine) 9 | - [Image ve Container (Docker)](#image-ve-container-docker) 10 | - [Image Registry](#image-registry) 11 | - [Kurulum Yapmadan Docker Kullanmak](#kurulum-yapmadan-docker-kullanmak) 12 | - [Container 101](#container-101) 13 | - [Docker CLI](#docker-cli) 14 | - [Container Temelleri-1](#container-temelleri-1) 15 | - [Container Temelleri-2](#container-temelleri-2) 16 | - [Container Temelleri-3](#container-temelleri-3) 17 | - [Docker Katmanlı Dosya Sistemi Yapısı](#docker-katmanlı-dosya-sistemi-yapısı) 18 | - [Docker Container Yaşam Süresi (Lifecycle)](#docker-container-yaşam-süresi-lifecycle) 19 | - [Docker Volume-Container Dışı Veri Saklama](#docker-volume-container-dışı-veri-saklama) 20 | - [Docker Boş-Dolu Volume Davranışları](#docker-boş-dolu-volume-davranışları) 21 | - [Bind Mounts](#bind-mounts) 22 | - [Container 102](#container-102) 23 | - [Docker Network Driver](#docker-network-driver) 24 | - [Docker Network Objeleri-1](#docker-network-objeleri-1) 25 | - [Docker Network Objeleri-2-Port Publish](#docker-network-objeleri-2-port-publish) 26 | - [Docker Network Objeleri-3](#docker-network-objeleri-3) 27 | - [Logging Uygulama Günlükleri](#logging-uygulama-günlükleri) 28 | - [Docker Stats ve Top](#docker-stats-ve-top) 29 | - [Container Cpu ve Memory Limitleri](#container-cpu-ve-memory-limitleri) 30 | - [Environment Variables (Ortam Değişkenleri)](#environment-variables-ortam-değişkenleri) 31 | - [Image ve Registry](#image-ve-registry) 32 | - [Image İsimlendirme ve Tag Yapısı](#image-i̇simlendirme-ve-tag-yapısı) 33 | - [Image oluşturma](#image-oluşturma) 34 | - [Dockerfile-1](#dockerfile-1) 35 | - [Dockerfile Parametreleri](#dockerfile-parametreleri) 36 | - [Dockerfile-2](#dockerfile-2) 37 | - [Dockerfile-3](#dockerfile-3) 38 | - [Dockerfile-4](#dockerfile-4) 39 | - [Linux Shell Trickleri](#linux-shell-trickleri) 40 | - [Dockerfile-5](#dockerfile-5) 41 | - [ADD ve COPY Farkı](#add-ve-copy-farkı) 42 | - [ENTRYPOINT ve CMD Farkı](#entrypoint-ve-cmd-farkı) 43 | - [Exec Form ve Shell Form Farkı](#exec-form-ve-shell-form-farkı) 44 | - [Multi-stage Build](#multi-stage-build) 45 | - [ARG](#arg) 46 | - [Docker Commit](#docker-commit) 47 | - [Docker Save-Load](#docker-save-load) 48 | - [Registry](#registry) 49 | - [Compose ve Swarm](#compose-ve-swarm) 50 | - [Docker Compose](#docker-compose) 51 | - [Docker Compose CLI](#docker-compose-cli) 52 | - [Docker Compose Yaml Dosyası](#docker-compose-yaml-dosyası) 53 | - [Docker Compose Build](#docker-compose-build) 54 | - [Container Orchestration](#container-orchestration) 55 | - [Docker Swarm](#docker-swarm) 56 | - [Swarm Manager ve Worker Node](#swarm-manager-ve-worker-node) 57 | - [Manager Node](#manager-node) 58 | - [Worker Node](#worker-node) 59 | - [Docker Swarm init](#docker-swarm-init) 60 | - [Swarm Service](#swarm-service) 61 | - [Overlay Network](#overlay-network) 62 | - [Docker Secret](#docker-secret) 63 | - [Docker Stack](#docker-stack) 64 | 65 | 66 | # Giriş 67 | Docker öğrenirken aldığım notlar. 68 | 69 | Genellikle Özgür Öztürk'ün [Docker eğitimi](https://www.udemy.com/course/adan-zye-docker/)ni izlerken not aldım. 70 | 71 | Elimin altında Türkçe kaynak olması için [Docker ve Konteyner Uygulamaları](https://www.amazon.com.tr/Docker-Konteyner-Uygulamalar%C4%B1-Deniz-Parlak/dp/6058060761/ref=sxts_sxwds-bia-wc-rsf-lq2a1_0?__mk_tr_TR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&cv_ct_cx=docker&dchild=1&keywords=docker&pd_rd_i=6058060761&pd_rd_r=adeb9eba-433e-4a3e-86e0-e81304013581&pd_rd_w=yeCbD&pd_rd_wg=E8mQH&pf_rd_p=1afd11f1-1dc6-4ec0-a331-2a221d78fd95&pf_rd_r=ZQNNXBF5BV4D5Z92G71P&psc=1&qid=1610552031&sr=1-1-569cd1f4-72a6-4f1d-b3c5-cf7f1ae39fbb) kitabını almıştım ve bazen buradan faydalandım. 72 | 73 | *Metinlerin bir bölümünü Özgür Hoca'nın sunumundan aldım. 74 | 75 | *Naçizane; [eğitimi](https://www.udemy.com/course/adan-zye-docker/) şiddetle önerebilirim 76 | ## Neden Docker 77 | 78 | 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 :stuck_out_tongue_winking_eye: 79 | 80 | ## Sanallaştırma 81 | 82 | - 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. 83 | - Bu sayede fiziksel sunuculardaki atıl kapasiteyi minimuma indirebiliriz. 84 | - Kaynak israfı önlenir 85 | - Her uygulama izole edilmiştir, bu sayede bir uygulamada çıkan sorun diğer uygulamaları etkilemeyecektir 86 | 87 | ## Container (Linux) 88 | 89 | - 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. 90 | - Linux containerlar sayesinde uygulamalar izole bir şekilde çalıştırılabildi fakat bu kolay bir işlem değildi. 91 | - **Namespaces** 92 | - 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. 93 | - Bazı namespaces'ler 94 | - Net: Ağ arayüzlerini yönetir 95 | - PID: Süreçlerin izolasyonunu sağlar 96 | - Mnt: Dosya sistemindeki mount noktalarını yönetir 97 | - **Cgroups** 98 | - 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 99 | - Container'lar; host makinede izole olarak çalışan, kullanıcı tarafından her şekilde müdahale edilebilen **sanal birimdir**. 100 | - Aynı sistem üzerinde çalışırlar, o sistemin çekirdeğini kullanırlar fakat birbirlerinden tamamen izole durumdalardır. 101 | 102 | ## Docker Engine 103 | - Docker engine; client-server mimarisinde bir uygulamadır 104 | - Docker platformunun kalbidir 105 | - Docker Daemon, Docker Client, REST API bileşenlerinden (temel) oluşur 106 | - **Docker Daemon** 107 | - REST API isteklerini karşılar 108 | - Docker objelerini üretmemizi ve yönetmemizi sağlar (Container, image, volume vb bileşenler) 109 | - **Rest API** 110 | - Diğer uygulamalar rest api sayesinde docker daemon ile konuşur 111 | - **Docker CLI (Client)** 112 | - Rest API'nin en önemli kullanıcısı Docker CLI'dır 113 | - Bir docker engine kurduğumuzda o makinede hem docker server (daemon) hem de docker client (docker cli) kurulmuş olur 114 | - İ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. 115 | 116 | ![docker-components](./static/giris/giris-1.png) 117 | 118 | 119 | ## Image ve Container (Docker) 120 | - Docker image'lerde kernel'e gerek yoktur 121 | - Image'ler birer şablondur 122 | - Bir image'i bir yerde depolayabilirsem, docker engine sayesinde bu image'i çalıştırabilirim 123 | - Container'lar sayesinde image'leri depolayabiliriz 124 | - Container dediğimiz şey aslında bir nevi image'lerin çalışır halidir. Container image şablonunun çalışan kopyasıdır olarak düşünebiliriz 125 | - Bu sayede her sistemde her seferinde aynı sonucu alırız. Bir yerde çalışan container her yerde çalışır 126 | 127 | ## Image Registry 128 | - Container Registry, Container Image Registry, Docker Registry olarak da bilinir 129 | - Docker imajlarını depolayıp dağıtabildiğimiz bir alt yapı servisidir 130 | - En bilineni Docker Engine'ın default olarak baktığı yer olan [Docker Hub](https://hub.docker.com/)'dır 131 | 132 | 133 | ## Kurulum Yapmadan Docker Kullanmak 134 | - [Play With Docker](https://labs.play-with-docker.com/) hizmeti sayesinde cloud ortamında Docker denemeleri yapabiliriz 135 | - Tek kötü yanı bir oturumda en fazla 4 saat kullanmamıza izin vermesidir 136 | 137 | 138 | # Container 101 139 | ## Docker CLI 140 | - Docker Daemon'u yönetmemizi sağlar 141 | - `docker version` -> Docker kurulumu ile ilgili temel bilgilere erişiriz 142 | - `docker info` -> Docker ile ilgili temel bilgilere erişiriz (kaç container çalışıyor, drivers vb.) 143 | - `docker` -> Docker CLI'da kullanabileceğimiz komutları listeler 144 | - **Options** 145 | - Docker Daemon'a bağlanırken kullanacağımız parametreler gözükür 146 | - **Management Commands** 147 | - Yönetebileceğimiz bileşenlerin listesi 148 | - **Commands** 149 | - Yönetmek istediğimiz bileşen için çalıştırmak istediğimiz komut 150 | - `docker image --help` -> image bileşeni ile kullanabileceğimiz komutları listeler 151 | 152 | ## Container Temelleri-1 153 | - `docker container --help` -> container bileşeni ile kullanabileceğim komutlar 154 | - `docker container run` -> parametre olarak verdiğimiz isimde bir container varsa başlatır yoksa önce oluşturur sonra başlatır 155 | - `docker 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ı 156 | - `docker container ls -a` -> sistemdeki tüm container'ları listeler. -a olmasaydı sadece çalışan container'ları listelerdi 157 | - **Container içerisindeki varsayılan olarak çalışması için ayarlanan uygulama durduğunda container'da kapatılır** 158 | 159 | 160 | ## Container Temelleri-2 161 | - `docker container run ` 162 | - `docker container run -p 80:80 ozgurozturknet/adanzyedocker` 163 | - 80:80 portunda çalışan bir web servisi çalıştırır (hazır imaj) 164 | - `docker container ls` komutu ile bu container'ı görebiliriz. Çünkü bu çalışıp kapanan bir uygulama değildir 165 | - `docker container logs ` -> ID'si verilen container'a ait logları gösterir 166 | - `docker container stop ` -> ID'si verilen container'ı durdurur 167 | - `docker container start ` -> ID'si verilen container'ı başlatır 168 | - `docker container run -d -p 80:80 ozgurozturknet/adanzyedocker` 169 | - **-d** detach'ten gelmektedir. Container direkt arka planda çalışmaya başlar (terminalimize bağlamaz) 170 | - `docker container rm ` -> ID'si verilen container'ı siler 171 | - illa tam id vermek zorunda değiliz id'nin ilk harflerini versek de olur 172 | - Çalışan bir container silinemez bunu öncelikle durdurmamız gerekir ya da **-f** parametresi kullanılarak **force** ederek sileriz 173 | - `docker container prune` 174 | - sistemdeki çalışmayan tüm container'ları siler 175 | 176 | 177 | ## Container Temelleri-3 178 | - `docker container run --name websunucu -p 80:80 -d ozgurozturknet/adanzyedocker` 179 | - websunucu adında bir container'ı adanzyedocker imajından oluşturdu ve arka planda çalıştırdı (127.0.0.1'e giderek görebilirsiniz) 180 | - `docker container exec -it ` 181 | - `it` -> interaktif olarak container'a bağlan demek 182 | - `docker container exec -it websunucu sh` 183 | - websunucu container'ına bağlan ve sh komutunu çalıştır (shelle bağlanır) 184 | - `ctrl + p q` kombinasyonu ile Container'ı kapatmadan arka plana alabiliriz 185 | - `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. 186 | 187 | 188 | ## Docker Katmanlı Dosya Sistemi Yapısı 189 | - Docker depolama alt yapısında **union file system** adı verilen bir yapı kullanır 190 | - Docker imajları mevcut bir base imaj üzerine inşa edilir 191 | - Bu imaj üzerine yapılan her değişiklik birer katman olarak eklenir ve bu katmanlar birer dosya olarak saklanır 192 | 193 | 194 | ## Docker Container Yaşam Süresi (Lifecycle) 195 | - Tüm ayarlamalar image oluşturma aşamasında yapılandırılır 196 | - Tek bir uygulama çalıştırması için dizayn edilir 197 | - Bir sorun olursa saniyeler içerisinde yeni bir kopya oluşturulabilir 198 | - Sorun container'a bağlanılarak çözülmez 199 | - Container içerisinde çalışan ana uygulama durduğu zaman container'da durdurulur 200 | - 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 201 | - Container'lar yeniden oluşturulduğunda container içerisindeki veriler sıfırlanır, bunları container dışında tutmamız gerekir 202 | 203 | 204 | ## Docker Volume-Container Dışı Veri Saklama 205 | - 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 206 | - Volume'ler Container'lar dışında veri saklamak istediğimiz zaman çok kullanışlıdır 207 | - `docker volume create ` -> parametre olarak verilen isimde bir volume oluşturur 208 | - `docker volume create ilkvolume` 209 | - `docker volume inspect ` -> volume detaylarını verir 210 | - `docker volume inspect ilkvolume` 211 | - `docker container run -it -v ilkvolume:/uygulama alpine sh` 212 | - alpine imajından bir container oluşturuyorum 213 | - **-it** ile container'a interaktif olarak bağlanıp **sh** komutunu çalıştırıyorum 214 | - **-v** ile ilkvolume adındaki volume'u container içerisindeki /uygulama adındaki klasöre bağlıyorum 215 | - `-v :` 216 | - Örneğimiz gereği aşağıdaki işlemleri gerçekleştiriyoruz 217 | - `cd uygulama` 218 | - `touch test` 219 | - `echo "naber nasılsın?" > test` 220 | - `exit` ile 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) 221 | - `docker volume ls` -> komutu ile volume'leri listeleriz 222 | - `docker container run --name mydebiancontainer -it -v ilkvolume:/uygulama debian sh` 223 | - 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 224 | - burdan aynı şekilde klasöre gidip cat ile dosya içerisine bakarsak yazdığımız verinin orda bulunduğunu görebiliriz 225 | 226 | 227 | ## Docker Boş-Dolu Volume Davranışları 228 | - 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? 229 | - Eğer volume imaj içinde bulunan mevcut klasöre mount edilirse: 230 | - Klasör boşsa o anda volume içinde hangi dosyalar varsa bu klasörde de o dosyaları görürüz 231 | - Klasörde dosya varsa ve volume boşsa klasördeki **dosyalar volume'e kopyalanır** 232 | - 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 233 | 234 | 235 | 236 | ## Bind Mounts 237 | - Host makinada (kendi local makinamız) bulunan bir klasörü veya dosyayı Container içerisinde map etmeye **Bind Moun** denir 238 | - `docker container run -d -p 80:80 --name mynginx nginx` -> basit bir web sunucu oluşturduk 239 | - `docker container exec -it mynginx sh` -> container'a bağlanıyoruz 240 | - `cd /usr/share/nginx/html` -> bize default olarak serve edilen dosya 241 | - Şimdi bu container'ı siliyoruz ve aşağıdaki komutu çalıştırıyoruz 242 | - `docker container run -d -p 80:80 -v /Users/mebaysan/Desktop/mydockertest:/usr/share/nginx/html nginx` 243 | - -d ile container'ın arka planda çalışmasını sağlıyoruz 244 | - -p ile port set ediyoruz 245 | - -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 246 | - nginx -> imaj adı 247 | - Unutmamalıyız ki bu yöntem development aşamasında kullanılır, kesinlikle production ortamında kullanmamalıyız! 248 | 249 | 250 | # Container 102 251 | 252 | ## Docker Network Driver 253 | - Ek protokol vb getirmeden ağ işlemlerini gerçekleştirebiliriz 254 | - Container sistemlerinin iletişim altyapısını network driver'ları ile sağlıyoruz 255 | - Temel 5 driver vardır 256 | - Bridge 257 | - Varsayılan driver'dır 258 | - Network objesi oluşturulurken özellikle başka bir driver belirtilmezse bridge driver ile oluşturulur 259 | - 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 260 | - Host 261 | - Her sistemde host driver ile oluşturulmuş "Host" adında bir driver vardır 262 | - 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 263 | - Macvlan 264 | - 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 265 | - None 266 | - Container'a hiç bir şekilde ağ bağlantısı olmasın istersek None driver kullanılır 267 | - Overlay 268 | - Ayrı hostlar üzerindeki container'ların aynı ağda çalışıyormuş gibi çalışması istendiği zaman Overlay network'ler kullanılır 269 | 270 | 271 | 272 | ## Docker Network Objeleri-1 273 | - `docker network ls` -> sistemdeki kurulu network objeleri listeler 274 | - `docker network inspect bridge` -> bridge NAME'ine sahip objenin özelliklerini listeler 275 | - `docker container run --net ` 276 | - `--net` ile network objesini vererek ilgili network'e bağlanabiliriz 277 | - `docker container run --net none ` -> container'a ağ bağlantısı olmaz (none) 278 | 279 | 280 | 281 | ## Docker Network Objeleri-2-Port Publish 282 | - 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. 283 | - **Örnek olarak** container içerisindeki servis 80 portundan dinliyor. Biz `-p` ya da `--publish` parametresi ile bu portu belirleriz ve bu sayede host makineye 80 portundan gelen istekleri container'ın 80 portuna iletiriz. 284 | - Bu işleme **port publish** denir. Notasyon şu şekildedir 285 | - `-p :` 286 | - `-p 80:80` -> örnek 287 | - `-p 8080:80 -p 8043:443` -> birden fazla port publish yapabiliriz 288 | - **Default olarak TCP portları açılır. Eğer istersek UDP portları açabiliriz** 289 | - `-p 80:80/udp` 290 | 291 | 292 | ## Docker Network Objeleri-3 293 | - Container'lar arası network izolasyonu sağlamak istersek ayrı bridge'ler oluşturarak bunu sağlayabiliriz 294 | - Default bridge network içerisinde dns çözümlemesi yok 295 | - Varsayılan dışında ip aralıkları tanımlayabiliriz 296 | - Kullanıcı tanımlı bridge network'e bağlı container'lar birbirleriyle isimler üzerinden haberleşebilirler. Dns çözümlemesi sağlar 297 | - Container'lar çalışır durumdayken de kullanıcı tanımlı bridge network'lere bağlanıp, bağlantıyı kesebilirler 298 | - `docker container run -d --name websunucu ozgurozturknet/adanzyedocker ` -> websunucu adında bir container oluşturuyorum 299 | - `docker container run -it -d --name database1 ozgurozturknet/adanzyedocker sh` -> database1 adında bir container oluşturup içine giriyorum. 300 | - `ping websunucu1` ile ilk container'a erişmeye çalışıyorum 301 | - `/usr/src/myapp # ping websunucu` 302 | - `ping: websunucu: Name does not resolve` -> o container'a direkt container adı ile erişemiyorum; çünkü default bridge network'de dns çözümlemesi yok 303 | - Fakat IP adresi üzerinden erişebiliriz yani aralarında bağlantı var 304 | - Şimdi container'ları siliyoruz ve kendi bridge'mizi oluşturup container'ları yeniden oluşturacağız 305 | - `docker network create mybridge` -> mybridge adında bir bridge network oluşturduk. Opsiyon girmediğimiz için default olarak bridge oluşturdu 306 | - `docker network create --driver=host myhost` -> host network'u oluşturur 307 | - `docker network ls` -> network driver'lar listelenir 308 | - `docker network inspect mybridge` -> network driver'ımızı inceliyoruz 309 | - `docker container run -d --name websunucu --net mybridge ozgurozturknet/adanzyedocker` -> websunucu adında bir container oluşturduk ve mybridge driver'ına bağladık 310 | - `docker container run -d --name database --net mybridge ozgurozturknet/adanzyedocker` -> database adında bir container oluşturduk ve mybridge driver'a bağladık 311 | - `docker network inspect mybridge` -> mybridge adındaki driver'a bakıyoruz ve bağlı olan container'ları görüyoruz 312 | - `docker container exec -it websunucu sh` -> websunucu container'ına bağlanıyoruz 313 | - `ping 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 314 | - `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 315 | - Kullanıcı tanımlı bridge'lerin en önemli özelliklerinden birisi de container'lar çalışırken bu bridge'lere bağlanabilirler 316 | - Notasyon şu şekildedir: 317 | - `docker network connect ` 318 | - `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! 319 | - `docker attach database` -> çalışan bir container olan database'e bağlanıyoruz 320 | - `ifconfig` -> yazdığımızda göreceğiz ki **eth1** (mybridge2) gelmiş 321 | - `docker network disconnect mybridge2 database` -> database container'ı mybridge2'den düşürüyoruz 322 | - `docker network rm mybridge2` -> driver'ı sildik (bağlı bir container olmaması gerek) 323 | 324 | 325 | ## Logging Uygulama Günlükleri 326 | - Docker araçlarını kullanarak loglara erişebiliriz 327 | - `docker container run -d --name mycont1 ozgurozturknet/app1` -> arka planda mycont1 adında bir container oluştur 328 | - `docker logs mycont1` -> mycont1 adındaki container'a ait loglar 329 | - `docker container run -d --name mycont2 -p 80:80 nginx` -> container oluşturup 127.0.0.1 adresine gidip 3-5 kere refresh yapıyorum 330 | - `docker logs mycont2` -> container'a ait loglar 331 | 332 | 333 | ## Docker Stats ve Top 334 | - Container; tek bir uygulamanın ya da servisin paketlenmiş halidir, sürekli olarak container içerisine girmeyiz. 335 | - `docker top ` -> ilgili container içerisinde çalışan process'leri listeler 336 | - `docker stats ` -> ilgili container'ın ne kadar kaynak kullandığını gösterir 337 | - `docker stats` -> tüm container'ların kaynak kullanımını gösterir 338 | 339 | 340 | 341 | ## Container Cpu ve Memory Limitleri 342 | - **Eğer container oluştururken limitler koymazsak her container; sistem kaynaklarını sınırsız olarak kullanır** 343 | - `docker container run -dit --name mycont alpine` -> bir container oluşturuyorum 344 | - `docker attach mycont` -> komutu ile container'a bağlanabilirim 345 | - `ctrl + p q` kombinasyonu ile arka plana atabilirim (çalışmaya devam eder) 346 | - `docker container run -d --memory=100m alpine` -> max 100mb kullanabilecek bir container oluşturdu 347 | - `docker container run -dit --name mytest --memory=100m alpine` -> mytest adında bir container oluşturuldu, max 100m kullanabilecek 348 | - `m` -> megabyte 349 | - `g` -> gigabyte 350 | - `k` -> kilobyte 351 | - `b` -> byte 352 | - `docker container run -dit --memory=100m --memory-swap=200m alpine` -> eğer memory limiti aşılsa bile swap olarak 200m daha kullanabilecek 353 | - `docker container run -dit --cpus="1.5" alpine` -> oluşturduğumuz container sistem içerisinde ne kadar core varsa onun sadece 1.5 tanesini kullanabilecek 354 | - `docker container run -dit --cpus="1.5" --cpuset-cpus="0,3" alpine` -> sadece cpu 0 ve cpu 3'ü kullanabil dedik 355 | 356 | 357 | 358 | ## Environment Variables (Ortam Değişkenleri) 359 | - İşletim sistemi bazında tanımlanan ve her yerden çağrılabilen değişkenlerdir 360 | - Linux sistemlerde: 361 | - `printenv` ile tüm ortam değişkenlerini gösterir 362 | - `echo $` -> ilgili değişkenin değerini verir 363 | - `export =` -> değişken tanımlamamızı sağlar 364 | - `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**. 365 | - Container içerisinde `printenv` kullanırsak (alpine linux olduğundan) tanımladığımız değişkenleri görebiliriz 366 | - `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 367 | - Eğer istersek bir dosya içerisinde tüm ortam değişkenlerini tanımlayıp tek komut ile de bunu gönderebiliriz 368 | - `touch env.list` 369 | - `echo "VAR1=deneme1" >> env.list` 370 | - `echo "VAR2=deneme1" >> env.list` 371 | - `echo "VAR3=deneme1" >> env.list` 372 | - Değişkenleri dosya içerisine ekledim 373 | - `docker container run -it --env-file ./env.list alpine sh` -> **--env-file** parametresi sayesinde liste olarak environment'leri gönderdik 374 | 375 | 376 | 377 | # Image ve Registry 378 | 379 | ## Image İsimlendirme ve Tag Yapısı 380 | - Docker imajına verilen isim aynı zamanda o imajın nerede depolandığını da belirtir 381 | - Docker imaj adı ile container oluşturabildiğimiz gibi imaj ID'sini de kullanarak imajlardan container oluşturabiliriz 382 | - Docker imaj yapısı: 383 | - `/:` 384 | - `docker.io/mebaysan/test:latest` 385 | - **docker.io** olmasının sebebi varsayılan olarak docker hub registry'den imaj çekilmesidir. Eğer istersek farklı registry'leri belirtebiliriz: 386 | - `docker image pull gcr.io/google-containers/busybox` -> örnek olarak google image registry'den busy box adındaki imajı çektik 387 | - Tag'ler sayesinde tek repository içinde birden fazla versiyon tutabiliriz 388 | - `docker image pull ` -> komutu sayesinde local sistemimize bir imajı çekeriz 389 | - Tag belirtmediğimiz müddetçe default olarak `latest` tag'ı kullanılır 390 | - `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. 391 | 392 | 393 | 394 | ## Image oluşturma 395 | 396 | ### Dockerfile-1 397 | - Docker imajı oluşturmak istersek öncelikle Dockerfile adında bir dosya oluşturmamız gerekir 398 | 399 | #### Dockerfile Parametreleri 400 | - Daha detaylı bilgi için [buraya](https://github.com/ozgurozturknet/AdanZyeDocker/blob/master/kisim5/bolum47/Dockerfile%20Talimatlari%20Aciklamasi.txt) Özgür hocanın repository'sine bakınız. Bu parametreleri ve açıklamalarını onun reposundan aldım. 401 | - **FROM** 402 | - Oluşturulacak imajın hangi imajdan oluşturulacağını belirten talimat. Dockerfile içerisinde geçmesi mecburi tek talimat budur. Mutlaka olmalıdır. 403 | - Ör: FROM ubuntu:18.04 404 | - **LABEL** 405 | - İ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. 406 | - Ör: LABEL version:1.0.8 407 | - **RUN** 408 | - İ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. 409 | - Ör: RUN apt-get update 410 | - **WORKDIR** 411 | - 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. 412 | - Ör: WORKDIR /usr/src/app 413 | - **USER** 414 | - gireceğimiz komutları hangi kullanıcı ile çalıştırmasını istiyorsak bu talimat ile onu seçebiliriz. 415 | - Ör: USER poweruser 416 | - **COPY** 417 | - İmaj içine dosya veya klasör kopyalamak için kullanırız 418 | - Ör: COPY /source /user/src/app 419 | - **ADD** 420 | - 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. 421 | - Ör: ADD https://wordpress.org/latest.tar.gz /temp 422 | - **ENV** 423 | - Imaj içinde environment variable tanımlamak için kullanılır 424 | - Ör: ENV TEMP_FOLDER="/temp" 425 | - **ARG** 426 | - 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. 427 | - Ör: ARG VERSION:1.0 428 | - **VOLUME** 429 | - 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. 430 | - Ör: VOLUME /myvol 431 | - **EXPOSE** 432 | - Bu imajdan oluşturulacak containerların hangi portlar üstünden erişilebileceğini yani hangi portların yayınlanacağını bu talimatla belirtirsiniz. 433 | - Ör: EXPOSE 80/tcp 434 | - **ENTRYPOINT** 435 | - Bu talimat ile bir containerın çalıştırılabilir bir uygulama gibi ayarlanabilmesini sağlarsınız. 436 | - Ör: ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] 437 | - **CMD** 438 | - Bu imajdan container yaratıldığı zaman varsayılan olarak çalıştırmasını istediğiniz komutu bu talimat ile belirlersiniz. 439 | - Ör: CMD java merhaba 440 | - **HEALTHCHECK** 441 | - 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. 442 | - Ör: HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1 443 | - **SHELL** 444 | - 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. 445 | - Ör: SHELL ["powershell", "-command"] 446 | 447 | 448 | 449 | ### Dockerfile-2 450 | - Aşağıdaki örnek senaryo için [buraya](./uygulamalar/Dockerfile-2/Dockerfile) bakabilirsiniz. Comment line'lar ile desteklenmeye çalışıldı. 451 | - Ubuntu 18.04 yüklü bir sistem kur 452 | - İşletim sistemini güncelle 453 | - Python kur 454 | - Uygulamayı sisteme kopyala 455 | - Sistem başladığında uygulamanın başlamasını ayarla 456 | - `docker image build -t -f .` 457 | - `docker image build -t mebaysan/ilkimaj .` 458 | - ilkimaj adında bir imaj oluşturur 459 | - **.** -> 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 460 | - Dockerfile'ın olduğu dizinde bir adet Dockerfile olduğundan ekstra -f parametresini girmeme gerek yok 461 | - `docker image ls` komutu ile sistemimizdeki mevcut imajları görebiliriz 462 | - `docker container run mebaysan/ilkimaj` komutu ile oluşturduğumuz imajdan bir container oluşturduk ve ekran çıktısnı gördük 463 | - `docker image history ` komutu ile imajın geçmişini görebiliriz 464 | - `docker image history mebaysan/ilkimaj` 465 | 466 | 467 | ### Dockerfile-3 468 | - Localde oluşturduğumuz bir Docker imajını hub'a göndermek için öncelikle CLI'da login olmamız gerekir 469 | - `docker login` -> komutu ile login olabiliriz 470 | - `docker image push ` komutu ile localdeki istediğimiz image'i hub'a pushlayabiliriz 471 | - `docker image push mebaysan/ilkimaj` -> ilgili imajı pushlar 472 | 473 | 474 | 475 | ### Dockerfile-4 476 | - Bir flask uygulamasını container'da çalıştırıyoruz. Daha detaylı bilgi için [buraya](./uygulamalar/Dockerfile-4/pythonapp/) bakabilirsiniz. 477 | - O klasördeki Docker imajı oluşturmak için: 478 | - `docker image build -t mebaysan/basitflaskimaj .` komutunu kullanıyorum 479 | - Oluşturduğum imajdan bir container oluşturmak için: 480 | - `docker container run --rm -p 80:5000 mebaysan/basitflaskimaj` 481 | - `--rm` -> container kapanınca otomatik olarak sil (bir daha silmekle uğraşmayalım) 482 | - `-p` -> bu makinaya 80 portundan gelen istekleri container'ın 5000 portuna yönlendir. Flask uygulaması 5000 portundan ayağa kalktığı için 483 | 484 | 485 | 486 | ### Linux Shell Trickleri 487 | - `echo` komutu sayesinde bir değeri çıktı olarak verir 488 | - `>` sayesinde bir komutun çıktısını yönlendiririz 489 | - `echo "deneme" > deneme.txt` 490 | - `&` komutun sonuna eklersek komutu arka plana atar, arkada çalışır 491 | - `|` 1. komutun çıktısını 2. komuta iletmeye sağlar 492 | - `cat dosya | grep "naber"` dosya içeriğini okur çıktıyı grep'e yollar, içerisinde naber geçenleri filtreler 493 | - `ls ; date` -> **;** sayesinde aynı anda birden fazla komut çalıştırmamızı sağlar 494 | - `&&` -> VE 495 | - `||` -> VEYA 496 | 497 | 498 | 499 | ### Dockerfile-5 500 | - Healthcheck konusunu gördüğümüz dosyaya [buradan](./uygulamalar/Dockerfile-5/Dockerfile) bakabilirsiniz 501 | - İmaj oluşturmak için: 502 | - `docker image build -t mebaysan/basichealthcheck .` 503 | - Bu imajdan container oluşturmak için: 504 | - `docker container run -d --name mycont -p 80:80 mebaysan/basichealthcheck` 505 | - ENV örneği ile container oluşturmak için: 506 | - `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](./uygulamalar/Dockerfile-5/Dockerfile) içerisindedir 507 | 508 | 509 | 510 | ### ADD ve COPY Farkı 511 | - COPY -> belirttiğimiz dosya veya klasörü belirttiğimiz PATH'e atar 512 | - 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 513 | - Detaylar için [buraya](uygulamalar/ADD-COPY-FARKI/Dockerfile) bakabilirsiniz 514 | - Oluşturduğumuz Dockerfile ile imaj oluşturup aşağıdaki komut ile container oluşturuyoruz ve ADD sonucunu görüyoruz 515 | - `docker container run -it mebaysan/wpadd sh` 516 | 517 | 518 | 519 | ### ENTRYPOINT ve CMD Farkı 520 | - CMD için [buraya](uygulamalar/ENTRYPOINT-CMD-FARKI/cmd/Dockerfile) bakabilirsiniz 521 | - ENTRYPOINT için [buraya](uygulamalar/ENTRYPOINT-CMD-FARKI/entrypoint/Dockerfile) bakabilirsiniz 522 | - CMD runtime'da değişebilirken ENTRYPOINT runtime'da değiştirilemez 523 | - Her image'de en az 1 adet CMD veya ENTRYPOINT olmalıdır 524 | - Eğer hem CMD hem de ENTRYPOINT varsa, CMD'de yazılanları ENTRYPOINT'e parametre olarak geçer 525 | 526 | 527 | ### Exec Form ve Shell Form Farkı 528 | - Exec Form => `CMD ["python", "app.py"]` 529 | - Shell Form => `CMD python app.py` 530 | - 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 531 | - 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 532 | - Exec formunda çalıştırılan komutlar herhangi bir shell processi çalışmadığı için Environment Variable gibi bazı değerlere erişemezler. 533 | - 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 534 | 535 | 536 | 537 | ### Multi-stage Build 538 | - İ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. 539 | - Ö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 540 | - Örnekler için [buraya](uygulamalar/MultiStageBuild/Dockerfile) bakabilirsiniz 541 | 542 | 543 | 544 | ### ARG 545 | - İ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. 546 | - Örnek için [buraya](uygulamalar/ARG/Dockerfile) bakabilirsiniz. 547 | - Örnek bir Build Arg gönderimi 548 | - `docker image build -t mytest2 --build-arg VERSION=3.8.1 .` 549 | 550 | 551 | 552 | 553 | 554 | ### Docker Commit 555 | - Dockerfile olmadan da docker imaj oluşturabiliriz 556 | - Doğru kullanım Dockerfile olsa da tek yöntem bu değildir 557 | - Öncelikle localimizde bir container oluşturur ve içerisinde gerekli kurulumları vs yaparız 558 | - Ardından `docker commit ` komutu ile o container'dan bir imaj oluşturmuş oluruz 559 | - Ör: `docker commit localcont1 mebaysan/prodcont1:latest` 560 | - `docker commit -c 'CMD ["command 1", "command 2"]' ` -> -c parametresi ile CMD, EXPOSE vb. komutları bu imaja ekleyebiliriz 561 | 562 | 563 | ### Docker Save-Load 564 | - Save komutu sayesinde localde oluşturduğumuz bir imajı `.tar` dosyası olarak kayıt edebiliriz, ve internet erişimi olmasa bile (hub'dan çekemiyor demektir) sunucuya atabiliriz 565 | - `docker save -o .tar` 566 | - `docker save mebaysan/test -o mebaysantestimaj.tar` 567 | - Load komutu ile `.tar` olarak gelen docker dosyasını sisteme imaj olarak yükleyebiliriz 568 | - `docker load -i ` 569 | - `docker load -i mebaysantestimaj.tar` 570 | 571 | 572 | 573 | 574 | ### Registry 575 | - Kendi ağımızda ücretsiz olarak bir docker deposu oluşturabiliriz 576 | - Bunun için yine Docker Hub üzerinden :blush: [registry](https://hub.docker.com/_/registry) imajını kullanacağız 577 | - 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. 578 | - `docker pull registry` imajı locale çekiyoruz 579 | - `docker container run -d -p 5000:5000 --restart always --name registry registry` 580 | - restart parametresi container down olduğunda ne yapılacağını alır 581 | - `always` -> down olunca ne olursa olsun restart at 582 | - `no` -> down olunca bir şey yapma 583 | - `on-failure` -> sadece hata olur da kapanırsa yeniden başlat fakat biz elimizle manuel kapatırsak yeniden başlatma 584 | - `unless-stopped` -> manuel olarak stop edersek başlatmaz fakat geri kalan her durumda başlatır 585 | - 5000 portunu 5000 portuna publish ettik 586 | - registy adındaki container'ı registry imajından oluşturduk 587 | - `http://127.0.0.1:5000/` altında çalışmaya başlar 588 | - `http://127.0.0.1:5000/v2/_catalog` altında kayıtlı repoları gösterir, 589 | - `localcont1` adında bir imaj oluşturduğumuzu varsayalım 590 | - `docker push localhost:5000/localcont1` -> localdeki imajı registry'e kayıt etti 591 | - `docker pull localhost:5000/localcont1` bu adrese erişebilen makinalar; komutu ile local registry'deki imajı çekebilir 592 | 593 | 594 | # Compose ve Swarm 595 | 596 | 597 | ## Docker Compose 598 | - Compsoe, çoklu Docker uygulamalarını oluşturmak ve çalıştırmak için kullanılan bir araçtır 599 | - Compose ile uygulamanın hizmetlerini yapılandırmak için bir YAML dosyası kullanılır 600 | - Daha sonra tek bir komut ile tüm hizmetleri yapılandırmaya başlar ve sistemi başlatırız 601 | - Compose production için çok uygun bir araç değildir. Development aşaması için idealdir 602 | - Compose, Docker Engine ile birlikte gelen bir araç değildir. Bunu ayrıca sisteme kurmamız gerekir. 603 | - Mac ve Windows sistemlerde Docker Desktop kurduğumuzdan bu uygulama ile birlikte kurulu olarak Compose gelmektedir 604 | - `docker-compose.yml` dosyası içerisinde gerekli konfigürasyonlar tutulur 605 | - `docker-compose up -d` ile .yml dosyası kullanılarak sistem ayağa kaldırılır 606 | - `docker compose down` ile sistem kapatılır 607 | 608 | 609 | 610 | ### Docker Compose CLI 611 | - docker-compose komutlarını kullanmak için yml dosyası ile aynı dizinde olmamız önemlidir 612 | - `docker-compose up` -> **aynı dizindeki** docker-compose.yml dosyasını kullanarak sistemi başlatır 613 | - `docker-compose up -d` -> arka planda (detach) çalıştırır 614 | - docker objelerini isimlendirirken; sistemdeki diğer objeler ile çakışmasın diye docker-compose.yml dosyasının bulunduğu klasör adıyla başlayan isimlendirme yapar -> `klasorAdi_objeAdi` 615 | - `docker-compose down` -> tüm servisleri (docker objeleri) kapatır ve siler 616 | - **her şeyi siler fakat volume'leri silmez** 617 | - `docker-compose config` ile docker-config.yml dosyasını gösterir 618 | - `docker-compose images` -> servislerin hangi imajlarla oluştuğunu gösterir 619 | - `docker-compose logs` -> tüm servislerin loglarını listeler 620 | - `docker-compose exec` -> compose ile oluşturduğumuz servisin içinde komut çalıştırır 621 | - `docker-compose exec ` 622 | 623 | 624 | 625 | 626 | ### Docker Compose Yaml Dosyası 627 | - Detaylar için [buraya](uygulamalar/Compose/intro/docker-compose.yml) bakabilirsiniz 628 | - İlgili dizinde `docker-compose up -d` komutu sayesinde bu config dosyasından sistemi ayağa kaldırıyorum. `http://127.0.0.1/` adresine gittiğimizde başarılı bir şekilde wordpress kurulumunu görmüş olacağız 629 | 630 | 631 | 632 | ### Docker Compose Build 633 | - İstersek **imajımızı** compose ayağa kalkarken oluşacak şekilde ayarlayabiliriz 634 | - Bunun için docker-compose.yml dosyası ile aynı dizinde bir Dockerfile oluşturmamız gerekir. Dockerfile içerisinde istediğimiz imajı hazırlarız. 635 | - Compose file içinde ise servisi hazırlarken image yerine `build` key'ini kullanırız ve build olacak Dockerfile'ı aynı dizinde olduğundan `.` ile belirtiriz 636 | ![compose-build](./static/compose/Screen%20Shot%202021-01-17%20at%2012.17.21.png) 637 | - Daha detaylı bilgi için [buraya](https://github.com/ozgurozturknet/AdanZyeDocker/tree/master/kisim6/bolum68) bakabiliriz 638 | - Kod içerisinde güncelleme yaptığımızda ise önce imajı güncellememiz gerekir. Bunun için de `docker-compose build` komutunu kullanır önce build aldığımız imajı güncelleriz. Sonrasında `docker-compose up` ile servisleri ayağa kaldırırız 639 | 640 | 641 | 642 | 643 | ## Container Orchestration 644 | - Container Orchestration, containerların dağıtımını, yönetimini, ölçeklendirilmesini ve ağ oluşturulmasını otomatikleştirme işlemine denir 645 | - Yüzlerce container'ı bir arada yönetmek için kullanılan yazılımlardır 646 | - En bilinen araçlar: 647 | - **Swarm** 648 | - Docker engine ile gelen bir araçtır. Docker tarafından geliştirilmiştir 649 | - Bir Docker ana bilgisayar havuzunu tek bir sanal ana bilgisayara dönüştürür 650 | - **Kubernetes** 651 | - Neredeyse sektör standardı haline gelmiştir 652 | - Container uygulamalarının dağıtımını, ölçeklendirilmesini ve yönetimini otomatikleştirmek için oluşturulmuş açık kaynaklı bir sistemdir 653 | - Kolay yönetim ve keşif için uygulamayı oluşturan container'ları mantıksal birimler halinde gruplandırır 654 | - Google'da 15 yıldan fazla süreye sahip olan container deneyiminin açık kaynak topluluk dünyası üyelerinin tecrübelerine eklenerek oluşturulmuştur 655 | 656 | 657 | 658 | ### Docker Swarm 659 | - Docker Engine'e gömülü bir container orchestration çözümüdür 660 | - Bir docker ana bilgisayar havuzunu tek bir sanal ana bilgisayara dönüştürür 661 | - Hostlar arasında şu portlar açık olmalıdır 662 | - TCP port 2377 -> Cluster yönetimi 663 | - TCP ve UDP port 7946 -> Nodelar arası iletişim 664 | - UDP port 4789 -> Overlay network 665 | 666 | 667 | 668 | ### Swarm Manager ve Worker Node 669 | #### Manager Node 670 | - Bir adet manager tarafından diğer hostlar yönetilir 671 | - docker swarm init komutunu çalıştırdığımızda üzerinde bulunduğumuz host sistemi engine moddan swarm mode geçirir 672 | - Swarm birden fazla manager node destekler ve bu sayede yüksek erişilebilirlik sağlar. Bir managerda sorun olursa diğer manager devreye girer ve iş yürümeye devam eder 673 | - Manager nodelardan yalnızca 1 tanesi lider olarak seçilidir ve tüm yönetim lider tarafından yapılır. Diğer manager nodelar pasif durumdadır. Pasif manager nodelardan birine bir komut verip iş yapmasını istersek bu sadece proxy görevi görür ve komutu lider node'a iletir 674 | - Birden fazla manager olan ortamlarda bir adet lider seçilmelidir. Swarm bunu otomatik halleder ve bunun için Raft Consensus algoritmasını kullanır. Raft algoritması; lider seçimi için kuralları belirlemeye yarar. Mesela ortamda 5 manager olan durumda bir şekilde lider olan nodea erişilemezse belirli bir zaman sonra kalan 4 node kendi aralarında oylama yaparak lider belirler. Artık swarm-cluster'ın yönetimi bu lider tarafından yapılır 675 | - Raft algoritması yalnızca (n-1)/2 sayıda nodeun devre dışı kalmasını tolere edebilir. (5 node için max 2 hata tolere) Aksi halde yönetim altyapısı çalışmayacaktır 676 | - Raft algoritmasının düzgün çalışabilmesi için ve lider seçiminin sorunsuz olması için ortamın her zaman tek sayıda manager nodela kurulmuş olması gerekir. 7'den fazla manager olduğu durumlarda ortamda daha fazla sorun çıkması muhtemeldir. 677 | 678 | #### Worker Node 679 | - Swarm cluster kurulur, ve cluster'a worker node olarak dahil ol deriz 680 | - Manager node'dan sertifika çekerler ve emir beklerler 681 | - İstediğimiz sayede worker node ekleyebiliriz 682 | 683 | ### Docker Swarm init 684 | - Bu bölüm için [labs.play-with-docker.com](https://labs.play-with-docker.com/) adresine gidiyorum ve 5 adet instance oluşturuyorum 685 | - Bir hostu swarm moda alacağız 686 | - `docker swarm init --advertise-addr 192.168.0.8` bu hostun swarm modunu aktif ediyoruz (192.168.0.8 play with docker tarafından kullandığımız hosta verilen IP) 687 | - advertise-addr -> host üzerindeki kullanmak istediğimiz network kartına ait adres 688 | - `docker swarm join-token manager` -> bir nodeu cluster'a manager olarak eklemek için gerekli olan komutu ve tokeni verecek 689 | - manager olarak eklemek istediğimiz node'a (hosta,makinaya,cihaza) gidip ilgili komutu yapıştırdığımızda cluster'a manager olarak eklenecek 690 | - `docker swarm join-token worker` -> bir node'u cluster'a worker olarak eklemek için gerekli olan komutu ve tokeni verecek 691 | - aynı şekilde worker olarak eklemek istediğimiz node'da çalıştırıp nodeu worker olarak cluster'a ekleyeceğiz 692 | - swarm mode'u aktif ettiğimiz node'a gidip `docker node ls` komutu ile cluster hakkında bilgi sahibi olabiliriz 693 | - swarm manager olan node'a gidip `docker service create --name test --replicas=5 -p 8080:80 nginx` komutu ile 694 | - adı test olan (--name) 695 | - 8080 portu 80 portuna publish edilmiş (-p) 696 | - nginx imajından 697 | - 5 adet container oluştur (--replicas=5) 698 | - `docker service ps ` -> adı verilen service hakkında bilgi getirir 699 | 700 | 701 | 702 | 703 | ### Swarm Service 704 | - Swarm service'lerinde 2 mod vardır. 705 | - **Replicated** 706 | - Aksini belirtmediğimiz sürece bu modda servis oluşturulur 707 | - Oluşturmak istediğimiz servisin kaç replica içereceğini belirtiriz 708 | - Swarm uygun nodelarda o sayıda replica oluşturur 709 | - **Global** 710 | - Servisin kaç replica içereceğini belirtmeyiz. Swarm altındaki her node üzerinde 1 replica oluşturur- 711 | - `docker service create --name test nginx` -> nginx imajından test adında servis oluştur 712 | - replika sayısını belirtmediğimiz için 1 adet oluşturdu 713 | - `docker service ls` -> service listesini görebiliriz 714 | - `docker service ps test` -> test adındaki servisi altındaki tasklara ait detayları görebiliriz 715 | - `docker service logs test` -> test servisi altındaki tüm container'lara ait logları gösterir 716 | - `docker service inspect test` -> test servisine ait detaylar 717 | - Swarm servislerinin en önemli özelliklerinden biri servislere hızlıca yeni replikalar oluşturabiliriz 718 | - `docker service scale test=3` ile test servisimize yeni 2 replika daha (zaten 1 replika ile oluşturmuştuk) ekliyor. Aynı şekilde azaltabiliriz de 719 | - `docker service rm test` -> test adındaki servisi sileriz 720 | - `docker service create --name myglb --mode=global nginx` -> servisi global modda oluşturur (her node üzerinde 1 replika) 721 | - Update işlemi 722 | - update yapınca servisteki containerlardan birini siler yerine yeni güncellenmiş container'ı koyar ve sıradaki eski container'a geçer, siler yerine güncellenmişi koyar ve diğerine geçer ... 723 | - `docker service create --name websrv --network over-net -p 8080:5000 --replicas=10 mebaysan/basitflaskimaj` 724 | - adı websrv olan 725 | - over-net adında oluşturulmuş network driver'a bağlı 726 | - 8080:5000 port publish yapılmış olan 727 | - 10 adet replikaya sahip bir servis oluştur (play with docker platformu üzerinde over-net adında bir overlay network oluşturdum & 3 manager 2 workerlı bir cluster oluşturmuştum) 728 | - `--update-delay` -> bu parametre, güncellemeler arasında ne kadar bekleyeceğini belirtmemizi sağlar (bir containeri sil gyerien güncellenmişi koy parametre kadar bekle diğerine geç gibi) 729 | - `--update-parallelism` -> bu parametre sayesinde aynı kanda kaç container'ın güncelleneceğini söyleriz (aynı anda 2 container sil güncelle 5 sn bekle diğer ikisine geç gibi) 730 | - `docker service update --detach --update-delay 5s --update-parallelism 2 --image mebaysan/basitflaskimaj websrv` 731 | - arkaplanda (detach) 732 | - 5 saniyede bir (update-delay) 733 | - aynı anda 2 container olacak şekilde 734 | - mebaysan/basitflaskimaj adındaki imajdan 735 | - websrv adındaki servisi güncelle 736 | - `docker service rollback --detach websrv` -> arkaplanda websrv adındaki servisi bir önceki haline getir 737 | 738 | 739 | ### Overlay Network 740 | - Overlay network aslında bir network driver'dır 741 | - Farklı merkezlerde bulunan nodelar sanki aynı merkezdeymiş gibi haberleşebilir 742 | - Bir swarm cluster oluşturulduğu zaman ingress adında bir overlay network de otomatik olarak oluşturulur. Aksini belirtmediğimiz sürece oluşturduğumuz servisler bu overlay network'e bağlanır 743 | - İstersek user defined overlay networkler de oluşturabiliriz 744 | - Overlay networklerin temel yönetim katmanının haberleşme altyapısı encryptedir. Fakat buraya bağladığımız containerların birbirleriyle iletişimi varsayılan olarak encrypted değildir. Overlay network oluştururken `--opt encrypted` parametresini kullanarak bu trafiğin de encrypted olmasını sağlayabiliriz. Bu opt encrypted overlay netowrk trafiğini biraz yavaşlatacaktır. 745 | - Aynı overlay network'e bağlı servislerin containerları birbirleriyle herhangi bir port kısıtlaması olmaksızın haberleşebilirler ve sanki aynı ağdaymış gibi çalışırlar. 746 | - Swarm altında yaratılan servisler aynı overlay network üzerinde birbirlerine servis isimleriyle ulaşabilir. Docker burada hem dns çözümlemesi hizmeti hem de load balancing hizmeti sağlar 747 | - Overlay network üzerinde port publsh de yapabiliriz. Swarm overlat networklerde ingress routing mesh destekler. Port publish edip Docker host üzerinden o porta erişirsek Docker o host üstünde o portun publish olduğu bir container bulunmasa bile bulunan bir host'a trafiği yönlendirecek ve cevap verecektir 748 | - `docker network create -d overlay over-net` -> adı over-net olan overlay bir network oluştur 749 | 750 | 751 | 752 | # Docker Secret 753 | - Conteinar'larda plain text olarak tutmamızın güvenlik zafiyeti oluşturabileceği username ve password gibi verileri secret objeleri şeklinde encrypted olarak transfer edebiliriz 754 | - Docker Swarm, aynı volume ve container'lar gibi birer Docker objesidir 755 | - Swarm altında bir isim ve değer şeklinde secretler oluşturabiliriz. Bu objeler Swarm cluster'ın raft deposunda encrypted olarak saklanıyor. Bu secretleri istediğimiz servislere bağlayabiliyoruz. Secret, Swarm manager'dan servisin çalışacağı container'a transfer ediliyor (encrypted). Bağlandığı service container'larının /run/secrets klasöründe erişilebilecek şekilde map ediliyor. O container bu path içindeki objeye erişiyor ve kullanıyor 756 | - `docker swarm init` diyerek swarm cluster oluşturuyoruz 757 | - Secret oluşturmanın iki yolu vardır. Birincisi metin dosyalarından oluşturmaktır 758 | - username.txt ve password.txt dosyalarımın olduğu dizine gidiyorum. `docker secret create ` komutu ile secret oluşturuyoruz 759 | - `docker secret create username ./username.txt` 760 | - `docker secret create password ./password.txt` 761 | - `docker secret ls` ile Secret'leri listeleriz 762 | - `docker secret rm ` ile Secret sileriz 763 | - `docker secret inspect ` ile Secret inceleyebiliriz 764 | - İkinci yöntem ise terminalden oluşturmaktır 765 | - `echo "" | docker create -` 766 | - `echo "Bu bir secrettir" | docker secret create deneme -` 767 | - `docker service create -d --name secrettest --secret username --secret password mebaysan/basitflaskimaj` -> bir servis oluşturduk ve içerisine cluster'daki secretları gönderdik 768 | - `docker exec -it 0c sh` -> oluşturduğumuz container'a bağlandık 769 | - `cd /run/secrets` -> secretların tutulduğu dizine gidiyoruz ve orada oluşturduğumuz secret isimleriyle dosyalar görüyoruz. Bunların değerleri de secretların değerleridir 770 | - Secret'i güncellemek istersek service'i güncellememiz gerekir 771 | - Önce cluster'da yeni bir secret oluşturuyoruz (varsayalım ki username2 adında olsun) 772 | - `docker service update --secret-rm username --secret-add username2 secrettest` 773 | - `--secret-rm username` secrettest servisindeki username adlı secreti sil 774 | - `--secret-add username2` ilgili servisteki username secret'in yeni değerini cluster'daki username2 secretinin değeri olarak güncelle 775 | 776 | 777 | 778 | 779 | # Docker Stack 780 | - Docker Compose'daki gibi bir işleme benzer. Stack de bunu swarm ortamında yapmamızı sağlar. 781 | - docker-compose.yml dosyası kullanır 782 | - Docker Compose dosyası ile arasında bazı farklar var 783 | - Docker Engine ile tanımlı komutlar Compose ile kullanılabilirken Stack için kullanılamaz 784 | - Stack için uygun olan komutlar Compose ile kullanılamaz 785 | - İlgili dosyanın bulunduğu dizine gidiyorum 786 | - `docker stack ls` -> oluşturduğumuz stckleri listeler 787 | - `docker stack ps` -> stack altındaki taskları görebiliriz 788 | - `docker stack rm ` -> ilgili stack i siler 789 | - `docker stack services ` -> ilgili stack altındaki servisleri listeler 790 | - `docker stack deploy -c ./docker-compose.yml ilkstack` -> docker-compose.yml'dan bir stack oluşturur ve ayağa kaldırır. 791 | - ilkstack adındaki stack'i bu dizindeki docker-compose.yml dosyasından oluşturur 792 | - **stacklerde docker-compose.yml pathini belirtmemiz gerekir** 793 | -------------------------------------------------------------------------------- /static/compose/Screen Shot 2021-01-17 at 12.17.21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mebaysan/DockerElKitabi/a9b9dbb1d768af880214a71c1f8e8efed454387e/static/compose/Screen Shot 2021-01-17 at 12.17.21.png -------------------------------------------------------------------------------- /static/giris/giris-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mebaysan/DockerElKitabi/a9b9dbb1d768af880214a71c1f8e8efed454387e/static/giris/giris-1.png -------------------------------------------------------------------------------- /uygulamalar/ADD-COPY-FARKI/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | # base image alpine kullanır 3 | WORKDIR /wordpress-uygulamasi 4 | # dizin değiştirdik 5 | ADD https://tr.wordpress.org/latest-tr_TR.tar.gz . 6 | # url'den dosyayı dizine kopyaladık, buradaki olay uzak bir sunucudaki dosyayı buraya kopyalayabilmekti 7 | # fakat decompress olarak atmasını istersek aynı dizindeki dosyayı (.tar) vermemiz gerekir -------------------------------------------------------------------------------- /uygulamalar/ARG/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | 3 | WORKDIR /sallamasyon 4 | 5 | ARG VERSION=3.7.1 6 | # build olurken VERSION adında bir environment gelecek, bu sayede aşağıdaki gibi 7 | # dinamik olarak yönetim yapabileceğiz 8 | # varsayılan olarak değer atadık, eğer bu parametre gelmezse bu değeri kullanır 9 | ADD https://www.python.org/ftp/python/${VERSION}/Python-${VERSION}.tgz . 10 | 11 | CMD ls -al 12 | # docker image build -t mytest2 --build-arg VERSION=3.8.1 . -> bu şekilde imaj oluştururken kullanabiliriz 13 | -------------------------------------------------------------------------------- /uygulamalar/Compose/intro/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # yaml bir veri serilizasyon dilidir 2 | # verileri key-value olarak tutar 3 | # her yaml dosyası bir version keyi ile başlamak zorundadır 4 | # top level key'ler -> version services volumes networks 5 | 6 | # Senaryo: bir veritabanı servisi olacak bir de wordpress servisi, ardından 2 servis arasında bağlantı kurarak wordpress uygulamasını ayağa kaldıracağız 7 | 8 | version: "3.9" 9 | # version -> docker compose dosyasının hangi versiyonu ile kullanmak istiyoruz anlamına gelir 10 | 11 | services: 12 | # container'ları burada tanımlıyoruz 13 | veritabani: 14 | # veritabani -> service (container) adı 15 | image: mysql:5.7 16 | # hangi imajdan oluşturacağız 17 | restart: always 18 | # her seferinde yeniden başlatacak 19 | # container oluştururken kullandığımız --restart parametresine karşılık gelir olarak düşünebiliriz 20 | volumes: 21 | - verilerim:/var/lib/mysql 22 | # verilerim adında bir volume oluşturup container altındaki pathe bağlıyorum 23 | - ikincivolume:/baysandata 24 | # liste halinde birden fazla öğe ekleyebildiğimiz için - kullanarak tanımladık 25 | # yani şöyle düşünebiliriz volumes = [verilerim:/var/lib/mysql, ikincivolume:/baysandata, ...] 26 | environment: 27 | MYSQL_ROOT_PASSWORD: rootmysqlsifresi 28 | MYSQL_DATABASE: mywordpressdb 29 | MYSQL_USER: wordpressuser 30 | MYSQL_PASSWORD: mysqlpassword 31 | # container oluştururken --env MYSQL_USER="wordpressuser" yapıyorduk, compose ile dosya hazırlarken de bu şekilde belirtmemiz gerekir 32 | networks: 33 | - baysanwpnet 34 | # bu servisi baysanwpnet adındaki ağa bağladık 35 | # docker container run --name veritabani --net baysanwpnet mysql -> container oluştururken de bu işleme karşılık gelecekti 36 | 37 | mywp: 38 | # mywp adında bir servis (container) oluşturuyoruz 39 | image: wordpress:latest 40 | depends_on: 41 | # hangi servislere bağımlı olduğunu belirtiyoruz 42 | - veritabani 43 | # önce database servisimiz (veritabani) ayağa kalkacak ki sonra wordpress bu servise bağlanabilsin ve çalışabilsin 44 | restart: always 45 | ports: 46 | - "80:80" 47 | # host'un 80 portunu servisin 80 portuna publish et 48 | # birden fazla port tanımlayabiliriz 49 | environment: 50 | WORDPRESS_DB_HOST: veritabani:3306 51 | # veritabanı servisinde 3306 portu 52 | WORDPRESS_DB_USER: wordpressuser 53 | WORDPRESS_DB_PASSWORD: mysqlpassword 54 | WORDPRESS_DB_NAME: mywordpressdb 55 | WORDPRESS_TABLE_PREFIX: wp 56 | # aslında buradaki olay basit bir wordpress ayağa kaldırmak, veritabqanı servisinde oluşturduğumuz mysql db'e oluşturduğumuz wordpress servisini bağlarken ordaki db bilgilerini burada set ediyoruz ki bağlanabilelim 57 | networks: 58 | - baysanwpnet 59 | # 2 servis aynı ağda olacak 60 | 61 | volumes: 62 | # kullanacağımız volume'leri burada tanımlarız 63 | verilerim: 64 | # verilerim adında bir volume oluşturduk, bu volume'u veritabanı servisinde kullanacağız 65 | ikincivolume: 66 | 67 | networks: 68 | # kullanacağımız network objelerini burada tanımlarız 69 | baysanwpnet: 70 | # bu sistemde kullanılacak (veritabani servisindeki) network'u burada oluşturuyoruz 71 | driver: bridge 72 | # hangi driver'ı kullanacak -------------------------------------------------------------------------------- /uygulamalar/DockerSecret/password.txt: -------------------------------------------------------------------------------- 1 | 12345 -------------------------------------------------------------------------------- /uygulamalar/DockerSecret/username.txt: -------------------------------------------------------------------------------- 1 | mebaysan -------------------------------------------------------------------------------- /uygulamalar/DockerStack/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | 5 | 6 | veritabani: 7 | image: mysql:5.7 8 | volumes: 9 | - verilerim:/var/lib/mysql 10 | environment: 11 | MYSQL_ROOT_PASSWORD: rootmysqlsifresi 12 | MYSQL_DATABASE: mywordpressdb 13 | MYSQL_USER: wordpressuser 14 | MYSQL_PASSWORD: mysqlpassword 15 | networks: 16 | - baysanwpnet 17 | 18 | 19 | mywp: 20 | image: wordpress:latest 21 | # stack ile çalışacağımızdan imajın önceden oluşturulmuş olması gerekiyor 22 | # compose'daki gibi build kullanamayız 23 | depends_on: 24 | - veritabani 25 | ports: 26 | - "80:80" 27 | environment: 28 | WORDPRESS_DB_HOST: veritabani:3306 29 | WORDPRESS_DB_USER: wordpressuser 30 | WORDPRESS_DB_PASSWORD: mysqlpassword 31 | WORDPRESS_DB_NAME: mywordpressdb 32 | WORDPRESS_TABLE_PREFIX: wp 33 | networks: 34 | - baysanwpnet 35 | 36 | deploy: 37 | # stack kullanırken bu bloğu girmemiz gerek 38 | replicas: 3 39 | # kaç adet replikası olsun? bunun için swarm bölümüne bakabiliriz 40 | update_config: 41 | parallelism: 2 42 | # aynı anda kaç adet güncellensin 43 | delay: 10s 44 | # güncellerken ne kadar beklesin 45 | order: stop-first 46 | 47 | 48 | volumes: 49 | verilerim: 50 | 51 | 52 | networks: 53 | baysanwpnet: 54 | driver: overlay 55 | # swarm ile çalışacağımız için overlay network oluşturuyoruz -------------------------------------------------------------------------------- /uygulamalar/Dockerfile-2/Dockerfile: -------------------------------------------------------------------------------- 1 | # hangi base imajdan container kuracaksın 2 | FROM ubuntu:18.04 3 | # container **oluşturulurken** çalıştırılacak komut 4 | RUN apt-get update -y 5 | # sisteme python kur 6 | RUN apt-get install python3 -y 7 | RUN apt-get install python3-pip -y 8 | # myapp adındaki path'e geç eğer yoksa oluştur 9 | WORKDIR /ilkuygulama 10 | # /myapp -> host üzerinde bu dosyalar nerede duruyor, Dockerfile ile aynı dizindeki proje klasörü 11 | # . -> imaj içerisinde bu dosyaları nereye koyacağız, zaten yukarıda /ilkuygulama adındaki path'e geçmiştik 12 | COPY /myapp . 13 | # container **oluşturulduktan sonra** çalıştırılacak komut (app.py dosyasını çalıştıracak) 14 | CMD ["python3", "app.py"] -------------------------------------------------------------------------------- /uygulamalar/Dockerfile-2/myapp/app.py: -------------------------------------------------------------------------------- 1 | print("Merhaba ben bir konsol uygulamasiyim. Ilk docker imaji icin olusturuldum!") -------------------------------------------------------------------------------- /uygulamalar/Dockerfile-4/pythonapp/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | # oluşturduğumuz ilk Dockerfile'da önce ubuntuyu kurup sonra içinde python kurmuştuk. 3 | # Aslında buna gerek yoktur. Python'un resmi imajını arıyoruz ve 4 | # bize işletim sisteminin üzerine kurulmuş olan bir imaj geliyor, bu sayede tek tek ikisini 5 | # kurmak ile uğraşmıyoruz 6 | COPY . /app 7 | # . -> bu klasördeki tüm dosyaları, imaj içindeki app folderine kopyala 8 | WORKDIR /app 9 | # imaj içindeki app klasörüne geçiyoruz 10 | RUN pip install -r requirements.txt 11 | # gerekli paketleri yüklüyoruz 12 | EXPOSE 5000 13 | # konteynır dışından konteynıra 5000 portundan ulaşılacağını belirtiyoruz 14 | CMD ["python","app.py"] 15 | # python dosyasını çalıştırıyoruz -------------------------------------------------------------------------------- /uygulamalar/Dockerfile-4/pythonapp/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | 6 | @app.route('/') 7 | def index(): 8 | return "Merhaba anasayfa!" 9 | 10 | 11 | if __name__ == '__main__': 12 | app.run(debug=True,host='0.0.0.0') -------------------------------------------------------------------------------- /uygulamalar/Dockerfile-4/pythonapp/requirements.txt: -------------------------------------------------------------------------------- 1 | flask -------------------------------------------------------------------------------- /uygulamalar/Dockerfile-5/Dockerfile: -------------------------------------------------------------------------------- 1 | # daha detaylı: https://github.com/ozgurozturknet/AdanZyeDocker/blob/master/kisim5/bolum52/hello-docker/Dockerfile 2 | FROM nginx:latest 3 | 4 | LABEL maintainer="@mebaysan" 5 | LABEL version="1.0" 6 | LABEL name="merhaba-docker" 7 | # bu bilgielre container içinden erişemeyiz 8 | 9 | 10 | ENV KULLANICI="Dunyali" 11 | 12 | 13 | RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list 14 | # bu imajda uyumluluk sorunları var ve o nedenle update olmuyor 15 | # Bu url'leri sources.list'e ekleyerek update olabilmesini sağlıyoruz 16 | 17 | 18 | 19 | RUN apt-get update 20 | 21 | RUN apt-get install curl -y 22 | # debian-slim'de bir çok olmadığından; curl kullanmamız gerektiği için curl yüklüyoruz 23 | 24 | 25 | WORKDIR /usr/share/nginx/html 26 | # nginx web sayfalarını /usr/share/nginx/html folder'ında barındırıyor, bu folder'a geçiyoruz 27 | 28 | 29 | COPY index.html /usr/share/nginx/html 30 | 31 | # sistemin düzgün çalıştığını ve nginx daemon'ının web sitesini publish etmekte bir sorun yaşamadığını test ediyoruz 32 | HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD curl -f http://localhost/ || exit 1 33 | # interval -> 30 saniyede bir çalıştır 34 | # timeout -> 10 saniye bekle 35 | # start-period -> 5 saniye bekle sonra healthcheck çalıştır 36 | # retries -> kaç deneme ard arda başarısız olursa bu container'ı unhealthy olarak işaretle 37 | # CMD curl -f http://localhost/ -> çalışacak komut / localhost'a http üzerinden erişmeye çalışıyorum, eğer ulaşamazsan process'i öldür ve hata dön (exit 1) 38 | # Bu komutun meali = container başladıktan sonra 5 sn bekle (start-period), sonra healthcheck komutunu çalıştır (CMD ..), 39 | # bu komutun sonucunu not et, sonra 30 sn bekle(interval), container çalıştığı sürece bunu tekrar et eğer bu işlemler sırasında 40 | # ardı ardına 3 deneme sonunda olumsuz sonuç alırsan container'ı unhealthy olarak işaretle 41 | 42 | 43 | CMD sed -e s/Kullanici/"$KULLANICI"/ index.html > index1.html && sed -e s/Hostname/"$HOSTNAME"/ index1.html > index.html ; rm index1.html; nginx -g 'daemon off;' 44 | # index.html'i tara, orda Kullanici adında bir şey görürsen onu $KULLANICI (ENV) ile değiştir ve bu dosyayı index1.html olarak yaz 45 | # index1.html'i tara Hostname görürsen onu $HOSTNAME (ENV) ile değiştir ve bu dosyayı index.html olarak yaz 46 | # index1.html i sil 47 | # nginx daemon'u çalıştır 48 | # -!! burada env değerlerini almamızın sebebi; CMD container oluştuktan sonra çalışır, yani container oluşurken parametre olarak gönderdiğimiz --env değerlerini burada yakalayabiliriz 49 | 50 | -------------------------------------------------------------------------------- /uygulamalar/Dockerfile-5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Docker Deneme 7 | 12 | 13 | 14 |

Merhaba Kullanici

15 | 16 |

17 | Bu sayfa size Hostname id'li docker container içerisinde çalışan 18 | Nginx yazılımı tarafından sağlanıyor 19 |

20 | 21 | 22 | -------------------------------------------------------------------------------- /uygulamalar/ENTRYPOINT-CMD-FARKI/cmd/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | # base image'den bir imaj oluştur 3 | WORKDIR /myapp 4 | # dizin değiştir 5 | RUN echo "print('Merhaba dünya ben container uygulamasiyim')" > "app.py" 6 | # app.py dosyası oluştur ve içerisine kodu yaz 7 | CMD ["python","app.py"] 8 | # app.py dosyasını çalıştır 9 | # bu container başlatıldığında bir şey denmemişse CMD komutunu (python app.py) çalıştır 10 | # eğer runtime'da farklı bir komut çalıştırılması söylenirse onu çalıştır 11 | -------------------------------------------------------------------------------- /uygulamalar/ENTRYPOINT-CMD-FARKI/entrypoint/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:alpine 2 | # base image'den bir imaj oluştur 3 | WORKDIR /myapp 4 | # dizin değiştir 5 | RUN echo "print('Merhaba dünya ben container uygulamasiyim')" > "app.py" 6 | # app.py dosyası oluştur ve içerisine kodu yaz 7 | ENTRYPOINT ["python","app.py"] 8 | # app.py dosyasını çalıştır 9 | # bu container başlatıldığında bu komutu çalıştır, runtime'da farklı bir şey denmesi entrypoint'i bağlamaz 10 | -------------------------------------------------------------------------------- /uygulamalar/MultiStageBuild/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/java/jdk:8-zulu-alpine AS derleyici 2 | # derleyici adında bir stage oluşturduk, bu bir aşama oldu ve diğer FROM komutuna kadar olan kodlar bu stage'e aittir 3 | 4 | COPY /source /usr/src/uygulama 5 | 6 | WORKDIR /usr/src/uygulama 7 | 8 | RUN javac uygulama.java 9 | # java kodunu derledik 10 | 11 | # yukarıdaki tüm kodlar buraya kadar bir stage'dir 12 | 13 | 14 | FROM mcr.microsoft.com/java/jre:8-zulu-alpine 15 | 16 | WORKDIR /uygulama 17 | 18 | COPY --from=derleyici /usr/src/uygulama . 19 | # derleyici stage'indeki /usr/src/uygulama altındaki dosyaları, buradaki /uygulama ya kopyala 20 | 21 | CMD ["java","uygulama"] 22 | 23 | 24 | # bu sayede nihai imaj 2. From'dan oluştu ve uygulamayı çalıştırmak için gereksiz 25 | # olan jdk (derleyici kiti)'ı bu son imaja eklemek zorunda kalmadık 26 | -------------------------------------------------------------------------------- /uygulamalar/MultiStageBuild/source/uygulama.java: -------------------------------------------------------------------------------- 1 | public class uygulama{ 2 | public static void main(String[] args){ 3 | System.out.println("Uygulama çalıştı"); 4 | } 5 | } --------------------------------------------------------------------------------