Bu örneğimizde docker compose ile bir tane HAProxy ve iki tanede Apache container yaratacağız. Web sitemize ulaşmak istediğimizde HAProxy containere ulaşacağız, Apache containerlara değil. HAProxy istekleri Apache containerlara eşit olarak yönlendirecek.


Mantık


  1. İstek HAProxy containera gider.

  2. HAProxy container Apache container 1 veya 2'ye isteği iletir.

  3. Cevap Apache container 1 veya 2 ile sunulur.

Yapı


ubuntu@linux:~/helloworld$ tree -a
.
└── docker
├── apache
│   ├── 1
│   │   ├── Dockerfile
│   │   └── index.html
│   └── 2
│   ├── Dockerfile
│   └── index.html
├── docker-compose.yml
├── .env
└── haproxy
├── Dockerfile
└── haproxy.cfg

5 directories, 8 files

Dosyalar


docker/apache/1/Dockerfile


ubuntu@linux:~/helloworld$ cat docker/apache/1/Dockerfile 
FROM httpd:2.4

COPY index.html /usr/local/apache2/htdocs/index.html

docker/apache/1/index.html


ubuntu@linux:~/helloworld$ cat docker/apache/1/index.html 
Serving from Apache Server 1

docker/apache/2/Dockerfile


ubuntu@linux:~/helloworld$ cat docker/apache/2/Dockerfile 
FROM httpd:2.4

COPY index.html /usr/local/apache2/htdocs/index.html

docker/apache/2/index.html


ubuntu@linux:~/helloworld$ cat docker/apache/2/index.html 
Serving from Apache Server 2

docker/haproxy/Dockerfile


ubuntu@linux:~/helloworld$ cat docker/haproxy/Dockerfile 
FROM haproxy:1.7

COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg

docker/haproxy/haproxy.cfg


HAProxy'nin GUI'sine http://host_os_ip/haproxy?stats adresinden ulaşıp admin:admin ile login olabilirsiniz.


ubuntu@linux:~/helloworld$ cat docker/haproxy/haproxy.cfg 
global
log /dev/log local0
log localhost local1 notice
maxconn 2000
daemon

defaults
log global
mode http
option httplog
option dontlognull
retries 3
timeout connect 5000
timeout client 50000
timeout server 50000

frontend http-in
bind *:80
default_backend webservers

backend webservers
stats enable
stats auth admin:admin
stats uri /haproxy?stats
balance roundrobin
option httpchk
option forwardfor
option http-server-close
server apache1 ${APACHE_1_IP}:${APACHE_EXPOSED_PORT} check
server apache2 ${APACHE_2_IP}:${APACHE_EXPOSED_PORT} check

docker/.env


ubuntu@linux:~/helloworld$ cat docker/.env 
COMPOSE_PROJECT_NAME=helloworld

APACHE_EXPOSED_PORT=80

APACHE_1_IP=192.168.0.11
APACHE_2_IP=192.168.0.22

HA_PROXY_IP=192.168.0.33

NETWORK_SUBNET=192.168.0.0/24

docker/docker-compose.yml


ubuntu@linux:~/helloworld$ cat docker/docker-compose.yml 
version: '3'

services:
apache_img_1:
container_name: ${COMPOSE_PROJECT_NAME}_apache_con_1
build: ./apache/1
expose:
- ${APACHE_EXPOSED_PORT}
networks:
public_net:
ipv4_address: ${APACHE_1_IP}
apache_img_2:
container_name: ${COMPOSE_PROJECT_NAME}_apache_con_2
build: ./apache/2
expose:
- ${APACHE_EXPOSED_PORT}
networks:
public_net:
ipv4_address: ${APACHE_2_IP}
haproxy_img:
build: ./haproxy
ports:
- 80:80
expose:
- 80
networks:
public_net:
ipv4_address: ${HA_PROXY_IP}
environment:
- APACHE_1_IP=${APACHE_1_IP}
- APACHE_2_IP=${APACHE_2_IP}
- APACHE_EXPOSED_PORT=${APACHE_EXPOSED_PORT}
networks:
public_net:
driver: bridge
ipam:
driver: default
config:
- subnet: ${NETWORK_SUBNET}

Onaylama


Mevcut olan "docker-compose.yml" dosyasını aşağıdaki gibi onaylayıp, ilişkilendirmeyi görelim.


ubuntu@linux:~/helloworld/docker$ docker-compose config
networks:
public_net:
driver: bridge
ipam:
config:
- subnet: 192.168.0.0/24
driver: default
services:
apache_img_1:
build:
context: /home/ubuntu/helloworld/docker/apache/1
container_name: helloworld_apache_con_1
expose:
- '80'
networks:
public_net:
ipv4_address: 192.168.0.11
apache_img_2:
build:
context: /home/ubuntu/helloworld/docker/apache/2
container_name: helloworld_apache_con_2
expose:
- '80'
networks:
public_net:
ipv4_address: 192.168.0.22
haproxy_img:
build:
context: /home/ubuntu/helloworld/docker/haproxy
environment:
APACHE_1_IP: 192.168.0.11
APACHE_2_IP: 192.168.0.22
APACHE_EXPOSED_PORT: '80'
expose:
- 80
networks:
public_net:
ipv4_address: 192.168.0.33
ports:
- 80:80/tcp
version: '3.0'

Kurulum


Aşağıdaki komutu -d eki olmadan çalıştırdığınızda, HAProxy'nin Apache sunucularıni hep 1 saniyede bir test ettiğini göreceksiniz. Bu kurulumun doğru çalıştığını belirtir.


ubuntu@linux:~/helloworld/docker$ docker-compose up

Creating network "helloworld_public_net" with driver "bridge"
Building haproxy_img
Successfully tagged helloworld_haproxy_img:latest

Building apache_img_2
Successfully tagged helloworld_apache_img_2:latest

Building apache_img_1
Successfully tagged helloworld_apache_img_1:latest

Creating helloworld_apache_con_1 ... done
Creating helloworld_apache_con_1 ...
Creating helloworld_apache_con_2 ...

helloworld_apache_con_1 | 192.168.0.33 - - [03/Feb/2018:21:15:29 +0000] "OPTIONS / HTTP/1.0" 200 -
helloworld_apache_con_2 | 192.168.0.33 - - [03/Feb/2018:21:15:29 +0000] "OPTIONS / HTTP/1.0" 200 -
helloworld_apache_con_1 | 192.168.0.33 - - [03/Feb/2018:21:15:31 +0000] "OPTIONS / HTTP/1.0" 200 -
helloworld_apache_con_2 | 192.168.0.33 - - [03/Feb/2018:21:15:33 +0000] "OPTIONS / HTTP/1.0" 200 -
helloworld_apache_con_1 | 192.168.0.33 - - [03/Feb/2018:21:15:33 +0000] "OPTIONS / HTTP/1.0" 200 -
helloworld_apache_con_2 | 192.168.0.33 - - [03/Feb/2018:21:15:31 +0000] "OPTIONS / HTTP/1.0" 200 -
helloworld_apache_con_1 | 192.168.0.33 - - [03/Feb/2018:21:15:35 +0000] "OPTIONS / HTTP/1.0" 200 -
...

HAProxy'den gelen test iletişim bilgilerini kaydetmemesi için Apache'yi konfigüre etmeniz gerekir ki log dosyası şişmesin. Eğer nasıl yapıldığını görmek isterseniz, bloğun "HAProxy" yazılarındaki "Web sunucusu kayıtları" bölümündeki bilgileri uygulayabilirsiniz.


Konfigürasyon


Eğer tüm elementleri detayları ile görmek isterseniz docker inspect komutunu çalıştırabilirsiniz.


Imajlar


ubuntu@linux:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld_apache_img_2 latest 6f63653a9e68 9 minutes ago 177MB
helloworld_haproxy_img latest 363551ccafe6 9 minutes ago 136MB
helloworld_apache_img_1 latest 83bc617be089 9 minutes ago 177MB
...


ubuntu@linux:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c72c538d9025 helloworld_public_net bridge local
...

Containerlar


ubuntu@linux:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e4291f3a95c helloworld_apache_img_2 "httpd-foreground" 11 minutes ago Up 11 minutes 80/tcp helloworld_apache_con_2
ebba54230552 helloworld_apache_img_1 "httpd-foreground" 11 minutes ago Up 11 minutes 80/tcp helloworld_apache_con_1
a770b68939c5 helloworld_haproxy_img "/docker-entrypoin..." 11 minutes ago Up 11 minutes 0.0.0.0:80->80/tcp helloworld_haproxy_img_1

Test


Performas kıyaslama işlemini aşağıdaki komut ile yapabilirsiniz. Aynı anda 30 tane olmak üzere, toplam 10000 istek gönderiliyor. Bununla birlikte herhangi bir Apache containere girip htop komutunu çalıştırırsanız, CPU ve Memory kullanımını görebilirsiniz.


ubuntu@linux:~$ ab -n 10000 -c 30 http://192.168.0.33/

This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.33 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests

Server Software: Apache/2.4.29
Server Hostname: 192.168.0.33
Server Port: 80

Document Path: /
Document Length: 29 bytes

Concurrency Level: 30
Time taken for tests: 2.943 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 2730000 bytes
HTML transferred: 290000 bytes
Requests per second: 3397.93 [#/sec] (mean)
Time per request: 8.829 [ms] (mean)
Time per request: 0.294 [ms] (mean, across all concurrent requests)
Transfer rate: 905.89 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.3 0 6
Processing: 0 9 5.4 8 153
Waiting: 0 8 5.4 8 153
Total: 0 9 5.4 8 154

Percentage of the requests served within a certain time (ms)
50% 8
66% 9
75% 9
80% 10
90% 11
95% 13
98% 16
99% 25
100% 154 (longest request)

Her iki Apache sunucusu çalışırken.


ubuntu@linux:~$ for i in {1..10}; do curl 192.168.0.33:80; done

Serving from Apache Server 1
Serving from Apache Server 2
Serving from Apache Server 1
Serving from Apache Server 2
...

Sadece Apache 1 sunucusu çalışırken.


ubuntu@linux:~$ for i in {1..10}; do curl 192.168.0.33:80; done

Serving from Apache Server 1
Serving from Apache Server 1
Serving from Apache Server 1
Serving from Apache Server 1
...

Sadece Apache 2 sunucusu çalışırken.


ubuntu@linux:~$ for i in {1..10}; do curl 192.168.0.33:80; done

Serving from Apache Server 2
Serving from Apache Server 2
Serving from Apache Server 2
Serving from Apache Server 2
...

Apache sunucuları çalışımıyorken.


ubuntu@linux:~$ curl 192.168.0.33:80

<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>