Ubuntu sunucu üzerinde Docker Container çalıştırma ile ilgili bu yazı dizisinin ilk bölümünde kurulum konusuna başlamıştık. Yazının ikinci bölümünde kurulum sonrası yapılması gerekenler ve Apache httpd örneği ile devam etmiştik. Üçüncü bölümde örneklere devam ederken Docker İmajları konusuna basitçe değinmiştik Bu makalede ağırlıklı olarak Apache Httpd imajı üzerinden örnek vermiştim. Yazının dördüncü bölümünde ağırlıklı olarak en çok çalıştırılan imaj olduğu için nginx örnekleri vermiştim. Ayrıca çalışan Container’in komut satırına nasıl ulaşılacağı, containerin konfigürasyonunun nasıl değiştirileceğini ve bind mount konusunu anlatmıştım.Yazının bu 5nci bölümünde nginx load balancer örneği üzerinden Volume konusuna devam edeceğim. Bu makalenin anlaşılabilmesi için Network konusuna da girmemiz gerek. Bu yazıda ana örneğimiz bir nginx load balancer arkasında çalışan 2 web sunucusu olacak. Nginx load balancer olarak çalışırken, kendisine gelen istekleri bu iki web sunucuya yönlendirecek.
Docker Network
Bu örneğin çalışacağı yapıyı kurmadan önce Docker Network konusunu incelemeye çalışacağız. Docker networkü hakkında bilgi verirken bir altta yer alan ağ katmanlarını gösteren şemadan yaralanacağım. Şemada yeşil kısım Docker Networkünün fiziksel kısmını, turuncu ile çevrilmiş alan ise sanal networkü temsil ediyor. Sanal networkten kastım Docker tarafından oluşturulan switch, nat cihazı, sanal ethernet kartı ve diğer network komponentleri. Aslına bakarsanız, sanal yerine yazılım tabanlı network daha uygun bir tanımlama olur. Bu tanımlamayı açmak için network katmanlarını anlatmakta fayda var. Aşağıdaki resme bakarsanız network katmanlarını görürsünüz. TCP/IP networkü 4 katman olarak açıklarken OSI Modeli networkü 7 katman olarak tanımlar. Ben bu yazı boyunca 7 katmanlı OSI modelini esas alacağım.
Dikkat ederseniz 7 katmanın tamamı da elle tutulacak olan kablolar ve kartlar vs haricinde tamamen yazılımdır. 2nci katmanda (Layer/Katman 7 en üstte, Layer/Katman 1 en altta) bulunan switcing, switch donanımı üzerinde çalışan bir yazılımdır. Layer3 te bulunan Routing te aynı şekilde bir router veya L3 destekleyen bir switch üzerinde çalışan bir yazılımdır. Bu açıdan tüm katmanlar donanımdan ayrıştırılmış olarak yazılım ortamında çalışabilir. Bu yazı boyunca Katman 2 DataLink’te çalışan Switcing, Katman 3 Network’te çalışan Routing, Katman 4 Transport’ta çalışan NAT , Katman 7 Application’da çalışan Proxy (ileri/forward ve geriye/reverse) ve kullanılan yönteme göre Katman 3/4/7de çalışan Load Balance (Yük dengeleme) konularından bahsedeceğim.
Yukarıdaki şemada üzerinde Ubuntu kurulu sunucuya Docker kurduğunuz zaman, Docker hemen bir yazılım tabanlı network oluşturur (burada bahsettiğim Software Defined Network/SDN değil de daha çok Network Functions Virtualization/NVF anlamında). Şemada bu network switchi Docker Tarafından Oluşturulan Nat/Brdige Sanal Switch olarak belirttim. Oluşturulan her Container bu switche şemada Docker Container Sanal Ethernet Kart olarak belirttiğim bağlantıdan bağlanır. Aksi belirtilmedikçe oluşturulan tüm Containerler bu networke bağlanır. Bu networke bağlanan tüm Containerler kendi aralarında başka bir ayara gerek kalmadan konuşurlar. Bu network ile ilgili anlatmaya devam etmeden önce ilk network komutlarını görelim:
Komutlar docker network ile başlar, ilk komut mevcut networkleri listelemek için kullanılan docker network ls komutu. Bu komutun çıktısı aşağıdaki gibi olur, var olan networkleri listeler. Bu networklerden en önemlisi adı ve network tipi bridge olan networktür.
oktay@ubuntu1804:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
a8ea3b6d3eec bridge bridge local
a38c11f94152 host host local
69b4acf65bc9 none null local
oktay@ubuntu1804:~$
Daha önce de yazdığım gibi oluşturulan tüm containerler, eğer aksi belirtilmezse bu networke bağlanırlar. Tüm L2 Switching bu katmanda olur. Bu networkteki containerler dış network ile konuşmak isterler ise, fiziksel sunucunun ethernet bağlantısı üzerinden dış dünyaya bağlanır. Bu bağlantı, NAT şeklinde olur. Yani Container’den çıkan paketler, L4 katmanında NAT edilerek fiziksel sunucunun IP adresi üzerinden dış networke bağlanır. Dışarıya doğru giden paketler için özel bir ayar yapmaya gerek yoktur. Dış networkte, bu Containerden gelen paketlerin IP adresi olarak fiziksel ethernet kartının IP adresini görünür. Ayrıca dışardan bu networkte bulunan Containerlere bağlanmak gerekirse, yine içeriye doğru NAT ile bağlanılabilir. İçeriye doğru NAT yapılabilmesi için, kullanılacak olan portun Container çalışırken belirtilmesi gerekir. Bu port parametresini daha önce kullandık, -p <dış_port>:<iç_port>. Bu networkü ayrıntılı incelemek istersek inspect parametresi ile birlikte network adını kullanırız.
oktay@ubuntu1804:~$ docker network inspect bridge
[
{
“Name”: “bridge”,
“Id”: “f4673e040e5806df2ffebcb9c13a1a0a5b4f6501f452f445afbc32607d0250b1”,
“Created”: “2018-10-30T12:56:49.607398888Z”,
“Scope”: “local”,
“Driver”: “bridge”,
“EnableIPv6”: false,
“IPAM”: {
“Driver”: “default”,
“Options”: null,
“Config”: [
{
“Subnet”: “172.17.0.0/16”,
“Gateway”: “172.17.0.1”
}
]
},
“Internal”: false,
“Attachable”: false,
“Ingress”: false,
“ConfigFrom”: {
“Network”: “”
},
“ConfigOnly”: false,
“Containers”: {},
“Options”: {
“com.docker.network.bridge.default_bridge”: “true”,
“com.docker.network.bridge.enable_icc”: “true”,
“com.docker.network.bridge.enable_ip_masquerade”: “true”,
“com.docker.network.bridge.host_binding_ipv4”: “0.0.0.0”,
“com.docker.network.bridge.name”: “docker0”,
“com.docker.network.driver.mtu”: “1500”
},
“Labels”: {}
}
]
Yukarıda docker network inspect bridge komutunun çıktısını gördük. Komut çıktısında “Name”: “bridge” kısmı network adını, “Driver”: “bridge” network tipini belirtiyor. “Subnet”: “172.17.0.0/16” bölümü bu networkün IP aralığını, belirtiyor. İlk network 172.17.0.0/16 olup sonra oluşan networkler bir sonraki IP aralığından devam eder. Bu çıktıda daha Container oluturmadığımız için Container görmüyoruz. Şimdi bir Ubuntu Container oluşturalım ve ne olduğuna bakalım. Bunun için aşağıdaki komut ile bir Container çalıştıracağım ve doğrudan komut satırına bağlanacağım. Önce ilk satırdaki komut ile Ubuntu:16.04 Containeri çalıştırıyorum, -it parametresi ile interaktif olarak çalışmasını ve konsola bağlanmasını belirtiyorum, en sondaki bash ile de Bash kabuğuna bağlanmasını belirtiyorum. Ubuntu Container imajı oluşturulurken herhangi bir yazılım vs çalıştırılması söylenmediği için, eğer -it ve bash parametresi kullanmaz isek Container çalışmaya başlar ve çalışması için herhangi birşey belirtilmediği için durur.
oktay@ubuntu1804:~$ docker container run -it –name ubuntu1 ubuntu:16.04 bash
Aşağıdaki ifconfig komutu ile içinde bulunduğum Container IP adresini öğrenmek istiyorum ama imaj küçük olsun diye ifconfig ve ping komutları konulmadığı için komut hata veriyor.
root@a2b8c78a5457:/# ifconfig
bash: ifconfig: command not found
Bu komutlalrın olduğu paketleri yüklemem gerek. Aşağıdaki çıktıyı kısa olsun diye kısalttım.
root@a2b8c78a5457:/# apt-get update
Reading package lists… Done
root@a2b8c78a5457:/# apt-get install net-tools
root@a2b8c78a5457:/# apt-get install iputils-ping
ifconfig komutunu tekrar çalıştırınca eth0 interfaci ip adresini 172.17.0.2/16 olarak görüyorum. eth0, Containerde içinde oluşan sanal ethernet kartı.
root@a2b8c78a5457:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:4266 errors:0 dropped:0 overruns:0 frame:0
TX packets:2720 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:17233590 (17.2 MB) TX bytes:186880 (186.8 KB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Bağlı olduğumuz network default gateway’ini pingleyelim.
root@a2b8c78a5457:/# ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data.
64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.062 ms
— 172.17.0.1 ping statistics —
3 packets transmitted, 3 received, 0% packet loss, time 2042ms
rtt min/avg/max/mdev = 0.062/0.088/0.115/0.024 ms
root@a2b8c78a5457:/#
Şimdi de dış dünyadan bir web sitesini pingleyelim. Dikkat ederseniz Cisco için hem Dns adresini çözümledi hem de bu IP’yi pingledi.
root@a2b8c78a5457:/# ping http://www.cisco.com
PING e2867.dsca.akamaiedge.net (104.66.70.56) 56(84) bytes of data.
64 bytes from a104-66-70-56.deploy.static.akamaitechnologies.com (104.66.70.56): icmp_seq=1 ttl=246 time=44.1 ms
64 bytes from a104-66-70-56.deploy.static.akamaitechnologies.com (104.66.70.56): icmp_seq=2 ttl=246 time=44.2 ms
Bu aşamada docker network inspect bridge komutu ile tekrar bridge network ayrıntılarına bakalım. Şu an için tek container var, buna verilen IP adresi 172.17.0.2/16 ki bu da Ubuntu içinde gördüğümüz adres.
Çıktıyı kısalttım.
“Containers”: {
“a2b8c78a545782459b5f44eb6a9682d10d72e5488c94dfb67e49878a2a71eb65”: {
“Name”: “ubuntu1”,
“EndpointID”: “3560256a7aabc946a15328760c3a33b745c9ae7c9816d6ca50e2996a88bbc092”,
“MacAddress”: “02:42:ac:11:00:02”,
“IPv4Address”: “172.17.0.2/16”,
“IPv6Address”: “”
}
Container IP adresini görmenin başka bir yolu da docker container inspect ubuntu1 komutu ile Container ayrıntılarına bakmak. Çıktı uzun olduğu için kısalttım,
“NetworkSettings”:
“Gateway”: “172.17.0.1”,
“IPAddress”: “172.17.0.2”,
“IPPrefixLen”: 16,
Bu network ile ilgili bir sonraki aşamada bir nginx Container çalıştıralım ve IP adresini öğrenelim. Dikkat ederseniz bu nginx i -p ile dış dünyaya bağlamadım.
oktay@ubuntu1804:~$ docker container run -d nginx:alpine
84071ab48176283db0f724e684734dc4111ab4d136db4d5f6290d622adbab52b
oktay@ubuntu1804:~$ docker container ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
84071ab48176 nginx:alpine “nginx -g ‘daemon of…” 23 seconds ago Up 21 seconds 80/tcp stoic_torvalds
a2b8c78a5457 ubuntu:16.04 “bash” 18 hours ago Up 18 hours ubuntu1
oktay@ubuntu1804:~$ docker container inspect stoic_torvalds
Çıktıyı kısalttım
“Networks”: {
“bridge”: {
“IPAddress”: “172.17.0.3”
Şimdi bu nginx e daha önce çalıştırdığımız Ubuntu Container üzerinden ulaşalım:
root@a2b8c78a5457:/# curl http://172.17.0.3
bash: curl: command not found
root@a2b8c78a5457:/# apt-get install curl
Curl kurulu olmadığı için kuralım.
root@a2b8c78a5457:/# curl http://172.17.0.3
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href=”http://nginx.org/”>nginx.org</a>.<br/>
Commercial support is available at
<a href=”http://nginx.com/”>nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@a2b8c78a5457:/# ^C
root@a2b8c78a5457:/#
Yukarıda gördüğünüz gibi, -p parametresi ile bir Containeri dış networklerden erişime açmasak ta Containerler birbirleri ile konuşabiliyorlar. Bu özellikle birden çok Container ile kurduğumuz yapılarda, dış networkten erişime ihtiyacı olmayan Containerlerin -p ile dıştan gelen bağnatılara açılmadan çalışabilmesi açısında önemli. Örnek olarak bir web sunucu ve bir sql sunucudan oluşan bir uygulama düşünün. Dış dünyadan sadece web sunucuya bağlanılacak ve web sunucu sql sunucu ile konuşacaksa, sql sunucuyu dışa açmanın anlamı yok. Bu güvenlik açısından da önemli.
Kendi Network’ümüzü Oluşturalım
Bu aşamaya kadar otomatik oluşturulan network üzerinde çalıştık. Şimdi de kendimiz bir network oluşturalım. Bunun için docker network create <network_adı> komutunu kullanacağım. Bu komutun parametreleri bu kadar değil, kolay olsun diye bu şekilde başlayalım.
oktay@ubuntu1804:~$ docker network create oktay_test
1ab7d37da3a945ca5be376817cbcd1c773f714babe6df0b9462493e4a4f66d0d
oktay@ubuntu1804:~$ docker network inspect oktay_test
[
{
“Name”: “oktay_test”,
“Id”: “1ab7d37da3a945ca5be376817cbcd1c773f714babe6df0b9462493e4a4f66d0d”,
“Created”: “2018-10-31T08:14:03.507142944Z”,
“Scope”: “local”,
“Driver”: “bridge”,
“EnableIPv6”: false,
“IPAM”: {
“Driver”: “default”,
“Options”: {},
“Config”: [
{
“Subnet”: “172.18.0.0/16”,
“Gateway”: “172.18.0.1”
}
]
},
“Internal”: false,
“Attachable”: false,
“Ingress”: false,
“ConfigFrom”: {
“Network”: “”
},
“ConfigOnly”: false,
“Containers”: {},
“Options”: {},
“Labels”: {}
}
]
Dikkat ederseniz bu network Bridge tipinde oldu. Yani Fiziksel sunucu ethernet kartı üzerinden dış dünyaya bağlanabilir. Ayrıca Ip Adres Bloğu olarak 172.18.0.0/16 bloğunu aldı. Şimdi bu networkte bir nginx çalıştıralım. Bunun için komuta –network <network_adı> parametresi ekleyeceğiz. Daha önce söylediğim gibi eğer network belirtmezsek Containerler default networke bağlanır. Container çalıştıktan sonra network inspect komutu ile bu yeni networke bakalım, container ne IP aldı?
oktay@ubuntu1804:~$ docker container run -d –network oktay_test nginx:alpine
oktay@ubuntu1804:~$ docker network inspect oktay_test
[
{
“Name”: “oktay_test”,
“Subnet”: “172.18.0.0/16”,
“Gateway”: “172.18.0.1”
“Containers”: {
“e3be928f4a71c4df09f164cd2fc2052d37c77faf6e91684fcdfbef2ffeb2a67c”: {
“Name”: “peaceful_franklin”,
“EndpointID”: “a4e67d68a545420c276964a9a3d66e07d977e178d8f35d66ee9395399814bf82”,
“MacAddress”: “02:42:ac:12:00:02”,
“IPv4Address”: “172.18.0.2/16”,
“IPv6Address”: “”
Kısaltılmış çıktıda IP adresini 172.18.0.2 olarak gördüm.
Otomatik olarak oluşan bridge network ile kullanıcı tarafından oluşturulan bridge network arasındaki en büyük fark, kullanıcı tarafından oluşturulan bridge networkte Container isimlerini çözebilen bir DNS servisi otomatik olarak çalışmaya başlar. Bu sayede Containerler birbirlerine isimleri ile erişebilirler. Bunu aşağıdaki örnek ile görelim. Bu örnekte benim oluşturduğum brdige network üzerinde 2 adet nginx:alpine Container çalıştıracağım. Bunlara da srv1 ve srv2 isimlerini vereceğim.
oktay@ubuntu1804:~$ docker container run -d –network oktay_test –name srv1 nginx:alpine
641fcf0b73131ec5e2606570faa8e96ac1806c79029c5caad23740a7d6537b0d
oktay@ubuntu1804:~$ docker container run -d –network oktay_test –name srv2 nginx:alpine
a593e45229f0f078c79c9e8e41c694c26d25a14c6edfb9e27e3c1b754968b8a0
oktay@ubuntu1804:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a593e45229f0 nginx:alpine “nginx -g ‘daemon of…” 9 seconds ago Up 8 seconds 80/tcp srv2
641fcf0b7313 nginx:alpine “nginx -g ‘daemon of…” 18 seconds ago Up 17 seconds 80/tcp srv1
oktay@ubuntu1804:~$
Aşağıdaki komut ile srv1 nginx sunucunun komut satırına bağlanıp srv2 yi pingleyeceğim.
oktay@ubuntu1804:~$ docker container exec -it srv1 sh
/ # hostname
641fcf0b7313
/ # ping srv2
PING srv2 (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.134 ms
64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.175 ms
64 bytes from 172.18.0.4: seq=2 ttl=64 time=0.175 ms
^C
— srv2 ping statistics —
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.134/0.161/0.175 ms
/ #
Gördüğünüz gibi, kullanıcı tarafından oluşturulmuş olan networkte containerler birbirlerini isimleri ile pingleyebiliyorlar. Daha sonra kullanacağımız örneklerde, bu özellik sayesinde servisler birbirlerini ip vs bilmeden bulabilecek.
Nginx Load Balancer Örneği
Bir önceki yazıda hatrlarsanız ngix web sunucu olarak kullanılmıştı. Bu yazıda ise nginx load balancer olarak çalışacak. İnternet üzerinde load balancer veya reverse proxy nedir (her ikisi de benzer işler yapan ama çok temel farklılıkları olan teknolojiler) diye aratırsanız pek çok kaynak bulabilirsiniz. Kısaca belirtmek gerekirse, load balancer dengelenmek istenen hizmetin önüne koyulan ve yükü arkasındaki sunuculara bizim belirttiğimiz kurallara göre dağıtan teknolojidir (servis/sunucu/hizmet). Web sunucu olarak çalıştığı zaman html dosyaları /usr/share/nginx/html klasörü altında idi. Eğer bu dosyada html kodu varsa nginx web sunucu olarak çalışıyordu.
Ama eğer /etc/nginx/nginx.conf yolunda bulunan dosyayı konfigüre edersek bu sefer nginx load balancer olarak çalışır. Bu makalede anlatacağım örmekte, 2 nginx container web sunucu olarak çalışırken bunların önünde çalışan başka bir nginx container load balancer olarak çalışacak. Bu örneğin çalışması için iki ayrı klasör içinde iki ayrı index.html dosyası oluşturup bunu 2 ayrı nginx web sunucu containerine bağlayacağım. Ayrıca üçüncü bir ngix sunucunun load balancer olarak çalışması için bir nginx.conf dosyası oluşturacağım. Load balancer olarak çalışması için aşağıdaki örnek dosya kullanılabilir.
events {
worker_connections 1024; ## Default: 1024
}
http {
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
upstream backend {
server webserver1:80;
server webserver2:80;
}
}
Yukarıdaki dosya ayrıntılarını bir sonraki yazımda ayrıntılı anlatacağım ama kısaca söylemek gerekirse nginx’e 80 nolu porttan dinlemesini ve gelen istekleri webserver1 ve webserver2 arasında paylaştırmasını/yönlendirmesini söylüyor. Web sunucuları için ip yerine isim kullandığımdan bu network kullanıcı tarafından oluşturulmalı.
Şimdi gerekli altyapıyı kuralım. Önce webnet adında bir network oluşturdum. Sonra loadbaltest adında bir klasör ve bu klasör altında web1 ve web2 adında iki ayrı alt klasör oluşturdum. Her iki klasör içinde de 2 ayrı index. html dosyası. Bu dosya içerklerini aşağıda görebilirsiniz. Load balancer üzerinden gelen istekleri ayırabilmek için bir web sunucusu 1 diğer web sunucusu ise 2 diye cevap dönecek. Bu sayede hangi web sunucunun cevap verdiğini anlayabileceğim. Aşağıdaki yapıyı kurunca bir alttan devam edin.
oktay@ubuntu1804:~$ docker network create webnet
705d528dd7f620a9fae68d30ea751afff460750fb515d60819e2ccf96aea6b61
oktay@ubuntu1804:~$ pwd
/home/oktay
oktay@ubuntu1804:~$ mkdir loadbaltest
oktay@ubuntu1804:~$ cd loadbaltest/
oktay@ubuntu1804:~/loadbaltest$ mkdir web1
oktay@ubuntu1804:~/loadbaltest$ mkdir web2
oktay@ubuntu1804:~/loadbaltest$ cd web1
oktay@ubuntu1804:~/loadbaltest/web1$ nano index.html
<html>
<body bgcolor=”white” text=”blue”>
<h1> Oktay Web Sunucu 1 </h1>
</body>
</html>
oktay@ubuntu1804:~/loadbaltest/web1$ cd ..
oktay@ubuntu1804:~/loadbaltest$ cd web2
oktay@ubuntu1804:~/loadbaltest/web2$ nano index.html
<html>
<body bgcolor=”white” text=”blue”>
<h1> Oktay Web Sunucu 2 </h1>
</body>
</html>
oktay@ubuntu1804:~/loadbaltest/web2$ cd ..
oktay@ubuntu1804:~/loadbaltest$ tree
.
├── web1
│ └── index.html
└── web2
└── index.html
2 directories, 2 files
Şimdi gelelim Load Balancer konfig dosyasına. Bu dosya için yukarıdaki örnekteki içeriği kullanabiliriz. Bunun için loadbaltest klasörü içinde nginx.conf dosyası oluşturun ve bir üstteki örnek içeriği yapıştırın.
oktay@ubuntu1804:~/loadbaltest$ nano nginx.conf
Herşey hazır ise önce web sunucuları çalıştıralım:
oktay@ubuntu1804:~/loadbaltest$ docker container run -d –name webserver1 –network webnet -v /$(pwd)/web1:/usr/share/nginx/html nginx:alpine
e09c811220700647d0bded60c12ff1ee06bc59d16675be8b2744d49fad2f4986
oktay@ubuntu1804:~/loadbaltest$ docker container run -d –name webserver2 –network webnet -v /$(pwd)/web2:/usr/share/nginx/html nginx:alpine
9a375001aa706f3345d9c350d87ced74a688e564e618492659136f7afe1442f6
Buraya kadar geldiysek çalışan 2 ayrı web sunucumuz var. Dikkat edin, komutları daha önceden oluşturduğumuz loadbaltest klasörü içinden çalıştırdım, bu sayade komut satırında index.html dosylarının tam yolunu yazmak yerine $(pwd) yazın, bunun anlamı bulunduğum klasör demek. Aşağıdaki komut ile devam edelim, nginx bu sefer web sunucu değil de Load Balancer olarak çalışacak. Dikkat ederseniz ngin’leri web sunucu olarak çalıştırırken -p parametresi ile port açmadım. Bu işlemi load balancer yapacak ve Layer/Katman 4 de 80 nolu porta gelen istekleri gerideki bu web sunucuların 80 nolu portuna yollayacak.
oktay@ubuntu1804:~/loadbaltest$ docker container run -d -p 80:80 –network webnet -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf nginx
cfce60c397e568cdd00ea3cf94a1b0f39dc78ba3be64a82b363231faad8b1aa5
Bu aşamada web sayfaları geliyor mu diye kontrol edelim. Curl komutu ile web sayfalarını çağırdığımızda sırayla sunucu 1 ve sunucu 2 cevap verecek. Bir sonraki yazıda web sunuculardan biri çökerse LB nasıl davranır, LB için hangi yöntemler var vs. konularında ayrıntılı bilgi vereceğim.
oktay@ubuntu1804:~/loadbaltest$ curl http://localhost
<html>
<body bgcolor=”white” text=”blue”>
<h1> Oktay Web Sunucu 1 </h1>
</body>
</html>
oktay@ubuntu1804:~/loadbaltest$ curl http://localhost
<html>
<body bgcolor=”white” text=”blue”>
<h1> Oktay Web Sunucu 2 </h1>
</body>
</html>
Eğer LB loglarına bakarsam istekleri görürüm:
oktay@ubuntu1804:~/loadbaltest$ docker container ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cfce60c397e5 nginx “nginx -g ‘daemon of…” 8 minutes ago Up 8 minutes 0.0.0.0:80->80/tcp xenodochial_mcnulty
9a375001aa70 nginx:alpine “nginx -g ‘daemon of…” 9 minutes ago Up 9 minutes 80/tcp webserver2
e09c81122070 nginx:alpine “nginx -g ‘daemon of…” 9 minutes ago Up 9 minutes 80/tcp webserver1
oktay@ubuntu1804:~/loadbaltest$ docker container logs xenodochial_mcnulty
172.18.0.1 – – [31/Oct/2018:12:53:25 +0000] “GET / HTTP/1.1” 200 98 “-” “curl/7.58.0”
172.18.0.1 – – [31/Oct/2018:12:53:27 +0000] “GET / HTTP/1.1” 200 98 “-” “curl/7.58.0”
oktay@ubuntu1804:~/loadbaltest$
Bu yazıyı burada bitiriyorum. Önümüzdeki yazıda buraya kadar yaptıklarımızı toparlamaya çalışacağım.
Ek Okuma:
https://docs.docker.com/network/bridge/