Lista jest pewnie dużo dłuższa, ale poniższe dały mi się we znaki:
Nie uruchomisz openvpn’a
Kontenery domyślnie nie pozwalają na ingerencje w sieci systemu operacyjnego. Przez to nie da się w łatwy sposób uruchomić np. OpenVPN, który potrzebuje stworzyć własny interfejs sieciowy tun/tap. Czasami uruchamiając kontenery w różnych miejscach świata i w różnych serwerowniach postawienie VPN’a spinającego je wszystkie ze sobą jest dość wygodnym rozwiązaniem, dodatkowo dającym bezpieczeństwo.
Aby podłączyć taką sieć do kontenera trzeba się albo pogimnastykować z routingiem w systemie gospodarza albo poczarować z uprawnieniami kontenera. Aby to zrobić trzeba uruchomić nowy obraz z parametrem –cap-add=NET_ADMIN, który zwiększa możliwości ingerencji w macierzysty system, a w szczególności w konfigurację jego sieci.
Nie poda piwa
z drugiej strony zwykły desktop też piwa nie poda. Ale chociaż potrzyma na tacce cd, a docker nie. Idźmy dalej.
Debugowanie programów
Kolejną rzeczą jest debugowanie kodu. Debugger (np. gdb) wymaga dość głębokiego integrowania się z inną aplikacją, które jest zwykle wykonywane przez funkcję ptrace. Funkcja ta pozwala pisać i czytać po pamięci innych programów, które chcemy badać. Dzięki ptrace debuger może zatrzymać wykonywanie programu w wybranym przez siebie miejscu, wykonywać go krok po kroku lub przechwytywać (i zmieniać) przerwania systemowe. Z systemowej funkcji ptrace korzysta też programik strace, pokazujący co program aktualnie robi, przechwytując jego przerwania oraz User Mode Linux, który podmienia przerwania systemowe na własne.
Aby umożliwić korzystanie z ptrace w kontenerze, musimy dodać mu flagę –cap-add SYS_PTRACE, która przez linux capabilities pozwoli na dostęp do tej funkcji.
Nici z network namespaces
Czasami potrzeba wykonać coś więcej, niż sam VPN i poczarować np. z przestrzeniami nazw aby uruchomić niektóre narzędzia (np. podczas pisania i testów CoreCluster). Podobnie jak przy konfiguracji VPN, tutaj też Docker ograniczy nam taką możliwość. Można to obejść podobnie, przez capabilities.
Czyli jak się da obejść to jednak nie ogranicza?
W sumie tak. Ale należy pamiętać, że dodając kontenerowi każdą taką flagę ryzykujemy, że kod uruchomiony w kontenerze będzie mógł w jakiś sposób przejść do systemu gospodarza. Idąc tą drogą możemy pozdejmować wszystkie ograniczenia Dockera (lub innego silnika kontenerów) i cieszyć się nieskrępowaną pracą w łatwo zarządzalnym chroot. W ten sposób dostajemy wtedy sam chroot, z którego prawdopodobnie będziemy mogli łatwo wyjść, podobnie jak potencjalny intruz, który mógłby być nieco lepiej powstrzymany przez ograniczonego dockera (w domyślnej konfiguracji). Z drugiej strony wszyscy więksi dostawcy usług, oferujący silnik kontenerów nigdy nie dają dockera bezpośrednio na swoim sprzęcie, a za pośrednictwem wirtualnych maszyn, które nie są współdzielone pomiędzy użytkownikami.
Podsumowując, Docker mimo swoich fajnych narzędzi pozostawia trochę ograniczeń na to, co możemy wykonać w kontenerze. Tyczy się to prawdopodobnie również innych silników. W takich przypadkach (których zapewne znajdzie się znacznie więcej) możemy posiłkować się starą, dobrą wirtualizacją, która daje w pełni funkcjonalny system. Wykorzystując obrazy Copy On Write i Kernel Same Page Mapping możemy znacznie ograniczyć użycie pamięci i przestrzeni dyskowej potrzebnej na wirtualne maszyny, zachowując pełną funkcjonalność.