## 🐳 Начало «диеты» образов [[Docker]]: Разбираем родословную с помощью `docker history` {#sec-168deae1dd0f} Бывает, что вы запускаете всего одно легкое приложение, но при проверке обнаруживаете, что размер образа превышает 1 ГБ. Возникает вопрос: «Что я такого добавил?» В такие моменты необходимо разобраться в «родословной» образа. ![Диета слоев Docker](/media/whitedec/blog_img/de42f6f1949c4e91bc6def030f10ea5.webp) ## «Что же ты съел, чтобы так вырасти?» {#sec-5eaafdc2833e} Образ Docker подобен многослойной луковице. Команда `docker history` — это рентген, который позволяет снять каждый слой и найти «виновника» его разрастания. Её базовое использование очень просто: ```bash # Базовое использование docker history [опции] <имя_образа:тег> # Пример: проверка истории моего приложения docker history my-app:latest ``` При выполнении команды отображается полная история образа, начиная с самого нового слоя и до базового образа, в обратном хронологическом порядке. ```text IMAGE CREATED CREATED BY SIZE a6215f271958 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B 7 weeks ago /bin/sh -c #(nop) ADD file:f28242cf608f6... 7.81MB ``` Внимательно посмотрите на столбец **SIZE**. Если там, где должно быть 0B, указаны сотни мегабайт, значит, это ваш кандидат на «диету». С опытом вы быстро научитесь чувствовать, где «пахнет неладным». > \*\*💡 Полезный совет: `--no-trunc`** ` > > По умолчанию вывод команды обрезается, если она слишком длинная. Добавление опции `--no-trunc` позволяет увидеть команду целиком без обрезки, что крайне важно для точного анализа. > > `docker history --no-trunc my-app:latest` *** ## Практический пример: «Виновником оказался `chown`» {#sec-036665971432} Позвольте рассказать реальную историю из моего опыта. Я собирал проект размером 150 МБ, но образ в итоге весил более 300 МБ. Виновником оказались всего две, казалось бы, безобидные строки в Dockerfile. **[Неэффективный метод: создание двух слоев]** ```dockerfile # 1. Сначала копируем файлы (по умолчанию копируются с правами root) COPY . . # 2. Изменяем владельца для безопасности (выполняется отдельной командой) RUN chown -R appuser:appgroup /app ``` После сборки и проверки с помощью `docker history` я получил следующий результат: ```text IMAGE CREATED BY SIZE /bin/sh -c chown -R appuser:appgroup /app 150MB <-- (Проблемное место!) /bin/sh -c #(nop) COPY dir:abc in /app 150MB ``` Здесь проявляется коварство слоев Docker. На первом шаге, когда копируется файл размером 150 МБ, создается один слой. Но когда на втором шаге выполняется `chown`, Docker «говорит»: «Ой, информация о файле (владелец) изменилась? Тогда нужно создать еще один слой с новым состоянием!» — и копирует те же 150 МБ, создавая новый слой поверх существующего. В итоге, одно и то же содержимое, но с разными правами владения, было сохранено дважды, что удвоило размер образа. *** ## Решение: «диета» в одну строку! {#sec-b564ee91d4d9} Решение простое: достаточно указать права владения сразу при копировании, объединив таким образом создание слоев в один. **[Эффективный метод: создание одного слоя]** ```dockerfile # Копирование и одновременное указание прав владения! COPY --chown=appuser:appgroup . . ``` Если изменить Dockerfile таким образом и снова выполнить `docker history`, результат будет впечатляющим. ```text IMAGE CREATED BY SIZE /bin/sh -c #(nop) COPY --chown=appuser... dir:abc 150MB ``` Видите? Создан всего один слой, и размер образа снова стал «стройным» — 150 МБ. Просто объединив две команды в одну, мы сократили размер вдвое. *** ## Вывод: Всегда проверяйте «историю» после сборки! {#sec-74645a10d229} Не забывайте: образ [[Docker]] — это **один слой на каждую команду**. Как вы тестируете код после написания, так и после сборки образа возьмите за привычку запускать `docker history --no-trunc`. Вопросы вроде «Почему этот `apt-get` так много весит?» или «Зачем этот слой был разделен?» будут нанизываться один за другим, и незаметно для себя вы построите очень легкую и эффективную систему. Ведь ненужные слои — враги вашей системы! *** **Было полезно?** Если да, поставьте лайк! Читайте также связанные статьи. **Связанные статьи** [Полное понимание общей памяти Docker (shm_size и ipc)](/ko/whitedec/2025/11/5/docker-shm-size-ipc/) [Docker: Связь между контейнерами через порты хоста без общей сети](/ko/whitedec/2025/11/4/docker-host-port-container-communication/) [Копирование томов Docker (Volume): «Зачем» это нужно?](/ko/whitedec/2025/11/10/docker-volume-copy-reason/)