Docker Socket – czyli /var/run/docker.sock

Jeżeli kiedykolwiek korzystałeś z Dockera metodą Kopiego-Pasty, być może spotkałeś się już z następującym argumentem:
-v /var/run/docker.sock:/var/run/docker.sock

Co to jest i jaką pełni rolę? Dlaczego czasami jest wykorzystywany, a czasami nie – oraz w jakich przypadkach warto wiedzieć, o co w tym wszystkim chodzi?

TLDR;

Chcąc ująć to w jednym zdaniu: “Jest to Unix Socket, na którym domyślnie nasłuchuje Docker Daemon.”

Wystarczy zerknąć na powyższy diagram i w zasadzie wszystko powinno być już jasne ; -)

Dzięki podmontowaniu pliku /var/run/docker.sock (znajdującego się na hoście), kontener może komunikować się z Docker Deamonem – czyli jednym z komponentów wchodzących w skład architektury Dockera. Docker Daemon odpowiada za przyjmowanie “rozkazów” i przekazanie ich w dół, do warstwy OCI (container runtime).

Porównując to do architektury klient-serwer, kontener może stać się klientem, a Docker Deamon – serwerem.


Docker API

Jeżeli kiedykolwiek wpisałeś w terminalu docker container run (bądź też docker run) to na 99% “pod spodem” wykorzystałeś Docker Daemon Socket.

Jest to domyślny typ komunikacji pomiędzy Docker CLI a Docker Daemonem. Domyślny nie oznacza, że nie można go zmienić, ale tym za chwilę.

Gdy korzystamy z Docker CLI, np. docker image ls – automatycznie (w tle) dorzucany jest parametr -H unix:///var/run/docker.sock.

Parametr -H to informacja dla Docker CLI, z jakim Docker Daemonem ma się skomunikować. Inaczej mówiąc, gdzie polecenie ma zostać wykonane.


Warto podkreślić, że do parametru -H można przekazać również inną wartość. Na przykład adres hosta i port TCP lub inny unix socket.

WAŻNE: Jeżeli chcemy by Docker CLI komunikował się z Docker Daemonem po protokole TCP – zamiast Unix Sockets, należy pamiętać by najpierw “włączyć” ten typ komunikacji w ustawieniach Docker Daemon’a.

Jeżeli to, co do tej pory przeczytałeś odnośnie komunikacji na lini Docker CLI => Docker Daemon – nie jest dla Ciebie do końca zrozumiałe, to koniecznie zerknij TUTAJ, gdzie jakiś czasu temu opisywałem, w jaki sposób komunikować się ze zdalnym Docker Hostem z wykorzystaniem Docker Contexts.


Portainer – pierwszy przykład zastosowania

Wykorzystanie pliku /var/run/docker.sock możemy spotkać na przykład przy uruchamianiu Portainera – narzędzia do zarządzania Dockerem z poziomu przeglądarki.

$ docker container run -d \
  -p 9000:9000 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  portainer/portainer

Portainer to aplikacja webowa, która umożliwia zarządzanie poszczególnymi obiektami w Dockerze (obrazy, kontenery, volumeny itd.)

Zamiast wpisywania docker container stop <moj_kontener> czy też innych poleceń – możesz to “wyklikać”. Ale nie o tym dzisiaj.

Dzięki podmontowaniu pliku /var/run/docker.sock – Portainer uruchomiony w kontenerze może komunikować się z Docker Daemonem. Inaczej mówiąc, kontener Portainera otrzymuje dostęp do głównego Dockera, na którym został uruchomiony.


Szukasz wiedzy z zakresu konteneryzacji?

Sprawdź koniecznie mój autorski program DOCKER MAESTRO

Najbardziej obszerny kurs online z Dockera po polsku

* minimum 13 godzin materiału (nowe materiału w produkcji)
dożywotni dostęp do materiałów & aktualizacji
certyfikat Docker Maestro
gwarancja satysfakcji 
(masz 14 dni na zwrot kasy, licząc od dnia zakupu, jeśli COKOLWIEK Ci się nie spodoba)


Portainer & Docker API – jak to działa?

Najczęściej stosowanym typem komunikacji po HTTP jest protokoł TCP.

W przypadku Portainera – żądania HTTP do Docker Daemona nie są jednak wysyłane po TCP, ale właśnie przez Unix Socket.

Jeżeli wyklikamy w Portainerze utworzenie kontenera na podstawie obrazu wordpress, to pod spodem zostanie wykonane zbliżone polecenie:

curl -XPOST --unix-socket /var/run/docker.sock -d '{"Image":"wordpress"}' \
-H 'Content-Type: application/json' http://localhost/containers/create

{"Id":"fcb65c6147efb862d5ea3a2ef20e793c52f0fafa3eb04e4292cb4784c5777d65","Warnings":null}

Istnieje możliwość skonfigurowania Docker Daemona tak, by oprócz Unix Socket, dodatkowo nasłuchiwał po protokole TCP.

Z perspektywy bezpieczeństwa jest to jednak niezalecane.

Trzeba wiedzieć co się robi, i jak to działa. W przeciwnym wypadku – może to zostać wykorzystane przeciwko nam (przez osoby trzecie). Przykład takiego “włamania” do Docker Daemona można znaleźć TUTAJ.


Narzędzia do CI/CD w kontenerze (Gitlab, Jenkins)

Od dłuższego czasu, narzędzia takie jak GitLab czy Jenkins możemy uruchomić z poziomu Dockera. Obydwa narzędzia mogą być z powodzeniem wykorzystane do skonfigurowania procesów automatycznego budowania i publikowania obrazów w Docker Registry.

Swego czasu w takich zastosowaniach modne było podejście Docker-in-Docker. To podejście miało jednak sporo wad i szybko zostały uznane jako “anti-pattern”.

Aby mieć możliwość dostępu do “głównego” Dockera, bądź też – aby móc budować obrazy w skonteneryzowanym Gitlabie czy Jenkinsie – wystarczy podmontować Docker Socket.


Przykład – Gitlab Runner

Jak wspominałem wcześniej, istnieje możliwość uruchomienia lokalnej instancji GitLaba z poziomu Dockera. Gdy już to zrobimy, chcemy mieć możliwość automatycznego budowania obrazów.

Aby zbudować docker image, kontener gitlab-runner potrzebuje działającej instancji Dockera. (pamiętajmy, że kontener Gitlab Runnera to tak naprawdę tylko linuxowy proces!)

version: '3.5'

services:

  gitlab:
    image: gitlab/gitlab-ce:latest
    container_name: gitlab
    restart: always
    ...
    ...
 
  gitlab-runner:
    image: gitlab/gitlab-runner:alpine
    container_name: gitlab-runner
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /srv/gitlab-runner/config:/etc/gitlab-runner
    depends_on:
      - gitlab

Obecnie rekomendowanym podejściem jest podmontowanie /var/run/docker.sock:/var/run/docker.sock – dzięki czemu budowanie obrazów odbywa się na “głównym” Dockerze (pomimo tego, że cały GitLab jest uruchomionyjako kontener).

Benefitem tego rozwiązania jest przede wszystkim pełne wykorzystanie cache podczas budowania obrazów — gdyż cały proces wykonywany jest ZAWSZE na tej samej (i jedynej) instancji Dockera.


Podsumowanie

Mam nadzieję, że ten post pozwolił Ci na zrozumienie, w jakim celu wykorzystywany jest Docker Socket.

Podmontowanie pliku /var/run/docker.sock może pozwalać na zarządzanie Dockerem z poziomu kontenera. Daje nam to ogrom możliwości i może mieć zastosowanie w narzędziach integrujących się z Dockerem, czy procesach CI/CD.

PS. Jeżeli ten wpis był dla Ciebie wartościowy – będę BARDZO wdzięczny jeśli udostępnisz go/podzielisz się nim ze znajomym.


.

Leave a Comment

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *