Очистите свои образы Docker, оставив ненужные инструменты
В этой короткой статье мы создаем образ в несколько этапов, чтобы значительно уменьшить размер нашего образа докера. В итоге у нас будет изображение, которое делает то же самое, но почти в 10 раз меньше по размеру! Мы делаем это, оставляя позади инструменты, которые мы используем для создания образа.
Сначала мы создадим Dockerfile для сборки образа «обычным» способом. Затем мы обновляем этот файл, используя дополнительный этап, оставляя ненужные артефакты. Наконец, мы продолжим оптимизацию, поэкспериментировав с различными образами докеров. Посмотрим, сколько жира мы сможем срезать; Давайте кодировать!
Прежде чем мы начнем
Мы используем много терминальных команд. Ознакомьтесь с этой статьей, если вы не знакомы.
Настраивать
Представьте, что мы создаем приложение, которому нужны географические данные. Open StreetMap предоставляет нам эти геоданные: через geofabrik.de
мы можем скачать геоданные по странам в формате .osm.pbf
. Затем мы можем использовать инструмент под названием Osmium
, чтобы объединить эти файлы вместе. Представьте, что нам нужен только этот объединенный файл для передачи в наше приложение.
Подводя итог: нам нужно использовать curl
(для загрузки) и osmium
(для слияния) только один раз: когда мы получим объединенный файл, нам больше не нужны эти инструменты. В двухэтапной сборке мы загружаем эти инструменты на первом этапе, используем их там, а затем переносим только результат (объединенный файл) на следующий этап, оставляя инструменты позади.
Прежде чем мы увидим двухэтапную сборку, давайте посмотрим на «обычный» способ.
1. Нормальная сборка
В этой части мы построим наше изображение самым простым способом. Тем не менее, мы помним о некоторых небольших хитростях, чтобы свернуть наше изображение, как описано в этой статье. Вот докерфайл:
FROM ubuntu:20.04 # BUNDLE LAYERS RUN apt-get update -y && apt install -y --no-install-recommends \ curl \ osmium-tool \ && rm -rf /var/lib/apt/lists/* RUN mkdir /osmfiles \ && mkdir /merged \ && curl https://download.geofabrik.de/europe/monaco-latest.osm.pbf -o /osmfiles/monaco.osm.pbf \ && curl https://download.geofabrik.de/europe/andorra-latest.osm.pbf -o /osmfiles/andorra.osm.pbf \ && osmium merge /osmfiles/monaco.osm.pbf /osmfiles/andorra.osm.pbf -o /merged/merged.osm.pbf
Этот dockerfile делает именно то, что нам нужно: устанавливает curl и osmium, скачивает файлы и объединяет их. В итоге мы получаем объединенный файл, который находится в /merged
.
Обратите внимание, что после получения объединенного файла мы ничего не делаем. В этой статье мы упростим этот файл dockerfile и не будем делать с ним какие-либо действия.
Давайте проверим размер этого изображения:
testimg:latest a88a8848201b 16 seconds ago 96.9MB
Как видите, размер изображения составляет около 97 МБ. В следующей части мы обновим наш dockerfile несколькими этапами.
2. Реализация многоэтапной сборки
В предыдущем примере мы использовали наши инструменты сборки (curl и osmium) только один раз. После того, как они используются, они остаются в нашем образе. Аналогия: вы покупаете новую машину, но обнаруживаете, что все инструменты, которые использовались для сборки машины, все еще лежат в багажнике и занимают драгоценное место!
В этой части мы сосредоточимся на том, чтобы отказаться от инструментов, которые мы использовали для сборки автомобиля. Давайте проверим новый Dockerfile и пройдемся по коду.
FROM ubuntu:20.04 AS final FROM ubuntu:20.04 as build # BUNDLE LAYERS RUN apt-get update -y && apt install -y --no-install-recommends \ curl \ osmium-tool \ && rm -rf /var/lib/apt/lists/* RUN mkdir /osmfiles \ && mkdir /merged \ && curl http://download.geofabrik.de/europe/monaco-latest.osm.pbf -o /osmfiles/monaco.osm.pbf \ && curl http://download.geofabrik.de/europe/andorra-latest.osm.pbf -o /osmfiles/andorra.osm.pbf \ && osmium merge /osmfiles/monaco.osm.pbf /osmfiles/andorra.osm.pbf -o /merged/merged.osm.pbf FROM final RUN mkdir /merged COPY --from=build /merged /merged
Как видите, мы используем два этапа: один называется build, а другой называется final. Установите curl и osmium на нашу сборку. Используйте их для создания объединенного файла и, наконец, просто скопируйте папку merged
на этап final
.
Как только мы вводим FROM final
, мы «входим» в нашу последнюю стадию, поэтому все, что после FROM final
, происходит там. То же самое касается FROM ubuntu:20.04 as build
в строке 2. Обратите внимание, что curl и osmium устанавливаются только на этапе сборки. Как только мы достигнем конца нашего файла dockerfile, мы сохраним только ту стадию, на которой мы находимся. сцена остается позади. Давайте проверим размер нашего нового контейнера:
testimgbetter:latest 7342ee3948e8 3 seconds ago 75.1MB
Наш новый образ 75 МБ: мы сэкономили более 20 МБ или чуть меньше 20 %, оставив инструменты, которые нам больше не нужны. Это уже очень хорошее улучшение. Давайте найдем, как мы можем оптимизировать больше.
3. Многоэтапный с меньшим конечным изображением
В предыдущей части мы использовали образ ubuntu:20.04
как для сборки, так и для финальной стадии. Для стадии сборки это довольно логично; здесь мы делаем сложные вещи: устанавливаем пакеты, загружаем материал, клонируем git, в других случаях, возможно, даже используем cmake
или make
для компиляции кода! Однако последний этап не обязательно должен быть таким умным, как этап сборки.
Идея этой части заключается в том, что вам нужно большое, насыщенное изображение, такое как ubuntu:20.04
, для сложной стадии сборки. Затем мы можем скопировать результаты с этапа сборки на этап финальный, основанный на гораздо более простом изображении. В нашем случае мы можем использовать даже очень маленькое изображение, такое как Alpine. Немного подкорректируем наш dockerfile:
FROM alpine:3.14 AS final
Теперь, когда наша сборочная стадия завершена, мы копируем только наш объединенный файл на альпийскую стадию. Давайте проверим общий размер вновь созданного образа:
testimgbetter latest 8ad3278671e1 17 minutes ago 7.95MB
Мы перешли с 75 МБ на чуть менее 8 МБ: снижение составило почти 90 %!
Обратите внимание, что использование альпийских изображений не всегда работает; идея этой части этой статьи заключается в том, что мы можем использовать окончательные изображения, которые меньше, чем этап сборки.
Заключение
В этой статье мы сосредоточились на том, чтобы понять, как создается докер, и свести к минимуму образы докеров, удалив все инструменты, которые нам больше не нужны. Мы можем сделать это очень эффективно, используя несколько этапов: выполнение сложных задач, таких как установка и сборка расширенного образа, затем копирование результата в более тонкий окончательный образ и оставление этапа сборки позади.
Примеры в этой статье довольно минимальны; оставив только curl
и osmium
. Есть примеры, когда я использовал более громоздкий этап сборки и сэкономил более 1,5 ГБ, увеличив размер изображения с 1,8 ГБ до 0,3 ГБпросто оставив артефакты, которые нам больше не нужны!
Я надеюсь, что эта статья была понятной, но если у вас есть предложения/пояснения, прокомментируйте, чтобы я мог внести улучшения. А пока ознакомьтесь с моими другими статьями на всевозможные темы, связанные с программированием, например:
- Докер для абсолютных новичков
- Docker Compose для абсолютных новичков
- Превратите свой код в настоящую программу: упаковка, запуск и распространение скриптов с помощью Docker
- Почему Python медленный и как его ускорить
- Расширенная многозадачность в Python: применение и бенчмаркинг пулов потоков и пулов процессов
- Напишите собственное расширение для C, чтобы ускорить Python x100
- Начало работы с Cython: как выполнять ›1,7 миллиарда вычислений в секунду на Python
- Создайте быстрый автоматически документированный, удобный в сопровождении и простой в использовании Python API в 5 строк кода с помощью FastAPI
Удачного кодирования!
— Майк
P.S. Нравится, что я делаю? "Подписывайтесь на меня"!