Zmienne w Docker Compose
Jednym parametrów, których może dodatkowo potrzebować kontener do uruchomienia, jest tak zwana zmienna środowiskowa. Jest to wartość która musi podać użytkownik, aby zdefiniować różne wartości konfiguracji, co daje dodatkową elastyczność i porządek w projekcie zbudowanym z kontenerów.

Zmienna środowiskowa w poleceniu docker run
podawana jest jako wartość do parametru --env
, -e
, lub odczytywana z pliku po przez --env-file
. W Docker Compose jest podobnie, możemy wskazać zmienną jawnie wewnątrz pliku docker-compose.yaml w sekcji gdzie określamy parametry kontenera/serwisu lub też możemy ją zdefiniować w zewnętrznym pliku o domyślnej nazwie .env
.
Jednak należy wiedzieć że cześć przekazywanych zmiennych działa tylko w obrębie plików projektu Docker Compose a inne zmienne przekazywane są do wewnątrz kontenera.
Zmienne dla jednego projektu możemy zdefiniować w wielu miejscach. Warto tu zwrócić uwagę, która wartość zmiennej jest ważniejsza, jaka hierarchia występuję dla zmiennych środowiskowych.
Poniżej mamy listę miejsc, gdzie możemy zadeklarować zmienne dla danego projektu Docker Compose. Te z najwyższym priorytetem są na początku listy, a z najniższym na końcu. Tak więc, jeśli ustawimy tą sama zmienna w kilku miejscach to wyższy priorytet zadecyduje, która zmienna zostanie użyta.
A przy okazji, dodatkowo zobrazuje nam to, w jak wielu miejscach można zadeklarować zmienną środowiskową.
- Zmienna ustawiana w poleceniu docker compose run –env lub -e (działa do wewnątrz kontenera)
docker compose run -e DEBUG=0 web python console.py
Można też nie przekazywać wartości zmiennej DEBUG. Na przykładdocker compose run -e DEBUG web python console.py
wtedy wartość dla zmiennej DEBUG jest pobierana ze zmiennych Shella - Zmienna pobrana ze zmiennych Shella. (działa w obrębie plików projektu)
Tu mamy zakładamy, że mamy ustawioną zmienną w naszym Shellu MARIADB_VERSION=10.11.3
db: image: "mariadb:${MARIADB_VERSION}"
Miej na uwadze, że jeśli nie istnieje w tej zmiennej żadna wartość to docker compose wywali się błędem. Dlatego zawsze uczulam by sprawdzić dokładnie czy mamy poprawnie ustawioną wartość w zmiennych powłoki.
- Ustawiona jako parametr
environment
w pliku docker-compose.yml (działa do wewnątrz kontenera)
services: db: image: mariadb restart: always environment: MARIADB_ROOT_PASSWORD: tajnehaslodobazy
To prosty i czytelny sposób. Sprawdza się szczególnie tam gdzie kontener wymaga podania zmiennych do działania. Na przykład kontener z bazą danych będzie wymagał podania/ustawienia hasła.
- Zmienna pobrana z pliku po ustawieniu parametru w poleceniu CLI
--env-file
lub--file
(zmienne używane w obrębie pliku docker compose ale wartości ich mogą być przekazywane do kontenera)
Ten sposób możemy ustawić różne zmienne dla konkretnego środowiska i odpalać wszystko na bazie jednego pliku pliku compose.yaml
Na przykład:
docker compose --env-file ./conf/.env.dev up
docker compose --env-file ./conf/.env.stage up
docker compose --env-file ./conf/.env.prod up
W każdym plików mamy te same zamienne ale z rożnymi wartościami, odpowiednimi dla danego środowiska.
Warto tu posiadać dodatkowo sam plik .env z domyślnymi wartościami, ponieważ jeśli nie ma jakiejś wartości w pliku .env.xxx to pobierana jest z pliku .env.
Natomiast, jeśli wartość występuje w i w pliku .env.xxx i w pliku .env to wtedy ta z pliku env.xxx jest ważniejsza, nadpisuje wartość występującą w .env. Daje to dodatkową elastyczność.
- Pobierana z pliku po ustawieniu atrybutu
env_file
w pliku compose.yml
web: env_file: - plikZeZmiennymi.env
- Zmienna ustawiona w pliku .env znajdującym się w katalogu projektu (ten sposób polecam)
Zawartość pliku .env
TAG=v1.0
Zawartość pliku docker-compose.yml
services: web: image: "webapp:${TAG}"
- Ustawiona w obrazie za pomocą parametu ENV lub ARG
Podsumowując powyższe przykłady, jeśli ustawimy tą samą zmienną w dwóch miejscach, na przykład w oddzielnym pliku .env znajdującym się w katalogu projektu (6) a także jako atrybut environment (3) w pliku compose.yml to wartość zmiennej która zostanie użyta pochodzić będzie właśnie z atrybutu (bo ma wyższy priorytet – 3).
Mając widzę jak wygląda priorytet zmiennych to w ten sposób możemy świadomie nadpisywać zmienne.
Dobrym sposobem aby zweryfikować czy poprawnie ustawiliśmy zmienne dla projektu compose.yaml jest wydanie polecenia docker compose config w katalogu projektu. Zobaczmy wtedy konfiguracje z podstawionymi zmiennymi przez Dockera, dzięki czemu będziemy wiedzieć co mamy nawet przed uruchomieniem pliku (docker compose up)
Choć wiem, że wygodnie jest przechowywać hasła w zmiennych to na pewno nie jest to bezpieczny sposób. Może nie ma to aż takiego znaczenia na środowisku typu develop czy stage. To warto od razu stosować docelowe, bezpieczniejsze rozwiązanie poniewaz czesto sposób jakim obsługiwaliśmy hasła na stage’u przechodzi na proda i wychodzą potem proste hasła mamy w plain tekście na prodzie. Sam widziałem takie kwiatki. Do przechowywania haseł służy moduł secret do Dockerze.