SlideShare a Scribd company logo
1 of 58
Download to read offline
Sekrety magicznego
ogrodu Docker
Kamil Grabowski
Najczęstsze mity na temat Dockera
• "Docker jest dobry tylko do developmentu. Trzeba być nieodpowiedzialnym,
aby używać Dockera na produkcji"

• "Docker to takie lekkie maszyny wirtualne"

• "Nie ma różnicy w wydajności. Kontener dockerowy to przecież zwykły
proces linuksowy"

• "Nie powinno się uruchamiać baz danych w Dockerze, ponieważ bardzo
łatwo można stracić dane. Docker jest dobry, ale tylko do aplikacji stateless"

• "W kontenerze dockerowym powinien być uruchomiony tylko jeden proces"
Co jest tego powodem?
• Docker wystartował będąc bardzo młodym projektem, dużo eksperymentowano

• Ludzie nie czytają dokumentacji

• Ludzie nie śledzą zmian

• Ludzie używają starszych wersji oprogramowania (np. docker z repozytorium
Ubuntu/Debian, starsze wersje kernela)

• Sporo artykułów, blogów, prezentacji opisuje rozwiązania, które są już
deprecated lub też są lepsze metody na rozwiązanie danego problemu

• ... a czasem CORE Team Dockera rzeczywiście coś spierniczył ;)
Docker to takie lekkie maszyny wirtualne
Docker to takie lekkie maszyny wirtualne
• RootFS to nie jest to samo co system operacyjny czy też dystrybucja Linuksa
(kernel, init process, message logger itp.)

• Idea "lekkiej maszyny wirtualnej" to generator "pomysło-problemów":
zainstalujmy SSH serwer, systemd, rsyslog, cron
Docker to nie maszyna wirtualna
• Linux namespaces

• pid

• net

• mnt

• user

• ipc

• cgroups

• Warstwowy system plików (overlay2, aufs etc.)

• VETH - Virtual Ethernet Device
Linux namespaces: PID
Linux namespaces: PID
xx
Linux namespaces: PID
x x
Linux namespaces: PID
x x
x x
Linux namespaces: PID
x x
x x
x
x
x
x
Linux namespaces: PID
x x
x x
x
x
x
x
Linux namespaces: NET
Linux namespaces: NET
x
Linux namespaces: NET
x
Linux namespaces: NET
x
x
x
Linux namespaces: NET
x
Linux namespaces: NET
x
x
Linux namespaces: NET
x
x
x
Linux namespaces: NET
x
x
x
x
Wydajność: Native VS Container
• Wydajność to nie tylko CPU, ale również

• Sieć (veth, netfilter, NAT)

• Dysk (overlay2)
Docker Network Performance
1. iperf serwer oraz klient uruchomione natywnie na hoście
$ iperf -s

$ iperf -c 127.0.0.1 # 49.5 Gbits/sec
xx
Docker Network Performance
2. iperf serwer uruchomiony w kontenerze. Mapowanie portu 5001/TCP
pomiędzy hostem a kontenerem
$ export IPERF_INSTALL="apt-get update && apt-get install
iperf"
$ docker run --rm -ti -p 5001:5001 ubuntu:16.04 /bin/bash
-lic "${IPERF_INSTALL} && iperf -s"



$ iperf -c 127.0.0.1 # 19.5 Gbits/secx
x
x
Docker Network Performance
3.  Tak samo jak w punkcie (2) natomiast zamiast loopback (127.0.0.1)
użyjemy adresu IP przypisanego do eth0 hosta
$ export IPERF_INSTALL="apt-get update && apt-get install
iperf"
$ docker run --rm -ti -p 5001:5001 ubuntu:16.04 /bin/bash
-lic "${IPERF_INSTALL} && iperf -s"



$ iperf -c 192.168.0.100 # 40.5 Gbits/secx
x
x
Docker Network Performance
4.  iperf server uruchomiony w kontenerze, kontener korzysta z network
namespace hosta
$ export IPERF_INSTALL="apt-get update && apt-get install
iperf"
$ docker run --rm -ti --network host ubuntu:16.04 /bin/
bash -lic "${IPERF_INSTALL} && iperf -s"



$ iperf -c 127.0.0.1 # 49.3 Gbits/sec
$ iperf -c 192.168.0.100 # 49.1 Gbits/sec
x
x
x
x x
Docker Network Performance
1
iperf serwer uruchomiony natywnie na hoście

iperf klient uruchomiony natywnie na hoście
49,5 Gbits/sec
2
iperf serwer w kontenerze

iperf client łączy się przez loopback (127.0.0.1)
19,5 Gbits/sec
3
iperf serwer w kontenerze

iperf client łączy się używając adresu IP hosta
40,5 Gbits/sec
4
iperf server w kontenerze, kontener używa --network=host

iperf client łączy się przez loopback (127.0.0.1) oraz adres IP hosta
~49,2 Gbits/
sec
Docker Network Performance
• Docker używa netfilter do zarządzania ruchem pomiędzy kontenerem i
hostem (DNAT, MASQUERADE)

$ iptables -L -n 

$ iptables -L -n -t nat

• Kernel nie pozwala na filtrowanie ruchu na interface loopback (127.0.0.1),
więc docker dodatkowo uruchamia proces docker-proxy

• Docker-proxy działa w user-space, dlatego widać zauważalną różnice
(49 Gbits/sec VS 19 Gbits/sec)
Docker Storage Performance
• Kontenery dockerowe działają w oparciu o warstwowy system plików

• Mamy do dyspozycji wiele rodzajów storage-u:

• DeviceMapper (niska wydajność bez konfiguracji)

• BTRFS/ZFS (dobra wydajność, zaawansowane ficzery, wymaga zarządzania i
setupu)

• VFS (nieska wydajność, w ostateczności do developmentu)s

• AUFS (Dockera 18.06 i starsze, Ubutnu 14.04, Kernel 3.13 bez Overlay2)

• Overlay2 (rekomendowany)
Warstwowy system plików
Warstwowy system plików
Jak działa Overlay2?
Problemy / Limity OverlayFS
• open(2) - overlay2 obsługuję tylko podzbiór standardu POSIX

• fd1=open("foo", O_RDONLY)
• fd2=open("foo", O_RDWR)
• po operacji "copy_up" (otwarcie pliku w celu zapisu) fd1 oraz fd2 wskazują na dwa różne pliki

• fd1 wskazuje na plik z "lowerdir"

• fd2 wskazuje na plik z "upperdir"

• Obejściem problemu jest zrobienie touch przez co plik zostanie skopiowany do "upperdir"

• rename(2) również nie jest w pełni dobrze obsługiwane: trzeba obsłużyć failure i zrobić ręczni
"copy and unlink"
Przykład problemu z open(2)
$ cat Dockerfile 

FROM debian:wheezy



RUN apt-get update && 

apt-get install -y mysql-server
Przykład problemu z open(2)
$ cat Dockerfile 

FROM debian:wheezy



RUN apt-get update && 

apt-get install -y mysql-server
$ docker build -t tmp/mysql .

...
Przykład problemu z open(2)
$ cat Dockerfile 

FROM debian:wheezy



RUN apt-get update && 

apt-get install -y mysql-server
$ docker build -t tmp/mysql .

...
$ docker run -ti --name foo tmp/mysql /bin/bash

root@f778488d22bd:/# service mysql start

[FAIL] Starting MySQL database server: mysqld ... failed!
Przykład problemu z open(2)
$ docker diff foo

C /var

C /var/lib

C /var/lib/mysql

C /var/lib/mysql/ib_logfile0
Rozwiązanie: Docker Volumes
$ cat Dockerfile 

FROM debian:wheezy



VOLUME /var/lib/mysql

RUN apt-get update && 

apt-get install -y mysql-server

















Rozwiązanie: Docker Volumes
$ cat Dockerfile 

FROM debian:wheezy



VOLUME /var/lib/mysql

RUN apt-get update && 

apt-get install -y mysql-server
$ docker build -t tmp/mysql .

...








Rozwiązanie: Docker Volumes
$ cat Dockerfile 

FROM debian:wheezy



VOLUME /var/lib/mysql

RUN apt-get update && 

apt-get install -y mysql-server
$ docker build -t tmp/mysql .

...
$ docker run -ti --name foo tmp/mysql /bin/bash

root@f778488d22bd:/# service mysql start

[ ok ] Starting MySQL database server: mysqld ..

[info] Checking for tables which need an upgrade, are corrupt or
were not closed cleanly..
Czy VOLUME jest szybsze od Overlay2?
Czy VOLUME jest szybsze od Overlay2?
$ time docker build 

--no-cache 

--file Dockerfile01 . > /dev/null



real 0m37.643s

user 0m0.185s

sys 0m0.052s
x
x
Czy VOLUME jest szybsze od Overlay2?
$ time docker build 

--no-cache 

--file Dockerfile01 . > /dev/null



real 0m37.643s

user 0m0.185s

sys 0m0.052s
$ time docker build 

--no-cache 

--file Dockerfile02 . > /dev/null



real 0m27.955s

user 0m0.163s

sys 0m0.070s
x
x
x
x
Jeden kontener = jeden proces
• ... ale dlaczego? Best practice!

• Best practice? Dlaczego postgres i nginx uruchamia wiele procesów?

• hmm ... no dobra. Czepiasz się. Jeden kontener = jedna aplikacja

• itd. itd.

• https://docs.docker.com/config/containers/multi-service_container/

• ... w takim razie o co chodzi?
Jeden kontener = jeden proces
• Chodzi tu o zarządzanie procesami wewnątrz kontenera

• PID Namespace jest przypisywany do procesu, pierwszego który go stworzył

• Jeśli proces się kończy to stworzony PID Namespace przestaje istnieć

• ... nawet jeśli inny kontener go używa 

(--pid container:some-container)

• Musimy zatem posiadać jeden główny proces (PID 1, process "init"):

• obsługa sygnałów (TERM, INT) 

• zarządzanie procesami, które stworzył
Obsługa sygnałów
• docker kill wysyła sygnał SIGKILL ("kill -9 [process]")

• Nie ma możliwości obsłużenia tego sygnału

• Rodzaj sygnału można zmienić: docker kill -s TERM

• docker stop wysyła sygnał SIGTERM ("kill [process]")

• Jeśli process nie zostanie zakończony po upływie określonego czasu
(parametr -t|--time, domyślnie 10 sekund) to zostanie zabity (SIGKILL)
CMD: EXEC vs SHELL
• W Dockerfile przy pomocy instrukcji CMD możemy wskazać na proces, który zostanie uruchomiony
w kontenerze

• ... lub jeśli zdefiniowany ENTRYPOINT to wartość CMD zostanie przekazana do ENTRYPOINT jako
argument

• ENTRYPOINT ["/usr/bin/my-script"]

CMD ["start"]

Wynik: /usr/bin/my-script start

• CMD posiada dwie formy EXEC oraz SHELL

• EXEC - proces zostanie uruchomiony jako PID 1
• SHELL - najpierw zostanie uruchomiony shell (domyślnie /bin/sh -c ), a następnie nasza
aplikacja
Obsługa sygnałów: aplikacja
$ cat script.sh

#!/bin/sh

trap "echo Got signal! && exit" TERM INT



echo "pid is $$"



while :

do

sleep 1

done
Obsługa sygnałów: CMD EXEC
$ cat Dockerfile 

FROM ubuntu:18.04 

COPY script.sh /script.sh

CMD ["/script.sh"]
Obsługa sygnałów: CMD EXEC
$ cat Dockerfile 

FROM ubuntu:18.04 

COPY script.sh /script.sh

CMD ["/script.sh"]
$ docker build -t tmp/signal .

...



$ docker run --name foo tmp/signal

pid is 1

Obsługa sygnałów: CMD EXEC
$ cat Dockerfile 

FROM ubuntu:18.04 

COPY script.sh /script.sh

CMD ["/script.sh"]
$ docker build -t tmp/signal .

...



$ docker run --name foo tmp/signal

pid is 1

$ docker stop foo
Obsługa sygnałów: CMD EXEC
$ cat Dockerfile 

FROM ubuntu:18.04 

COPY script.sh /script.sh

CMD ["/script.sh"]
$ docker build -t tmp/signal .

...



$ docker run --name foo tmp/signal

pid is 1

Got signal!

$ $ docker stop foo
Obsługa sygnałów: CMD SHELL
$ cat Dockerfile 

FROM ubuntu:18.04 

COPY script.sh /script.sh

CMD /script.sh
Obsługa sygnałów: CMD SHELL
$ cat Dockerfile 

FROM ubuntu:18.04 

COPY script.sh /script.sh

CMD /script.sh
Poprzednia wartość



CMD ["/script.sh"]
Obsługa sygnałów: CMD SHELL
$ cat Dockerfile 

FROM ubuntu:18.04 

COPY script.sh /script.sh

CMD /script.sh
$ docker build -t tmp/signal .

...



$ docker run --name foo tmp/signal

pid is 6 

Obsługa sygnałów: CMD SHELL
$ cat Dockerfile 

FROM ubuntu:18.04 

COPY script.sh /script.sh

CMD /script.sh
$ docker build -t tmp/signal .

...



$ docker run --name foo tmp/signal

pid is 6

$ docker stop foo
Obsługa sygnałów: CMD SHELL
$ cat Dockerfile 

FROM ubuntu:18.04 

COPY script.sh /script.sh

CMD /script.sh
$ docker build -t tmp/signal .

...



$ docker run --name foo tmp/signal

pid is 6

$
$ docker stop foo
Pytania?
Kamil Grabowski

<kamil.grabowski@gmail.com>
Dziękuję :)

More Related Content

What's hot

Noc informatyka
Noc informatykaNoc informatyka
Noc informatyka
OnetIT
 
PLNOG 21: Alek Cesarz, Piotr Misiak - Petabajty_z_kosmosu_(serio)
PLNOG 21: Alek Cesarz, Piotr Misiak - Petabajty_z_kosmosu_(serio)PLNOG 21: Alek Cesarz, Piotr Misiak - Petabajty_z_kosmosu_(serio)
PLNOG 21: Alek Cesarz, Piotr Misiak - Petabajty_z_kosmosu_(serio)
PROIDEA
 

What's hot (20)

Monitoring sieci
Monitoring sieciMonitoring sieci
Monitoring sieci
 
Laravel Poznań Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...
Laravel Poznań Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...Laravel Poznań Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...
Laravel Poznań Meetup #3 - Uruchomienie i praca z Laravel w wirtualnym konten...
 
Uruchomienie i praca z laravel w wirtualnym kontenerze docker'a
Uruchomienie i praca z laravel w wirtualnym kontenerze docker'aUruchomienie i praca z laravel w wirtualnym kontenerze docker'a
Uruchomienie i praca z laravel w wirtualnym kontenerze docker'a
 
Ansible - Automatyzacja zadań IT
Ansible - Automatyzacja zadań ITAnsible - Automatyzacja zadań IT
Ansible - Automatyzacja zadań IT
 
“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...
“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...
“Dziesięć serwerów poproszę!“, czyli co może Ci zaoferować definiowanie infra...
 
PLNOG 6: Łukasz Jagiełło - Wdrożenie skalowalnego systemu plików GlusterFS w ...
PLNOG 6: Łukasz Jagiełło - Wdrożenie skalowalnego systemu plików GlusterFS w ...PLNOG 6: Łukasz Jagiełło - Wdrożenie skalowalnego systemu plików GlusterFS w ...
PLNOG 6: Łukasz Jagiełło - Wdrożenie skalowalnego systemu plików GlusterFS w ...
 
Infrastructure As Code
Infrastructure As CodeInfrastructure As Code
Infrastructure As Code
 
Kainos Tech Space #1 : DevOps : Artur Senk - Jenkins, najważniejsze narzędzie...
Kainos Tech Space #1 : DevOps : Artur Senk - Jenkins, najważniejsze narzędzie...Kainos Tech Space #1 : DevOps : Artur Senk - Jenkins, najważniejsze narzędzie...
Kainos Tech Space #1 : DevOps : Artur Senk - Jenkins, najważniejsze narzędzie...
 
Złam zasady i stwórz wydajny stos IP przy użyciu DPDK
Złam zasady i stwórz wydajny stos IP przy użyciu DPDKZłam zasady i stwórz wydajny stos IP przy użyciu DPDK
Złam zasady i stwórz wydajny stos IP przy użyciu DPDK
 
Noc informatyka
Noc informatykaNoc informatyka
Noc informatyka
 
Hugo - make webdev fun again
Hugo - make webdev fun againHugo - make webdev fun again
Hugo - make webdev fun again
 
Swoole w PHP. Czy to ma sens?
Swoole w PHP. Czy to ma sens?Swoole w PHP. Czy to ma sens?
Swoole w PHP. Czy to ma sens?
 
Aplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/ReduxAplikacje internetowe real-time w oparciu o React/Redux
Aplikacje internetowe real-time w oparciu o React/Redux
 
Testowanie rozwiązań serverless z LocalStack
Testowanie rozwiązań serverless z LocalStackTestowanie rozwiązań serverless z LocalStack
Testowanie rozwiązań serverless z LocalStack
 
Websockety w PHP
Websockety w PHPWebsockety w PHP
Websockety w PHP
 
Devbox - wirtualne środowisko pracy
Devbox - wirtualne środowisko pracyDevbox - wirtualne środowisko pracy
Devbox - wirtualne środowisko pracy
 
Ansible w praktyce
Ansible w praktyceAnsible w praktyce
Ansible w praktyce
 
PLNOG 21: Alek Cesarz, Piotr Misiak - Petabajty_z_kosmosu_(serio)
PLNOG 21: Alek Cesarz, Piotr Misiak - Petabajty_z_kosmosu_(serio)PLNOG 21: Alek Cesarz, Piotr Misiak - Petabajty_z_kosmosu_(serio)
PLNOG 21: Alek Cesarz, Piotr Misiak - Petabajty_z_kosmosu_(serio)
 
Shall we play a game? PL version
Shall we play a game? PL versionShall we play a game? PL version
Shall we play a game? PL version
 
infraxstructure: Robert Mroczkowski "Maszyny się uczą - admińskie rozmówki p...
infraxstructure: Robert Mroczkowski  "Maszyny się uczą - admińskie rozmówki p...infraxstructure: Robert Mroczkowski  "Maszyny się uczą - admińskie rozmówki p...
infraxstructure: Robert Mroczkowski "Maszyny się uczą - admińskie rozmówki p...
 

Similar to Sekrety magicznego ogrodu Docker

Similar to Sekrety magicznego ogrodu Docker (20)

PHP@Docker - w produkcji
PHP@Docker - w produkcjiPHP@Docker - w produkcji
PHP@Docker - w produkcji
 
Przenieś się do kontenera, czyli korzyści z Docker i Docker Compose
Przenieś się do kontenera, czyli korzyści z Docker i Docker ComposePrzenieś się do kontenera, czyli korzyści z Docker i Docker Compose
Przenieś się do kontenera, czyli korzyści z Docker i Docker Compose
 
Docker
DockerDocker
Docker
 
100 M pakietów na sekundę dla każdego.
100 M pakietów na sekundę dla każdego. 100 M pakietów na sekundę dla każdego.
100 M pakietów na sekundę dla każdego.
 
[QE 2017] Adrian Gonciarz - Tester w Kontenerze, czyli jak Docker może pomóc ...
[QE 2017] Adrian Gonciarz - Tester w Kontenerze, czyli jak Docker może pomóc ...[QE 2017] Adrian Gonciarz - Tester w Kontenerze, czyli jak Docker może pomóc ...
[QE 2017] Adrian Gonciarz - Tester w Kontenerze, czyli jak Docker może pomóc ...
 
Kubernetes i Docker Swarm - Tomasz Woszczynski
Kubernetes i Docker Swarm - Tomasz WoszczynskiKubernetes i Docker Swarm - Tomasz Woszczynski
Kubernetes i Docker Swarm - Tomasz Woszczynski
 
CruiseControl.rb
CruiseControl.rbCruiseControl.rb
CruiseControl.rb
 
Od Zera do Farmera
Od Zera do FarmeraOd Zera do Farmera
Od Zera do Farmera
 
Michał Dec - Quality in Clouds
Michał Dec - Quality in CloudsMichał Dec - Quality in Clouds
Michał Dec - Quality in Clouds
 
Wprowadzenie do Kubernetesa. K8S jako nowy Linux.
Wprowadzenie do Kubernetesa. K8S jako nowy Linux.Wprowadzenie do Kubernetesa. K8S jako nowy Linux.
Wprowadzenie do Kubernetesa. K8S jako nowy Linux.
 
OpenEmbedded
OpenEmbeddedOpenEmbedded
OpenEmbedded
 
PLNOG22 - Piotr Stolarek - Bezpieczeństwo użytkowania platform usługowych Tel...
PLNOG22 - Piotr Stolarek - Bezpieczeństwo użytkowania platform usługowych Tel...PLNOG22 - Piotr Stolarek - Bezpieczeństwo użytkowania platform usługowych Tel...
PLNOG22 - Piotr Stolarek - Bezpieczeństwo użytkowania platform usługowych Tel...
 
Programowanie sterowników w Linuksie.
Programowanie sterowników w Linuksie.Programowanie sterowników w Linuksie.
Programowanie sterowników w Linuksie.
 
Gluster FS
Gluster FSGluster FS
Gluster FS
 
Serwer internetowy w systemie Linux
Serwer internetowy w systemie LinuxSerwer internetowy w systemie Linux
Serwer internetowy w systemie Linux
 
Make deploy great again!
Make deploy great again!Make deploy great again!
Make deploy great again!
 
Torquebox
TorqueboxTorquebox
Torquebox
 
Piątek z XSolve - TravisCI & Continuous Delivery
Piątek z XSolve - TravisCI & Continuous DeliveryPiątek z XSolve - TravisCI & Continuous Delivery
Piątek z XSolve - TravisCI & Continuous Delivery
 
Net core (dawniej 5.0) – co to dla mnie. też dużo o open source
Net core (dawniej   5.0) – co to dla mnie. też dużo o open sourceNet core (dawniej   5.0) – co to dla mnie. też dużo o open source
Net core (dawniej 5.0) – co to dla mnie. też dużo o open source
 
Stosy sieciowe w przestrzeni użytkownika.
Stosy sieciowe w przestrzeni użytkownika.Stosy sieciowe w przestrzeni użytkownika.
Stosy sieciowe w przestrzeni użytkownika.
 

More from Kamil Grabowski

More from Kamil Grabowski (7)

Jak wygrać Igrzyska Chmury
Jak wygrać Igrzyska ChmuryJak wygrać Igrzyska Chmury
Jak wygrać Igrzyska Chmury
 
Porażka nie wchodzi w grę, czyli o niezawodności
Porażka nie wchodzi w grę, czyli o niezawodnościPorażka nie wchodzi w grę, czyli o niezawodności
Porażka nie wchodzi w grę, czyli o niezawodności
 
Docker
DockerDocker
Docker
 
RRDTool + RUBY DSL = RRD-FFI
RRDTool + RUBY DSL = RRD-FFIRRDTool + RUBY DSL = RRD-FFI
RRDTool + RUBY DSL = RRD-FFI
 
Jak wyglada monitoring w PLIX
Jak wyglada monitoring w PLIXJak wyglada monitoring w PLIX
Jak wyglada monitoring w PLIX
 
Sprzetowe i programowe aspekty punktu wymiany ruchu
Sprzetowe i programowe aspekty punktu wymiany ruchuSprzetowe i programowe aspekty punktu wymiany ruchu
Sprzetowe i programowe aspekty punktu wymiany ruchu
 
How to create effective NOC in Poland
How to create effective NOC in PolandHow to create effective NOC in Poland
How to create effective NOC in Poland
 

Sekrety magicznego ogrodu Docker

  • 2. Najczęstsze mity na temat Dockera • "Docker jest dobry tylko do developmentu. Trzeba być nieodpowiedzialnym, aby używać Dockera na produkcji" • "Docker to takie lekkie maszyny wirtualne" • "Nie ma różnicy w wydajności. Kontener dockerowy to przecież zwykły proces linuksowy" • "Nie powinno się uruchamiać baz danych w Dockerze, ponieważ bardzo łatwo można stracić dane. Docker jest dobry, ale tylko do aplikacji stateless" • "W kontenerze dockerowym powinien być uruchomiony tylko jeden proces"
  • 3. Co jest tego powodem? • Docker wystartował będąc bardzo młodym projektem, dużo eksperymentowano • Ludzie nie czytają dokumentacji • Ludzie nie śledzą zmian • Ludzie używają starszych wersji oprogramowania (np. docker z repozytorium Ubuntu/Debian, starsze wersje kernela) • Sporo artykułów, blogów, prezentacji opisuje rozwiązania, które są już deprecated lub też są lepsze metody na rozwiązanie danego problemu • ... a czasem CORE Team Dockera rzeczywiście coś spierniczył ;)
  • 4. Docker to takie lekkie maszyny wirtualne
  • 5. Docker to takie lekkie maszyny wirtualne • RootFS to nie jest to samo co system operacyjny czy też dystrybucja Linuksa (kernel, init process, message logger itp.) • Idea "lekkiej maszyny wirtualnej" to generator "pomysło-problemów": zainstalujmy SSH serwer, systemd, rsyslog, cron
  • 6. Docker to nie maszyna wirtualna • Linux namespaces • pid • net • mnt • user • ipc • cgroups • Warstwowy system plików (overlay2, aufs etc.) • VETH - Virtual Ethernet Device
  • 11. Linux namespaces: PID x x x x x x x x
  • 12. Linux namespaces: PID x x x x x x x x
  • 21. Wydajność: Native VS Container • Wydajność to nie tylko CPU, ale również • Sieć (veth, netfilter, NAT) • Dysk (overlay2)
  • 22. Docker Network Performance 1. iperf serwer oraz klient uruchomione natywnie na hoście $ iperf -s
 $ iperf -c 127.0.0.1 # 49.5 Gbits/sec
xx
  • 23. Docker Network Performance 2. iperf serwer uruchomiony w kontenerze. Mapowanie portu 5001/TCP pomiędzy hostem a kontenerem $ export IPERF_INSTALL="apt-get update && apt-get install iperf" $ docker run --rm -ti -p 5001:5001 ubuntu:16.04 /bin/bash -lic "${IPERF_INSTALL} && iperf -s"
 
 $ iperf -c 127.0.0.1 # 19.5 Gbits/secx x x
  • 24. Docker Network Performance 3.  Tak samo jak w punkcie (2) natomiast zamiast loopback (127.0.0.1) użyjemy adresu IP przypisanego do eth0 hosta $ export IPERF_INSTALL="apt-get update && apt-get install iperf" $ docker run --rm -ti -p 5001:5001 ubuntu:16.04 /bin/bash -lic "${IPERF_INSTALL} && iperf -s"
 
 $ iperf -c 192.168.0.100 # 40.5 Gbits/secx x x
  • 25. Docker Network Performance 4.  iperf server uruchomiony w kontenerze, kontener korzysta z network namespace hosta $ export IPERF_INSTALL="apt-get update && apt-get install iperf" $ docker run --rm -ti --network host ubuntu:16.04 /bin/ bash -lic "${IPERF_INSTALL} && iperf -s"
 
 $ iperf -c 127.0.0.1 # 49.3 Gbits/sec $ iperf -c 192.168.0.100 # 49.1 Gbits/sec x x x x x
  • 26. Docker Network Performance 1 iperf serwer uruchomiony natywnie na hoście
 iperf klient uruchomiony natywnie na hoście 49,5 Gbits/sec 2 iperf serwer w kontenerze
 iperf client łączy się przez loopback (127.0.0.1) 19,5 Gbits/sec 3 iperf serwer w kontenerze
 iperf client łączy się używając adresu IP hosta 40,5 Gbits/sec 4 iperf server w kontenerze, kontener używa --network=host
 iperf client łączy się przez loopback (127.0.0.1) oraz adres IP hosta ~49,2 Gbits/ sec
  • 27. Docker Network Performance • Docker używa netfilter do zarządzania ruchem pomiędzy kontenerem i hostem (DNAT, MASQUERADE) $ iptables -L -n 
 $ iptables -L -n -t nat • Kernel nie pozwala na filtrowanie ruchu na interface loopback (127.0.0.1), więc docker dodatkowo uruchamia proces docker-proxy • Docker-proxy działa w user-space, dlatego widać zauważalną różnice (49 Gbits/sec VS 19 Gbits/sec)
  • 28. Docker Storage Performance • Kontenery dockerowe działają w oparciu o warstwowy system plików • Mamy do dyspozycji wiele rodzajów storage-u: • DeviceMapper (niska wydajność bez konfiguracji) • BTRFS/ZFS (dobra wydajność, zaawansowane ficzery, wymaga zarządzania i setupu) • VFS (nieska wydajność, w ostateczności do developmentu)s • AUFS (Dockera 18.06 i starsze, Ubutnu 14.04, Kernel 3.13 bez Overlay2) • Overlay2 (rekomendowany)
  • 32. Problemy / Limity OverlayFS • open(2) - overlay2 obsługuję tylko podzbiór standardu POSIX • fd1=open("foo", O_RDONLY) • fd2=open("foo", O_RDWR) • po operacji "copy_up" (otwarcie pliku w celu zapisu) fd1 oraz fd2 wskazują na dwa różne pliki • fd1 wskazuje na plik z "lowerdir" • fd2 wskazuje na plik z "upperdir" • Obejściem problemu jest zrobienie touch przez co plik zostanie skopiowany do "upperdir" • rename(2) również nie jest w pełni dobrze obsługiwane: trzeba obsłużyć failure i zrobić ręczni "copy and unlink"
  • 33. Przykład problemu z open(2) $ cat Dockerfile 
 FROM debian:wheezy
 
 RUN apt-get update && 
 apt-get install -y mysql-server
  • 34. Przykład problemu z open(2) $ cat Dockerfile 
 FROM debian:wheezy
 
 RUN apt-get update && 
 apt-get install -y mysql-server $ docker build -t tmp/mysql .
 ...
  • 35. Przykład problemu z open(2) $ cat Dockerfile 
 FROM debian:wheezy
 
 RUN apt-get update && 
 apt-get install -y mysql-server $ docker build -t tmp/mysql .
 ... $ docker run -ti --name foo tmp/mysql /bin/bash
 root@f778488d22bd:/# service mysql start
 [FAIL] Starting MySQL database server: mysqld ... failed!
  • 36. Przykład problemu z open(2) $ docker diff foo
 C /var
 C /var/lib
 C /var/lib/mysql
 C /var/lib/mysql/ib_logfile0
  • 37. Rozwiązanie: Docker Volumes $ cat Dockerfile 
 FROM debian:wheezy
 
 VOLUME /var/lib/mysql
 RUN apt-get update && 
 apt-get install -y mysql-server
 
 
 
 
 
 
 
 

  • 38. Rozwiązanie: Docker Volumes $ cat Dockerfile 
 FROM debian:wheezy
 
 VOLUME /var/lib/mysql
 RUN apt-get update && 
 apt-get install -y mysql-server $ docker build -t tmp/mysql .
 ... 
 
 
 

  • 39. Rozwiązanie: Docker Volumes $ cat Dockerfile 
 FROM debian:wheezy
 
 VOLUME /var/lib/mysql
 RUN apt-get update && 
 apt-get install -y mysql-server $ docker build -t tmp/mysql .
 ... $ docker run -ti --name foo tmp/mysql /bin/bash
 root@f778488d22bd:/# service mysql start
 [ ok ] Starting MySQL database server: mysqld ..
 [info] Checking for tables which need an upgrade, are corrupt or were not closed cleanly..
  • 40. Czy VOLUME jest szybsze od Overlay2?
  • 41. Czy VOLUME jest szybsze od Overlay2? $ time docker build 
 --no-cache 
 --file Dockerfile01 . > /dev/null
 
 real 0m37.643s
 user 0m0.185s
 sys 0m0.052s x x
  • 42. Czy VOLUME jest szybsze od Overlay2? $ time docker build 
 --no-cache 
 --file Dockerfile01 . > /dev/null
 
 real 0m37.643s
 user 0m0.185s
 sys 0m0.052s $ time docker build 
 --no-cache 
 --file Dockerfile02 . > /dev/null
 
 real 0m27.955s
 user 0m0.163s
 sys 0m0.070s x x x x
  • 43. Jeden kontener = jeden proces • ... ale dlaczego? Best practice! • Best practice? Dlaczego postgres i nginx uruchamia wiele procesów? • hmm ... no dobra. Czepiasz się. Jeden kontener = jedna aplikacja • itd. itd. • https://docs.docker.com/config/containers/multi-service_container/ • ... w takim razie o co chodzi?
  • 44. Jeden kontener = jeden proces • Chodzi tu o zarządzanie procesami wewnątrz kontenera • PID Namespace jest przypisywany do procesu, pierwszego który go stworzył • Jeśli proces się kończy to stworzony PID Namespace przestaje istnieć • ... nawet jeśli inny kontener go używa 
 (--pid container:some-container) • Musimy zatem posiadać jeden główny proces (PID 1, process "init"): • obsługa sygnałów (TERM, INT) • zarządzanie procesami, które stworzył
  • 45. Obsługa sygnałów • docker kill wysyła sygnał SIGKILL ("kill -9 [process]") • Nie ma możliwości obsłużenia tego sygnału • Rodzaj sygnału można zmienić: docker kill -s TERM • docker stop wysyła sygnał SIGTERM ("kill [process]") • Jeśli process nie zostanie zakończony po upływie określonego czasu (parametr -t|--time, domyślnie 10 sekund) to zostanie zabity (SIGKILL)
  • 46. CMD: EXEC vs SHELL • W Dockerfile przy pomocy instrukcji CMD możemy wskazać na proces, który zostanie uruchomiony w kontenerze • ... lub jeśli zdefiniowany ENTRYPOINT to wartość CMD zostanie przekazana do ENTRYPOINT jako argument • ENTRYPOINT ["/usr/bin/my-script"]
 CMD ["start"]
 Wynik: /usr/bin/my-script start • CMD posiada dwie formy EXEC oraz SHELL • EXEC - proces zostanie uruchomiony jako PID 1 • SHELL - najpierw zostanie uruchomiony shell (domyślnie /bin/sh -c ), a następnie nasza aplikacja
  • 47. Obsługa sygnałów: aplikacja $ cat script.sh
 #!/bin/sh
 trap "echo Got signal! && exit" TERM INT
 
 echo "pid is $$"
 
 while :
 do
 sleep 1
 done
  • 48. Obsługa sygnałów: CMD EXEC $ cat Dockerfile 
 FROM ubuntu:18.04 
 COPY script.sh /script.sh
 CMD ["/script.sh"]
  • 49. Obsługa sygnałów: CMD EXEC $ cat Dockerfile 
 FROM ubuntu:18.04 
 COPY script.sh /script.sh
 CMD ["/script.sh"] $ docker build -t tmp/signal .
 ...
 
 $ docker run --name foo tmp/signal
 pid is 1

  • 50. Obsługa sygnałów: CMD EXEC $ cat Dockerfile 
 FROM ubuntu:18.04 
 COPY script.sh /script.sh
 CMD ["/script.sh"] $ docker build -t tmp/signal .
 ...
 
 $ docker run --name foo tmp/signal
 pid is 1
 $ docker stop foo
  • 51. Obsługa sygnałów: CMD EXEC $ cat Dockerfile 
 FROM ubuntu:18.04 
 COPY script.sh /script.sh
 CMD ["/script.sh"] $ docker build -t tmp/signal .
 ...
 
 $ docker run --name foo tmp/signal
 pid is 1
 Got signal!
 $ $ docker stop foo
  • 52. Obsługa sygnałów: CMD SHELL $ cat Dockerfile 
 FROM ubuntu:18.04 
 COPY script.sh /script.sh
 CMD /script.sh
  • 53. Obsługa sygnałów: CMD SHELL $ cat Dockerfile 
 FROM ubuntu:18.04 
 COPY script.sh /script.sh
 CMD /script.sh Poprzednia wartość
 
 CMD ["/script.sh"]
  • 54. Obsługa sygnałów: CMD SHELL $ cat Dockerfile 
 FROM ubuntu:18.04 
 COPY script.sh /script.sh
 CMD /script.sh $ docker build -t tmp/signal .
 ...
 
 $ docker run --name foo tmp/signal
 pid is 6 

  • 55. Obsługa sygnałów: CMD SHELL $ cat Dockerfile 
 FROM ubuntu:18.04 
 COPY script.sh /script.sh
 CMD /script.sh $ docker build -t tmp/signal .
 ...
 
 $ docker run --name foo tmp/signal
 pid is 6
 $ docker stop foo
  • 56. Obsługa sygnałów: CMD SHELL $ cat Dockerfile 
 FROM ubuntu:18.04 
 COPY script.sh /script.sh
 CMD /script.sh $ docker build -t tmp/signal .
 ...
 
 $ docker run --name foo tmp/signal
 pid is 6
 $ $ docker stop foo