При работе с Docker и создании собственных образов вы можете быть удивлены тем, как много места они занимают на диске. В этой статье мы рассмотрим 5 способов уменьшения размера образов Docker. В качестве примера мы возьмем создание образа с socks-сервером Dante, но не будем устанавливать его из готовых пакетов, а скомпилируем вручную.
Начало. Решение «в лоб». Размер образа — 328MB.
Создадим простой файл конфигурации Dante danted.conf.
internal: 0.0.0.0 port = 1080 internal: :: port = 1080 external: eth0 errorlog: stderr logoutput: stdout socksmethod: username user.privileged: root user.unprivileged: nobody client pass { from: 0/0 to: 0/0 session.max: 200 log: error connect disconnect } socks pass { from: 0/0 to: 0/0 log: error connect disconnect }
Также создадим Dockerfile будущего образа.
FROM debian:stable RUN apt-get update RUN apt-get upgrade -y RUN apt-get install -y wget gcc make WORKDIR /root/ RUN wget ftp://www.inet.no/dante/files/dante-1.4.2.tar.gz RUN tar zxvf dante-1.4.2.tar.gz WORKDIR /root/dante-1.4.2 RUN ./configure RUN make RUN make install COPY danted.conf /etc/ RUN useradd testuser RUN echo "testuser:pass123pass" | chpasswd RUN echo "precedence ::ffff:0:0/96 100" >> /etc/gai.conf EXPOSE 1080 CMD sockd -f /etc/danted.conf
Соберем образ и увидим что он весит аж 328M.
sudo docker build -t localhost/debian-danted:testing . sudo docker save -o danted.tar localhost/debian-danted:testing du -h danted.tar #328M danted.tar
Так как же нам уменьшить размер образа?
Способ #1. Используем более компактные образы ОС. Размер образа — 260MB.
Если ваше приложение никак не привязано к ОС, имеет смысл рассмотреть альтернативные базовые образы, например alpine. Это очень компактный и популярный образ ОС для использования в Docker.
Если же ваше приложение каким либо образом завязано на ОС, например на Debian, можно использовать более компактный образ, такой как debian:stable-slim.
Изменим базовый образ в Dockerfile на debian:stable-slim.
FROM debian:stable-slim RUN apt-get update RUN apt-get upgrade -y RUN apt-get install -y wget gcc make WORKDIR /root/ RUN wget ftp://www.inet.no/dante/files/dante-1.4.2.tar.gz RUN tar zxvf dante-1.4.2.tar.gz WORKDIR /root/dante-1.4.2 RUN ./configure RUN make RUN make install COPY danted.conf /etc/ RUN useradd testuser RUN echo "testuser:pass123pass" | chpasswd RUN echo "precedence ::ffff:0:0/96 100" >> /etc/gai.conf EXPOSE 1080 CMD sockd -f /etc/danted.conf
sudo docker build -t localhost/debian-danted:testing . sudo docker save -o danted.tar localhost/debian-danted:testing du -h danted.tar #260M danted.tar
Так-то лучше.
Способ #2. Не устанавливаем рекомендуемые пакеты. Размер образа — 253MB.
Передаём утилите apt параметр —no-install-recommends, а те пакеты, которые действительно нужны (libc-dev) перечисляем вручную.
FROM debian:stable-slim RUN apt-get update RUN apt-get upgrade -y RUN apt-get install -y --no-install-recommends wget gcc make libc-dev WORKDIR /root/ RUN wget ftp://ftp.inet.no/pub/socks/dante-1.4.2.tar.gz RUN tar zxvf dante-1.4.2.tar.gz WORKDIR /root/dante-1.4.2 RUN ./configure RUN make RUN make install COPY danted.conf /etc/ RUN useradd testuser RUN echo "testuser:pass123pass" | chpasswd RUN echo "precedence ::ffff:0:0/96 100" >> /etc/gai.conf EXPOSE 1080 CMD sockd -f /etc/danted.conf
sudo docker build -t localhost/debian-danted:testing . sudo docker save -o danted.tar localhost/debian-danted:testing du -h danted.tar #253M danted.tar
Способ #3. Удаляем неиспользуемые файлы, но только в том же Docker-слое. Размер образа — 121MB.
По умолчанию Docker создаёт отдельный слой на каждую строку Dockerfile. В слое содержатся изменения внесенные относительно предыдущего слоя, а в случае с первой строкой, относительно базового образа. Если удалять неиспользуемые файлы в следующем слое, предыдущий слой так и останется неизменным — данные из него никуда не удалятся и останутся на диске. Это позволяет Docker не проматывать все строки заново при ребилде образа, но, в некоторых случаях, может значительно увеличить размер образа.
Переместим установку, компиляцию и удаление в один слой.
FROM debian:stable-slim RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends wget gcc make libc-dev && \ wget ftp://ftp.inet.no/pub/socks/dante-1.4.2.tar.gz -P /root && cd /root && tar zxvf dante-1.4.2.tar.gz && \ cd /root/dante-1.4.2 && ./configure && make && make install && \ rm -r /root/dante* && apt-get -y remove wget gcc make libc-dev && apt-get -y autoremove --purge && apt-get -y clean COPY danted.conf /etc/ RUN useradd testuser && echo "testuser:pass123pass" | chpasswd RUN echo "precedence ::ffff:0:0/96 100" >> /etc/gai.conf EXPOSE 1080 CMD sockd -f /etc/danted.conf
sudo docker build -t localhost/debian-danted:testing . sudo docker save -o danted.tar localhost/debian-danted:testing du -h danted.tar #121M danted.tar
Способ #4. Экспериментальный параметр squash. Размер образа — 120MB.
При билде образа мы можем использовать экспериментальный параметр squash. При использовании этого параметра все промежуточные слои «схлапываются» в один финальный слой. Финальный слой полностью отвязывается от промежуточных, которые могут быть удалены. Такое «схлапывание» позволяет сэкономить немного места.
Т.к. параметр экспериментальный, необходимо разрешить его в конфиге Docker /etc/docker/daemon.json.
{ "experimental": true, }
Перезапустим Docker.
sudo systemctl restart docker
Пересоберем образ с параметром squash.
sudo docker build --squash -t localhost/debian-danted:testing . sudo docker save -o danted.tar localhost/debian-danted:testing du -h danted.tar #120M danted.tar
Способ #5. Используем сжатие файловой системы btrfs. Размер образа — 56MB.
Хорошо. Мы сделали всё, чтобы уменьшить образ для его передачи по сети. Но если мы хотим хранить множество образов в локальном репозитории и делать это еще более компактно? Для этих целей мы можем использовать файловую систему со сжатием — btrfs.
Для примера создадим временный файл и посмотрим какое количество дискового пространства удастся сэкономить в этот раз.
sudo apt install btrfs-progs sudo fallocate -l 2G /root/btrfs.tmp sudo mkfs.btrfs /root/btrfs.tmp sudo mount /root/btrfs.tmp /var/lib/docker -o compress-force=zstd
Подключим драйвер btrfs в конфиге Docker /etc/docker/daemon.json.
{ "experimental": true, "storage-driver": "btrfs" }
Перезапустим Docker, соберем образ и удалим лишнее.
sudo systemctl restart docker sudo docker build --squash -t localhost/debian-danted:testing . sudo docker run --restart=always -it -d --name danted localhost/debian-danted:testing sudo docker image prune -a sudo docker image rm debian:stable-slim
Посмотрим хорошо ли удалось сжать образ.
sudo apt install btrfs-compsize sudo compsize /var/lib/docker/ Processed 7481 files, 2121 regular extents (3468 refs), 4906 inline. Type Perc Disk Usage Uncompressed Referenced TOTAL 46% 56M 121M 192M none 100% 643K 643K 879K zstd 46% 56M 120M 191M
56MB. Так куда лучше.
Ах, да. Проверка.
#sudo docker run --restart=always -it -d --name danted localhost/debian-danted:testing curl --proxy socks5://testuser:pass123pass@172.17.0.2:1080 innerlife.io
Здесь вы должны увидеть содержимое моего сайта, что значит что контейнер с Dante запущен и успешно работает.
Thank you!!1