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ą.

  1. 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ład
    docker compose run -e DEBUG web python console.py
    wtedy wartość dla zmiennej DEBUG jest pobierana ze zmiennych Shella

  2. 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. 

  1. 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.

  1. 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ść.

  1. Pobierana z pliku po ustawieniu atrybutu env_file w pliku compose.yml
web:
   env_file:
      - plikZeZmiennymi.env
  1. 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}"
  1. 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.

Tags: