Co kilka lat w branży rozwoju oprogramowania następuje zmiana paradygmatu. Jednym z takich zjawisk jest wzrost zainteresowania koncepcją mikrousług. Choć mikrousługi to technologia niezbyt nowa, jej popularność w ostatnim czasie dosłownie wzrosła w niesamowitym tempie.
Duże monolityczne usługi są obecnie zastępowane niezależnymi, autonomicznymi mikrousługami. Mikrousługę można rozpatrywać jako aplikację, która służy jednemu, bardzo specyficznemu celowi. Na przykład, może to być relacyjna baza danych, aplikacja Express lub usługa Solr.
W dzisiejszych czasach trudno wyobrazić sobie rozwój nowego systemu oprogramowania bez zastosowania mikrousług. Ta sytuacja prowadzi nas bezpośrednio do platformy Docker.
Docker
Platforma , w zakresie opracowywania i wdrażania mikrousług, stała się praktycznie standardem przemysłowym. Na stronie projektu można przeczytać, że Docker to jedyna niezależna platforma konteneryzacji, która pozwala organizacjom bez żadnych przeszkód tworzyć dowolne aplikacje oraz je rozprowadzać i uruchamiać w różnych środowiskach — od chmur hybrydowych po systemy brzegowe.
Docker Compose
Technologia służy do konfigurowania aplikacji wielokontenerowych. W projekcie Docker Compose może być tyle kontenerów Docker, ile potrzebuje twórca danego projektu.
Pracując z Docker Compose, do konfiguracji usług aplikacji i organizacji ich wzajemnej interakcji używa się pliku YAML. Docker Compose jest zatem narzędziem do opisywania i uruchamiania wielokontenerowych aplikacji Docker.

Dwa kontenery działające na systemie gospodarza
GNU Make
Program make, w zasadzie, jest narzędziem do automatyzacji budowy programów i bibliotek z kodu źródłowego. Ogólnie rzecz biorąc, można powiedzieć, że make jest stosowane do każdego procesu, który obejmuje wykonywanie dowolnych poleceń w celu przekształcenia pewnych surowych materiałów w pewien rezultatywny kształt, w jakimś celu. W naszym przypadku polecenia docker-compose będą przekształcane w cele abstrakcyjne ().
Aby poinformować program make o tym, czego od niego oczekujemy, będziemy potrzebować pliku Makefile.
W naszym Makefile który będzie zawierał standardowe polecenia docker i docker-compose, które służą do rozwiązywania wielu zadań. Mianowicie chodzi o budowanie kontenera, uruchamianie go, zatrzymywanie, ponowne uruchamianie, organizowanie logowania użytkownika do kontenera, pracę z logami kontenera oraz rozwiązanie innych podobnych zadań.
Typowe zastosowania Docker Compose
Wyobraźmy sobie zwykłą aplikację webową, która posiada następujące komponenty:
- Baza danych TimescaleDB (Postgres).
- Aplikacja Express.js.
- Ping (po prostu kontener, który nic specjalnego nie robi).
Ta aplikacja będzie potrzebować 3 kontenerów Docker oraz pliku docker-compose, zawierającego instrukcje dotyczące zarządzania tymi kontenerami. Każdy z kontenerów będzie miał różne punkty interakcji. Na przykład, z kontenerem timescale można będzie pracować tak, jak pracuje się z bazami danych. Mianowicie pozwala on na wykonywanie następujących działań:
- Logowanie do powłoki Postgres.
- Import i eksport tabel.
- Tworzenie
pg_dumptabel lub baz danych.
Kontener aplikacji Express.js, expressjs, może mieć następujące możliwości:
- Dostęp do świeżych danych z dziennika systemowego.
- Logowanie do powłoki w celu wykonania pewnych poleceń.
Interakcja z kontenerami
Po skonfigurowaniu połączenia między kontenerami z użyciem Docker Compose, nadszedł czas na nawiązanie interakcji z tymi kontenerami. W ramach systemu Docker Compose dostępna jest komenda docker-compose, która obsługuje opcję -f, umożliwiającą przekazywanie systemowi pliku docker-compose.yml.
Korzystając z możliwości tej opcji, można ograniczyć interakcję z systemem wyłącznie do tych kontenerów, które są wymienione w pliku docker-compose.yml.
Zobaczmy, jak wyglądają interakcje z kontenerami przy użyciu komend docker-compose. Jeśli wyobrazimy sobie, że musimy wejść do powłoki psql, to odpowiednie komendy mogą wyglądać następująco:
docker-compose -f docker-compose.yml exec timescale psql -Upostgres Ta sama komenda, dla której używana jest inna docker-compose, a docker, może wyglądać tak:
docker exec -it edp_timescale_1 psql -Upostgres Zauważ, że w takich przypadkach zawsze lepiej jest używać komendy docker, a nie komendy docker-compose, ponieważ pozwala to uniknąć konieczności zapamiętywania nazw kontenerów.
Obie powyższe komendy nie są zbyt skomplikowane. Ale gdybyśmy skorzystali z "owijki" w postaci Makefile, który dałby nam interfejs w postaci prostych poleceń i sam wywoływałby podobne długie polecenia, to te same wyniki można by osiągnąć w ten sposób:
make db-shell Jest zupełnie oczywiste, że użycie Makefile znacząco upraszcza pracę z kontenerami!
Przykład roboczy
Na podstawie wcześniej omawianego schematu projektu stwórzmy następujący plik docker-compose.yml:
version: '3.3'
services:
api:
build: .
image: mywebimage:0.0.1
ports:
- 8080:8080
volumes:
- /app/node_modules/
depends_on:
- timescale
command: npm run dev
networks:
- webappnetwork
timescale:
image: timescale/timescaledb-postgis:latest-pg11
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
command: ["postgres", "-c", "log_statement=all", "-c", "log_destination=stderr"]
volumes:
- ./create_schema.sql:/docker-entrypoint-initdb.d/create_schema.sql
networks:
- webappnetwork
ping:
image: willfarrell/ping
environment:
HOSTNAME: "localhost"
TIMEOUT: 300
networks:
webappnetwork:
driver: bridge Aby zarządzać konfiguracją Docker Compose i wchodzić w interakcje z kontenerami, które ona opisuje, stwórzmy następujący plik Makefile:
THIS_FILE := $(lastword $(MAKEFILE_LIST))
.PHONY: help build up start down destroy stop restart logs logs-api ps login-timescale login-api db-shell
help:
make -pRrq -f $(THIS_FILE) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'
build:
docker-compose -f docker-compose.yml build $(c)
up:
docker-compose -f docker-compose.yml up -d $(c)
start:
docker-compose -f docker-compose.yml start $(c)
down:
docker-compose -f docker-compose.yml down $(c)
destroy:
docker-compose -f docker-compose.yml down -v $(c)
stop:
docker-compose -f docker-compose.yml stop $(c)
restart:
docker-compose -f docker-compose.yml stop $(c)
docker-compose -f docker-compose.yml up -d $(c)
logs:
docker-compose -f docker-compose.yml logs --tail=100 -f $(c)
logs-api:
docker-compose -f docker-compose.yml logs --tail=100 -f api
ps:
docker-compose -f docker-compose.yml ps
login-timescale:
docker-compose -f docker-compose.yml exec timescale /bin/bash
login-api:
docker-compose -f docker-compose.yml exec api /bin/bash
db-shell:
docker-compose -f docker-compose.yml exec timescale psql -Upostgres Większość opisanych tutaj poleceń dotyczy wszystkich kontenerów, ale użycie opcji c= umożliwia ograniczenie zakresu działań polecenia do jednego kontenera.
Po tym, jak Makefile jest gotowy, można go używać w ten sposób:
make help— wydanie listy wszystkich poleceń dostępnych dlamake.

Pomoc dotycząca dostępnych poleceń
make build— budowanie obrazu zDockerfile. W naszym przykładzie użyliśmy istniejących obrazówtimescaleiping. Ale obrazapichcemy zbudować lokalnie. To właśnie zostanie zrobione po wykonaniu tej komendy.

Budowanie kontenera Docker
make start— uruchomienie wszystkich kontenerów. Aby uruchomić tylko jeden kontener, można użyć polecenia w formaciemake start c=timescale.

Uruchomienie kontenera timescale

Uruchomienie kontenera ping
make login-timescale— wejście do sesji bash konteneratimescale.

Uruchomienie bash w kontenerze timescale
make db-shell— wejście dopsqlw kontenerzetimescaleaby wykonać zapytania SQL do bazy danych.

Uruchomienie psql w kontenerze timescaledb
make stop— zatrzymanie kontenerów.
![]()
Zatrzymanie kontenera timescale
make down— zatrzymanie i usunięcie kontenerów. Aby usunąć konkretny kontener, można użyć tej komendy ze wskazaniem wymaganego kontenera. Na przykład —make down c=timescalelubmake down c=api.

Zatrzymanie i usunięcie wszystkich kontenerów
Podsumowanie
Mimo że system Docker Compose oferuje rozbudowany zestaw poleceń do zarządzania kontenerami, czasami polecenia te stają się długie i trudne do zapamiętania.
Metodyka użycia Makefile pomogła nam nawiązać szybki i prosty kontakt z kontenerami z pliku docker-compose.yml. A konkretnie mowa o tym:
- Programista współdziała tylko z kontenerami projektu, opisanymi w
docker-compose.yml, które nie przeszkadzają w pracy innych uruchomionych kontenerów. - W przypadku, gdy jakieś polecenie zostało zapomniane, można wykonać polecenie
make helpi uzyskać pomoc na temat dostępnych poleceń. - Nie trzeba zapamiętywać długich list argumentów do wykonywania takich działań, jak uzyskiwanie świeżych zapisów dziennika czy logowanie się. Na przykład, polecenie w formacie
docker-compose -f docker-compose.yml exec timescale psql -Upostgresprzechodzi wmake db-shell. - Plik
Makefilemożna w miarę rozwoju projektu elastycznie dostosowywać do niego. Na przykład, można łatwo dodać polecenie do tworzenia kopii zapasowej bazy danych lub do wykonania jakiejkolwiek innej akcji. - Jeśli duża grupa programistów korzysta z tego samego
Makefile, porządkuje to współpracę i zmniejsza liczbę błędów.
P.S. W naszym jest dostępny obraz , który można zainstalować jednym kliknięciem. Możesz sprawdzić działanie kontenerów na . Wszystkim nowym klientom przysługuje 3 dni darmowego testowania.
Drodzy Czytelnicy! Jak automatyzujesz pracę z Docker Compose?
Źródło: habr.com
