Compose da o'zgaruvchilar — .env, env_file, secrets

~12 daq · Docker · Docker Compose

Muammodan boshlaylik

compose.yaml Git da. Ichida:

MYSQL_ROOT_PASSWORD: root123
JWT_SECRET: mening-maxfiy-kalitim
PAYME_KEY: live_a8f3c9...

Repozitoriyni ko'rgan har kim — hamkasblar, sobiq xodimlar, (ochiq bo'lsa) butun internet — production parollarini biladi. Va har bir dasturchida va serverda har xil qiymatlar kerak.

Yechim: faylda — o'zgaruvchilar, qiymatlar — alohida, Git dan tashqarida.


.env — avtomatik o'qiladi

Compose compose.yaml yonidagi .env faylni avtomatik o'qiydi:

# .env  (Git ga qo'shilmaydi!)
DB_ROOT_PASSWORD=Kuchli_Root_2026
DB_PASSWORD=Kuchli_App_2026
JWT_SECRET=a8f3c9e1b7d4f5a2c6e8b9d1f3a5c7e9
API_PORT=3000
NODE_ENV=development
# compose.yaml  (Git da)
services:
  api:
    build: .
    ports:
      - "${API_PORT}:3000"
    environment:
      NODE_ENV: ${NODE_ENV}
      DB_PASSWORD: ${DB_PASSWORD}
      JWT_SECRET: ${JWT_SECRET}

  baza:
    image: mysql:8.4
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_PASSWORD: ${DB_PASSWORD}

${O'ZGARUVCHI} — Compose uni .env (yoki terminal muhiti) dagi qiymat bilan almashtiradi.

.gitignore:

.env

Git ga — .env.example:

# .env.example — nusxalab .env deb nomlang va to'ldiring
DB_ROOT_PASSWORD=
DB_PASSWORD=
JWT_SECRET=
API_PORT=3000
NODE_ENV=development

Yangi dasturchi: cp .env.example .env → qiymatlarni to'ldiradi → docker compose up.


Standart qiymatlar va majburiy o'zgaruvchilar

ports:
  - "${API_PORT:-3000}:3000"          # yo'q yoki bo'sh bo'lsa — 3000
image: "mysql:${MYSQL_VERSION:-8.4}"

environment:
  JWT_SECRET: ${JWT_SECRET:?JWT_SECRET .env da berilishi shart}
Sintaksis Ma'nosi
${VAR} Qiymat (yo'q bo'lsa — bo'sh qator va ogohlantirish)
${VAR:-standart} Yo'q yoki bo'sh bo'lsa — standart
${VAR:?xabar} Yo'q yoki bo'sh bo'lsa — xato va xabar, ishga tushmaydi

:? — production uchun: muhim kalit unutilsa, ilova "bo'sh parol" bilan jimgina ishga tushmaydi.

Tekshirish:

docker compose config         # almashtirilgan yakuniy fayl

Ikki xil "env" — farqni tushuning

Bu eng ko'p chalkashtiriladigan joy:

1. .env — compose.yaml uchun (interpolatsiya): ${VAR} larni almashtiradi. Konteynerga o'z-o'zidan tushmaydi.

2. env_file: — konteyner uchun: fayldagi barcha o'zgaruvchilar konteynerga uzatiladi.

services:
  api:
    env_file:
      - ./api.env             # hammasi konteyner ichida process.env da
    environment:
      NODE_ENV: production    # environment — env_file dan ustun
# api.env
DB_HOST=baza
DB_PASSWORD=...
REDIS_URL=redis://kesh:6379
.env (loyiha ildizida) env_file:
Kim o'qiydi Compose — faylni tahlil qilishda Konteyner — ishga tushganda
Nima uchun ${VAR} larni almashtirish Ko'p o'zgaruvchini konteynerga uzatish
Konteynerga tushadimi Yo'q (agar environment da ishlatilmasa) Ha, hammasi

Ko'p ilova o'zgaruvchilari bo'lsa — env_file qulay; aniq nazorat kerak bo'lsa — environment + ${...}.


Ustuvorlik

Bitta o'zgaruvchi bir nechta joyda bo'lsa:

1. docker compose run -e VAR=...        ← eng yuqori
2. Terminal muhiti (export VAR=...) — ${VAR} interpolatsiyasi uchun
3. environment: (compose.yaml)
4. env_file:
5. Dockerfile dagi ENV                   ← eng past

Turli muhitlar uchun boshqa .env:

docker compose --env-file .env.production up -d

secrets — fayl sifatida

Muhit o'zgaruvchilari docker inspect da ko'rinadi (10-dars). Maxfiyroq yo'l — fayl sifatida ulash:

services:
  baza:
    image: mysql:8.4
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
    secrets:
      - db_root_password

  api:
    build: .
    secrets:
      - db_password

secrets:
  db_root_password:
    file: ./secrets/db_root_password.txt
  db_password:
    file: ./secrets/db_password.txt
  • Har bir secret — konteynerda /run/secrets/nomi fayli
  • docker inspect da qiymat ko'rinmaydi
  • Ko'p rasmiy image lar _FILE qo'shimchali o'zgaruvchilarni qo'llab-quvvatlaydi: MYSQL_ROOT_PASSWORD_FILE, POSTGRES_PASSWORD_FILE
  • O'z ilovangizda — faylni o'qing:
import { readFileSync } from 'node:fs';
const dbParol = readFileSync('/run/secrets/db_password', 'utf8').trim();

secrets/ papkasi — .gitignore da.


Nima uchun shunday?

Nima uchun Compose ikki xil "env" mexanizmiga ega — bitta bo'lsa soddaroq emasmi?

Ular turli qatlamlar uchun. .env — infratuzilma sozlamalari: qaysi portni ochish, qaysi image versiyasi, qaysi muhit. Bular compose.yaml ning o'ziga ta'sir qiladi va ilovaga umuman kerak emas. env_file / environment — ilova sozlamalari: baza manzili, API kalitlar. Agar .env dagi hamma narsa avtomatik konteynerga tushsa — ilova o'ziga keraksiz (va ba'zan maxfiy) infratuzilma qiymatlarini ham olardi. Ajratish — har bir qism faqat o'ziga kerakli narsani ko'radi.


Xulosa

Eslab qoling:

  • .env — compose.yaml yonida, avtomatik; Git ga emas; .env.example — Git ga
  • ${VAR}, ${VAR:-standart}, ${VAR:?xato} — majburiy kalitlar uchun :?
  • .env — faylni to'ldirish uchun; env_file: — konteynerga uzatish uchun
  • environment > env_file > Dockerfile ENV
  • --env-file .env.production — boshqa muhit
  • secrets — fayl sifatida, inspect da ko'rinmaydi; *_FILE o'zgaruvchilar
  • docker compose config — natijani tekshirish

Keyingi dars

30-dars: Ishlab chiqish uchun Compose — hot reload, watch