Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке .dockerignore і навіщо він потрібен?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`.dockerignore`** це gitignore-стилевий файл, що каже Docker, які файли виключити з build context. Без нього кожен файл у build-директорії (включно з `node_modules`, `.git`, secret) шиппиться на daemon і може опинитися у твоєму image. ``` # .dockerignore — типовий вміст node_modules .git dist *.log .env* Dockerfile* README.md .vscode coverage ``` **Головне:** менший build context = швидші білди, менші image, менше secret витікає. Перший файл, який варто додати у проект з Dockerfile.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`.dockerignore`** це найпростіший Docker-файл, який ти колись напишеш. Він також один з найвпливовіших: контролює, що шиппиться на daemon під час `docker build` і запобігає трьом класам багів (повільні білди, роздуті image, витоки secret). ## Теорія ### TL;DR - **Build context** = директорія, що передаєш у `docker build`. Усе в ній заливається на daemon перед стартом білду. - Без `.dockerignore` УСЯ директорія шиппиться: `node_modules`, `.git`, build-output, IDE-config, secret, усе. - Синтаксис `.dockerignore` як у gitignore з одним винятком: лише один `**` glob-патерн, без negation у деяких Docker-версіях. - Має бути у **корені build context** (поряд з `Dockerfile`). - **Три причини, чому важить:** швидкість білду, розмір image, безпека. ### Швидкий приклад ``` # .dockerignore node_modules .git dist build *.log *.tmp .env* .DS_Store Dockerfile* .dockerignore README.md .vscode .idea coverage tests *.test.js *.spec.ts ``` З цим `docker build .` шле лише реальні source-файли. Без цього типовий Node-проект шле 200+ MB `node_modules` і `.git`-папку повну історії, що не треба в image. ### Синтаксис патернів ``` # Коментар *.log # будь-який .log на будь-якій глибині logs/ # директорія logs і усе всередині !important.log # негація: включити, навіть якщо вище матчить **/temp # будь-яка 'temp'-директорія на будь-якій глибині src/**/*.test.js # test-файли будь-де під src/ ``` **Важливо:** порядок важить. Пізніші правила перекривають раніші. Бери `!` для винятків. ### Чому кожен рядок важить #### `node_modules` (і еквіваленти) Найбільший контрибутор. Часто сотні MB. Dockerfile все одно перевстановлює через `npm ci`. ``` node_modules vendor # PHP / Go / Ruby vendored deps .venv # Python virtualenv __pycache__ # Python bytecode cache *.pyc ``` #### `.git` Повна git-історія. Часто 50-500 MB на довго-живучих репо. Майже ніколи не потрібно у image. Виняток: якщо білд потребує git-info (commit SHA через `git rev-parse`), бери `git rev-parse HEAD > VERSION` ПЕРЕД білдом, тоді виключай `.git` і `COPY VERSION` лише. #### Build-output ``` dist build out target # Rust / Java ``` Ти перебудовуєш їх всередині image. Жодних причин шиппити host-output. #### Secret і локальні config ``` .env* *.pem *.key secrets.yaml config.local.json ``` `.env`, що випадково COPY'ється у image, це витоковий прод-secret. #### IDE / редактори / OS-сміття ``` .vscode .idea .DS_Store # macOS Thumbs.db # Windows *.swp # vim ``` #### Тести і dev-артефакти (іноді) ``` coverage tests # якщо не крутиш тести всередині image *.test.js ``` Залежить від твого build-flow. Якщо `RUN npm test` всередині білду (multi-stage), залиш тести. Інакше скіпай. ### Типові помилки **Без `.dockerignore` взагалі** ``` $ docker build -t myapp . [+] Building 0.0s => transferring context: 248.7MB ← занадто велико ``` 248 MB upload на daemon кожен білд. Додай `.dockerignore` і дивися, як це впаде до кількох MB. **Забути, що `COPY . .` копіює усе у context** ```dockerfile COPY . . # копіює усе, включно з .env, якщо не у .dockerignore ``` Якщо `.env` існує у build context І не у `.dockerignore`, він приземляється у image. Аудитори обожнюють їх знаходити. **Класти `.dockerignore` у піддиректорію** Docker читає `.dockerignore` лише з **кореня build context**. Build context це те, що передаєш у `docker build` (зазвичай `.` = поточна директорія). `.dockerignore` у `./api/.dockerignore` ігнорується, поки не білдиш через `docker build ./api`. **Negate-патерни і дивуватися** ``` * !Dockerfile !src/** ``` Цей allow-listy патерн крихкий і order-dependent. Простіше брати deny-list правила (`node_modules`, `.git`, `dist`). **Забути, що файл впливає і на multi-stage білди** Build context визначається раз для `docker build`, незалежно від того, скільки стейджів у Dockerfile. Кожен стейдж бачить той самий filtered context. ### Inspecting що у build context ```bash # Подивитися, що буде заливатися docker build --no-cache --progress=plain -t test . 2>&1 | head -10 # Шукай рядок "transferring context" # Або dry-run з ручним tar tar --exclude-from=.dockerignore -cf - . | wc -c ``` Якщо колись думав «чому мій build context 1 GB?», `du -sh */ .[^.]*/ 2>/dev/null | sort -h` з кореня білду каже, що найбільше. ### Реальне застосування - **Кожен прод-проект:** має `.dockerignore`. Дефолтний starter для будь-якого нового репо це додати його перед Dockerfile. - **Monorepos:** ще важливіше, директорії `node_modules` per package можуть давати гігабайти. - **CI білди:** великий build context, помножений на кожен CI-прогон, це реальні disk- і time-витрати. - **Cloud builds (Cloud Build, GitHub Actions):** шиппять context у remote-сервіс. Менший = швидше (і дешевше). ### Питання для поглиблення **Q:** Що відбувається, якщо я `COPY` файл, виключений `.dockerignore`? **A:** Docker падає з «file not found», з точки зору Docker файл не у context. **Q:** Чим `.dockerignore` відрізняється від `.gitignore`? **A:** Той самий синтаксис (переважно). `.gitignore` контролює, що git відстежує. `.dockerignore` контролює, що `docker build` шле на daemon. Незалежні файли, часто перетинаються, але не ідентичні (наприклад, сам `.git` не ігнорує `.gitignore`, але має ігнорувати `.dockerignore`). **Q:** Чи `.dockerignore` впливає на `docker run -v` mount? **A:** Ні. `.dockerignore` build-time only. Bind mount при run-time монтує те, на що показуєш, незалежно від `.dockerignore`. **Q:** Чи може `.dockerignore` бути в іншому місці? **A:** Так, з BuildKit можна використати `# syntax=docker/dockerfile:1.7` і файл `<Dockerfile>.dockerignore`. Корисно, коли одне репо має кілька Dockerfile з різними ignore-потребами. Дефолт це все ще `.dockerignore` у корені build context. **Q:** (Senior) Чому строго залочений `.dockerignore` може сповільнити dev-workflow? **A:** Якщо виключає речі, що Dockerfile очікує знайти (test-фікстури, dev-config), `COPY` падає, або image поводиться неправильно. Поширений підступ: виключати `.git`, поки build-крок потребує `git log` для версії. Рішення: попередньо розрахувати значення (`git rev-parse HEAD > VERSION` перед білдом), передати через `--build-arg`, або per-Dockerfile `.dockerignore` варіант для dev vs прод. ## Приклади ### Типовий `.dockerignore` Node-проекту ``` # Залежності (перебудовуються всередині image) node_modules bower_components # Build-output (перебудовуються всередині image) dist build out # Логи і temp *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Environment / secret .env .env.* !.env.example # лишити приклад для документації # Редактори .vscode .idea *.swp .DS_Store # Тести / coverage coverage *.test.js *.spec.ts # Docker Dockerfile* .dockerignore compose*.yaml # VCS .git .gitignore .gitattributes ``` Результат: `docker build` context, що містить рівно потрібні source-файли. Build-час падає драматично; image менший; secret не витікає. ### Замір до і після ```bash # До .dockerignore $ time docker build -t myapp . [+] Building ... transferring context: 312.4MB real 1m45s # Додати .dockerignore з node_modules і .git $ time docker build -t myapp . [+] Building ... transferring context: 4.2MB real 0m22s ``` Два рядки у `.dockerignore`, 5x швидший білд. Цифри множаться між CI-прогонами. ### Multi-Dockerfile проект (BuildKit) ``` repo/ ├── api/ │ ├── Dockerfile │ └── Dockerfile.dockerignore # специфічно для api ├── web/ │ ├── Dockerfile │ └── Dockerfile.dockerignore # специфічно для web └── .dockerignore # shared baseline ``` З `# syntax=docker/dockerfile:1.7` BuildKit авто-завантажує `<Dockerfile>.dockerignore`, якщо є, інакше root `.dockerignore`. Корисно, коли api і web мають різні exclusion-потреби.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.