Poza udostępnianiem portów kontenery mogą wymieniać między sobą informacje poprzez współdzielenie zasobów swoich systemów plików. W tym wpisie zostanie przedstawiony sposób udostępniania plików pomiędzy kontenerem a system operacyjnym gospodarza oraz pomiędzy kontenerami.
Ten wpis jest częścią serii wpisów o Dockerze. Jeżeli jakieś pojęcie jest używane bez wyjaśnienia to prawdopodobnie zostało wprowadzone w jednym z wcześniejszych wpisów.
* Zachęcamy również do zapoznania się z odświeżonymi w grudniu 2021 i styczniu 2022 artykułami nt. Dockera, które znajdziecie pod tym wpisem.
Współdzielenie kontener – system gospodarza
W niektórych sytuacjach możemy chcieć żeby kontener miał dostęp do plików znajdujących się w systemie gospodarza. Jeżeli w systemie gospodarza posiadamy kod aplikacji internetowej, którą chcemy uruchomić za pomocą serwera HTTP działającego w kontenerze wtedy serwer HTTP powinien mieć dostęp do katalogu projektu. Współdzielenie plików z kontenerem można zrealizować za pomocą opcji -v
(--volume
) w poleceniu docker run
.
docker run -v [zasób systemu plików gospodarza]:[punkt montowania w kontenerze] [nazwa obrazu]
W katalogu domowym stwórzmy katalog docker
zawierający plik index.html
o treści „Hello, world!”.
mkdir ~/docker
echo "Hello, world!" >> index.html
Stwórzmy kontener na podstawie obrazu python:3.5-slim, który:
- Montuje katalog
~/docker
w punkcie/shared_volume
. - Uruchamia serwer HTTP działający na porcie 8000.
- Udostępnia port 8000 w systemie gospodarza.
docker run -d -v ~/docker:/shared_volume -p 8000:8000 python:3.5-slim /bin/bash -c "cd /shared_volume && python -m http.server 8000"
W wyniku wykonania powyższych poleceń po otwarciu adresu http://127.0.0.1:8000/
powinniśmy zobaczyć napis „Hello, world!”. Każda modyfikacja pliku index.html
w systemie gospodarza powinna być widoczna po odświeżeniu przeglądarki.
Współdzielenie kontener – kontener
Podobnie jak w przypadku współdzielenia zasobów dyskowych pomiędzy systemem gospodarza i kontenerem możemy współdzielić zasoby pomiędzy kontenerami. Żeby osiągnąć ten efekt kontener udostępniający zasoby powinien określić je za pomocą opcji -v
, a każdy kontener chcący z nich skorzystać powinien wskazać kontener udostępniający za pomocą opcji --volumes-from
. Kontener udostępniający nie musi być uruchomiony żeby dało się korzystać z wystawionych przez niego zasobów. Jeżeli udostępniany zasób istnieje w systemie plików kontenera, który go montuje wtedy udostępniony zasób przykryje ten istniejący.
docker create -v [zasób systemu plików kontenera] --name [nazwa kontenera z danymi] [nazwa obrazu]
docker run --volumes-from [nazwa kontenera z danymi] [nazwa obrazu]
W powyższym schemacie do stworzenia kontenera z danymi została użyta nieomawiana wcześniej komenda docker create
. W wyniku jej wykonania kontener zostanie tylko stworzony bez uruchamiania jak to miejsce w przypadku komendy docker run
. Alternatywnie możemy użyć komendy docker run
i ustawić jej polecenie na /bin/bash
. Pomiędzy kontenerami nie będzie istotnej różnicy. W pierwszym przypadku kontener będzie miał status „created”, a w drugim „exited”.
Stwórzmy dwa kontenery obrazu postgres
z czego jeden będzie uruchamiał serwer bazy danych, a drugi będzie służył tylko do przechowywania danych. Zacznijmy od kontenera na dane ponieważ jego udostępnione zasoby będą montowane w kontenerze uruchamiającym serwer. Dane bazy postgres są przechowywane w katalogu /var/lib/postgresql/[wersja]/main
, gdzie [wersja]
to np. 9.3
. Lokalizację danych bazy postgres można ustalić wpisując:
SHOW data_directory;
w interaktywnym terminalu psql
.
docker run -v /var/lib/postgresql/9.5/main --name="postgres-data-container" postgres:9.5 /bin/bash
Stwórzmy kontener z serwerem bazy danych, który montuje zasoby udostępnione przez kontener postgres-data-container
. Żeby przetestować poprawność udostępniania katalogów pomiędzy kontenerami będziemy chcieli móc modyfikować stan bazy danych. Z tego powodu dodatkowo udostępniamy port bazy danych w systemie gospodarza.
docker run -d --volumes-from="postgres-data-container" -p 9500:5432 --name="postgres-container" postgres:9.5
Stwórzmy tabelę w bazie danych użytkownika postgres i dodajmy do niej kilka wierszy.
psql -U postgres -d postgres -h localhost -p 9500 -c"CREATE TABLE docker (id serial PRIMARY KEY, name varchar(32) NOT NULL)"
psql -U postgres -d postgres -h localhost -p 9500 -c"INSERT INTO docker VALUES (1, 'row 1'), (2, 'row 2'), (3, 'row 3')"
psql -U postgres -d postgres -h localhost -p 9500 -c"SELECT * FROM docker"
W wyniku powyższych poleceń na ekranie powinniśmy zobaczyć:
id | name
----+-------
1 | row 1
2 | row 2
3 | row 3
(3 rows)
Usuńmy kontener postgres-container
i stwórzmy go ponownie w taki sam sposób jak poprzednio.
docker stop postgres-container
docker rm postgres-container
docker run -d --volumes-from="postgres-data-container" -p 9500:5432 --name="postgres-container" postgres:9.5
Jeżeli po ponownym wykonaniu polecenia:
psql -U postgres -d postgres -h localhost -p 9500 -c"SELECT * FROM docker"
zobaczymy trzy dodane wcześniej wiersze to znaczy, że współdzielenie zasobów systemu plików pomiędzy kontenerami zadziałało prawidłowo.
* Zaktualizowane w 2021 i 2022 artykuły nt. Dockera
- Docker dla programistów: co to jest?
- Docker dla programistów – budowa pierwszego środowiska. Część I
- Docker dla programistów – budowa środowiska rozwojowego. Część II
- Docker dla programistów – dystrybucja aplikacji
Zostaw komentarz