Запросить демо
Я подтверждаю свое согласие на обработку компанией КРОК моих персональных данных, указанных в форме, в целях и пределах, установленных законодательством РФ о персональных данных в рамках проводимых мероприятий в течение неопределенного срока
Дополнительные услуги
Оставить заявку
Я подтверждаю свое согласие на обработку компанией КРОК моих персональных данных, указанных в форме, в целях и пределах, установленных законодательством РФ о персональных данных в рамках проводимых мероприятий в течение неопределенного срока
Узнать стоимость
Я подтверждаю свое согласие на обработку компанией КРОК моих персональных данных, указанных в форме, в целях и пределах, установленных законодательством РФ о персональных данных в рамках проводимых мероприятий в течение неопределенного срока
Дополнительные услуги
Попробовать бесплатно
Я подтверждаю свое согласие на обработку компанией КРОК моих персональных данных, указанных в форме, в целях и пределах, установленных законодательством РФ о персональных данных в рамках проводимых мероприятий в течение неопределенного срока
Дополнительные услуги
Быть в теме

6 советов по уменьшению Docker образа

29.01.2019 14 минут 64

Не секрет, что для того, чтобы получить максимальные преимущества и отдачу от использования контейнеров, необходимо, чтобы ваши Docker образы были минимального размера. В этой статье я расскажу о 6 простых шагах, которые позволят вам достичь этого результата. Итак, поехали!

Используйте минимальный базовый образ

Обычно, при упаковке ваших приложений вы используете тот или иной базовый образ, который чаще всего основываться на CentOS, Ubuntu или Debian, однако в последнее время широкое распространение получили образы, основанные на Alpine Linux. Давайте посмотрим на размеры этих базовых образов. Я специально взял :latest версии для сравнения:


docker pull ubuntu
docker pull debian
docker pull centos
docker pull alpine
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
debian              latest              a25c1eed1c6f        4 days ago          123 MB
centos              latest              3bee3060bfc8        6 days ago          193 MB
ubuntu              latest              7b9b13f7b9c0        9 days ago          118 MB
alpine              latest              a41a7446062d        2 weeks ago         3.97 MB

По выводу последней команды сразу становится видно, что базовый образ, основанный на Alpine при прочих равных будет меньше минимум в 30 раз! А это существенное сокращение времени загрузки и старта вашего приложения!

Уменьшите количество ваших слоев

Интересуясь Docker-ом и контейнерами в целом, вы уже наверняка успели узнать, что каждый образ контейнера состоит из некоторого количества слоев. Если еще нет, выполните простую команду, чтобы в этом убедиться:


docker history ubuntu
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
7b9b13f7b9c0        9 days ago          /bin/sh -c #(nop)  CMD ["/bin/bash"]            0 B
           9 days ago          /bin/sh -c mkdir -p /run/systemd && echo '...   7 B
           9 days ago          /bin/sh -c sed -i 's/^#\s*\(deb.*universe\...   2.76 kB
           9 days ago          /bin/sh -c rm -rf /var/lib/apt/lists/*          0 B
           9 days ago          /bin/sh -c set -xe   && echo '#!/bin/sh' >...   745 B
           9 days ago          /bin/sh -c #(nop) ADD file:5aff8c59a707833...   118 MB

Каждый из таких слоев занимает какое-то количество места в зависимости от того количества изменений, которые в нем выполнены. Собирая ваши собственные образы необходимо помнить о том, что каждая инструкция ADD, RUN или COPY в вашем Dockerfile-е будет создавать новый слой. Давайте установим postgres поверх стандартного образа Debian одной несколькими RUN командами, и посмотрим разницу. Dockerfile1:


FROM debian

RUN apt-get update -y

# Install packages
RUN apt-get install -y curl
RUN apt-get install -y postgresql
RUN apt-get install -y postgresql-client

Dockerfile2 будет следующим:


FROM debian

RUN apt-get update -y && \
    apt-get install -y curl postgresql postgresql-client

Соберем образы и посмотрим на результат:


docker build -t my_postgres1 -f Dockerfile1 .
docker build -t my_postgres2 -f Dockerfile2 .
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
my_postgres2        latest              35abcc747d83        6 seconds ago       301 MB
my_postgres1        latest              ef8a8500fa00        4 minutes ago       304 MB

Как видите, при использовании меньшего количества инструкций ADD, RUN или COPY ваши образы будут немного, но меньше!

Удалите весь мусор

Теперь проведем еще один фокус: если в процессе создания образа прибираться за собой и удалять различные артефакты, т.к. например, кеш пакетного менеджера или скачиваемые вами tar.gz архивы при установке специфического софта, размер образа будет еще меньше. Изменим два наших Dockerfile-а, добавив к ним инструкции по очистке кеша пакетного менеджера. Dockerfile1 будет:

FROM debian

RUN apt-get update -y

# Install packages
RUN apt-get install -y curl
RUN apt-get install -y postgresql
RUN apt-get install -y postgresql-client

RUN rm -rf /var/lib/apt/lists/*

Dockerfile2 будет:

FROM debian

RUN apt-get update -y && \
    apt-get install -y curl postgresql postgresql-client && \
    rm -rf /var/lib/apt/lists/*

Пересоберем образы и посмотрим на результат:

docker build -t my_postgres1 -f Dockerfile1 .
docker build -t my_postgres2 -f Dockerfile2 .
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
my_postgres2        latest              4d2481a7c7a1        3 minutes ago       291 MB
my_postgres1        latest              bdcf8219e4a7        6 minutes ago       304 MB

Что получилось? Второй образ стал еще меньше, а вот первый не изменился совсем. Почему? Ответ нам даст команда docker history:

docker history 4d2481a7c7a1 && docker history bdcf8219e4a7
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
4d2481a7c7a1        5 minutes ago       /bin/sh -c apt-get update -y &&     apt-ge...   168 MB
a25c1eed1c6f        4 days ago          /bin/sh -c #(nop)  CMD ["bash"]                 0 B
           4 days ago          /bin/sh -c #(nop) ADD file:ce4be6f55b1f47c...   123 MB
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
bdcf8219e4a7        8 minutes ago       /bin/sh -c rm -rf /var/lib/apt/lists/*          0 B
ef8a8500fa00        22 minutes ago      /bin/sh -c apt-get install -y postgresql-c...   543 kB
2f536c51c83f        22 minutes ago      /bin/sh -c apt-get install -y postgresql        152 MB
b1fce129f8e7        24 minutes ago      /bin/sh -c apt-get install -y curl              17.3 MB
ce63a4ba8c71        25 minutes ago      /bin/sh -c apt-get update -y                    9.96 MB
a25c1eed1c6f        4 days ago          /bin/sh -c #(nop)  CMD ["bash"]                 0 B
           4 days ago          /bin/sh -c #(nop) ADD file:ce4be6f55b1f47c...   123 MB

Получается, что команда apt-get update -y создала в отдельном слое кеш на 10 Мб, содержащий обновленную информацию о доступных пакетах, который никуда не делся при попытке его очистить новом слое!

Обратите также внимание и на то, что первый образ пересобрался почти моментально. Это произошло потому что Docker кеширует слои создаваемых вами образов и изменяет в процессе пересборки только те слои, которые были изменены. В первом образе изменился (добавился) только 6-й слой, в то время как во втором единственный слой, содержащий все изменения приходится пересоздавать заново, что занимает существенно больше времени. Эту особенность удобно использовать в процессе разработки: собирайте промежуточные образы используя отдельные инструкции ADD, RUN или COPY, чтобы сократить время пересборки образа, в то время как итоговый образ старайтесь собирать одной единственной командой.

Сделать итоговый образ еще меньше можно за счет использования, например, флага —no-install-recommends:


docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
my_postgres2        latest              5038970a830e        9 seconds ago       217 MB

Оцените разницу! Минус еще 74 мегабайта!

По возможности не копируйте свои исходники в контейнер

В прошлом пункте вы увидели, как Docker работает со слоями в процессе создания образа. Поэтому в этом пункте я лишь посоветую вам по возможности воздержаться от копирования внутрь образа контейнера вашего ПО. Храните ваше ПО на отдельном диске (Docker volume) и монтируйте его в процессе создания контейнера из образа.

Не устанавливайте внутрь контейнера больше 1 сервиса

Чем больше сервисов вы упакуете в контейнер, тем с одной стороны его будет сложнее поддерживать, а с другой стороны размер вашего образа будет много больше, что само собой повлияет на время запуска продуктивного контейнера. Зачем вам тогда нужны контейнеры? Используйте виртуальные машины!

Используйте .dockerignore

Если уж все таки нужно копировать исходники вашего проекта внутрь контейнера, не забудьте создать .dockerignore файл (работает так же как и .gitignore), в котором явно исключить не нужные в итоговом образе файлы, т.к. например:

  • *.pyc
  • *.venv
  • .git
  • build
  • и т.д.

Сервисы упоминаемые в статье

  1. Публичное облако КРОК

Не пропустите самые важные, интересные и полезные статьи недели

Ваш e-mail успешно подписан.

Смотрите также