Zmienne środowiskowe i plik .env


1. Wprowadzenie

W nowoczesnych aplikacjach kontenerowych niezwykle ważne jest oddzielenie konfiguracji od kodu źródłowego. Dzięki temu:

  • ten sam obraz Dockera może być używany w różnych środowiskach (dev, test, production),
  • dane wrażliwe (np. hasła, klucze API) nie są przechowywane w repozytorium kodu,
  • łatwiej jest zarządzać konfiguracją i wdrażać aplikację w sposób bezpieczny oraz powtarzalny.

Docker i Docker Compose oferują prosty mechanizm do pracy z zmiennymi środowiskowymi (environment variables) i plikami .env, które pełnią rolę centralnego miejsca przechowywania konfiguracji aplikacji.


2. Czym są zmienne środowiskowe

Zmienne środowiskowe (ang. environment variables) to wartości konfiguracyjne przekazywane do aplikacji w czasie uruchomienia kontenera. Zazwyczaj definiują one m.in.:

  • dane dostępowe do bazy danych (host, użytkownik, hasło),
  • klucze API,
  • adresy serwerów zewnętrznych,
  • porty aplikacji czy tryb uruchomienia (np. DEBUG=True).

W kontenerach Dockera można je przekazać na kilka sposobów:

  • Bezpośrednio w poleceniu docker run:
  • W pliku docker-compose.yml (sekcja environment):
  • W osobnym pliku .env, który Compose automatycznie odczytuje.

3. Przechowywanie sekretów i konfiguracji poza kodem

Przechowywanie poufnych danych w plikach źródłowych jest niebezpieczne — może prowadzić do przypadkowego wycieku haseł lub kluczy API (np. przy publikacji repozytorium na GitHubie). Dlatego najlepszą praktyką jest:

  • Nie umieszczać sekretów w plikach Dockerfile ani docker-compose.yml.
  • Przechowywać je w pliku .env, który nie jest wersjonowany (dodany do .gitignore).

Przykład pliku .env:

Taki plik może być potem użyty przez Docker Compose bez konieczności wpisywania tych wartości do pliku YAML.


4. Użycie pliku .env w Docker Compose

Docker Compose automatycznie wykrywa plik .env znajdujący się w tym samym katalogu co docker-compose.yml i wczytuje jego zawartość. W pliku Compose możemy następnie odwoływać się do tych zmiennych, korzystając z notacji ${NAZWA_ZMIENNEJ}.

Przykład:

Plik .env:

Plik docker-compose.yml:

W tym przykładzie Compose automatycznie zastąpi wszystkie wystąpienia ${POSTGRES_USER}, ${POSTGRES_PASSWORD} itd. wartościami z pliku .env.


5. Oddzielanie środowisk: dev / prod

W projektach rzeczywistych bardzo często istnieje potrzeba posiadania różnych konfiguracji dla środowisk:

  • dev (development) – dla programistów, z logami, trybem debugowania i lokalną bazą danych,
  • prod (production) – dla środowiska produkcyjnego, z optymalizacjami, innym portem, bez debugowania.

5.1 Podejście 1 – Różne pliki .env

Możemy stworzyć osobne pliki .env.dev i .env.prod, np.:

.env.dev

.env.prod

A następnie uruchamiać środowisko z odpowiednim plikiem:

lub

W ten sposób możesz kontrolować różne konfiguracje przy użyciu tego samego pliku Compose.


5.2 Podejście 2 – Różne pliki Compose

Innym rozwiązaniem jest posiadanie osobnych plików Compose:

  • docker-compose.yml – podstawowa konfiguracja wspólna dla wszystkich środowisk,
  • docker-compose.dev.yml – dodatkowe ustawienia dla środowiska developerskiego (np. mount kodu lokalnego),
  • docker-compose.prod.yml – optymalizacje produkcyjne (np. bez mapowania katalogów).

Uruchamianie:

lub

To rozwiązanie daje większą elastyczność, gdy środowiska różnią się znacznie konfiguracją.


6. Najczęstsze zastosowania zmiennych środowiskowych

Zmienna Opis Przykład
POSTGRES_USER Użytkownik bazy danych postgres
POSTGRES_PASSWORD Hasło do bazy haslo123
POSTGRES_DB Nazwa bazy danych mydb
FLASK_ENV Tryb aplikacji Flask development / production
NODE_ENV Tryb aplikacji Node.js production
API_URL Adres API backendu http://backend:5000
PORT Port aplikacji 8080

Warto także przekazywać zmienne z .env do kontenerów frontendu (np. Angulara) przy budowie, aby aplikacja mogła komunikować się z odpowiednim backendem w zależności od środowiska.


7. Dobre praktyki dotyczące pracy z plikiem .env

  • Dodaj plik .env do .gitignore, aby nie został przypadkowo opublikowany w repozytorium.
  • Utwórz plik .env.example, który zawiera tylko nazwy zmiennych bez wartości:

Taki plik można bezpiecznie przechowywać w repozytorium, aby nowi członkowie zespołu wiedzieli, jakie zmienne należy ustawić.

  • Stosuj prefiksy dla zmiennych, np. DB_, API_, APP_, aby zachować porządek.
  • Używaj wielkich liter i nie stosuj spacji (standardowa konwencja UNIX).
  • Nie mieszaj konfiguracji dla różnych środowisk w jednym pliku .env.
  • Używaj managerów sekretów (np. HashiCorp Vault, AWS Secrets Manager, Docker Secrets) dla środowisk produkcyjnych.

8. Przykładowa struktura projektu z .env

projekt/
├── backend/
│   ├── app.py
│   ├── Dockerfile
│   └── requirements.txt
├── frontend/
│   ├── Dockerfile
│   └── package.json
├── docker-compose.yml
├── .env
├── .env.dev
├── .env.prod
└── .gitignore

.gitignore:


9. Sprawdzenie wczytanych zmiennych

Aby zobaczyć, jakie zmienne środowiskowe zostały zastosowane w kontenerze:

Możesz też użyć:

To polecenie pokaże pełną konfigurację Compose po zastąpieniu zmiennych ich wartościami z .env.


10. Podsumowanie

W tej lekcji poznałeś kluczowy element zarządzania konfiguracją w Dockerze i Docker Compose — zmienne środowiskowe oraz pliki .env.

Nauczyłeś się:

  • jak oddzielać konfigurację od kodu,
  • jak bezpiecznie przechowywać hasła i klucze,
  • jak używać pliku .env w Compose,
  • jak tworzyć osobne konfiguracje dla środowisk dev i prod.

Dzięki temu Twoje aplikacje stają się:

  • bezpieczniejsze – sekrety nie trafiają do repozytorium,
  • bardziej elastyczne – łatwo zmienić konfigurację bez modyfikacji kodu,
  • łatwiejsze w utrzymaniu – to samo środowisko może działać na wielu maszynach z różnymi ustawieniami.

Docker + pliki .env to potężne narzędzie, które pozwala utrzymać porządek, bezpieczeństwo i skalowalność w każdym projekcie kontenerowym.