Как уменьшить размер образа Docker с 1,43 ГБ до 22,4 МБ

При работе с Docker большой проблемой является размер образа. Часто это более 1,43 ГБ только для стандартного проекта, который мы получаем от create-react-app.

Сегодня мы контейнеризируем приложение ReactJS и узнаем некоторые хитрости о том, как можно уменьшить размер и в то же время повысить производительность. Трюки будут показаны для ReactJS, но они применимы к любому приложению NodeJS.

Это перевод статьи.

Шаг 1. Создайте проект


Зайдите в свой терминал и введите


npx create-react-app docker-image-test

Затем create-react-app предоставит вам базовое приложение React.


После этого перейдите в корневой каталог и запустите проект.


cd docker-image-test
yarn install
yarn start

Затем перейдите по адресу http://localhost:3000, чтобы убедиться, что приложение запущено и работает.

Шаг 2. Создайте свой образ


Внутри корневого каталога вашего проекта создайте файл с именем Dockerfile и вставьте туда следующий код.


FROM node:12

WORKDIR /app

COPY package.json ./

RUN yarn install

COPY . .

EXPOSE 3000

CMD ["yarn", "start"]

Мы получаем наш базовый образ node:12, устанавливаем зависимости и запускаем основные команды.


Теперь со своего терминала создайте образ для своего контейнера.


docker build -t docker-image-test .

Docker создаст ваш образ. После завершения вы можете увидеть образ с помощью этой команды.


docker images

В верхней части списка находится наш только что созданный образ, а в правом углу мы видим его размер. На данный момент это 1,43 ГБ .

Мы можем запустить образ с помощью следующей команды


docker run --rm -it -p 3000:3000/tcp docker-image-test:latest

Вы можете зайти в браузер и обновить страницу, чтобы убедиться, что она все еще работает.

Шаг 3. Измените базовый образ


Мы использовали node:12 в качестве базового образа в предыдущей конфигурации. Но традиционно образы узлов основаны на Ubuntu, что излишне тяжело для нашего простого приложения React.


Из DockerHub (официальный реестр образов Docker) мы видим, что образы на основе Alpine намного меньше образов на основе Ubuntu, и они упакованы с минимальной зависимостью.


Сравнение размеров этих базовых образов показано ниже.

Теперь мы будем использовать node:12-alpine в качестве нашего базового образа и посмотрим, что произойдет.


FROM node:12-alpine

WORKDIR /app

COPY package.json ./

RUN yarn install

COPY . .

EXPOSE 3000

CMD ["yarn", "start"]

Ух ты! Размер нашего образа уменьшен до 580 МБ. Но можем ли мы сделать лучше?

Шаг 4. Многоэтапная сборка


В предыдущих конфигурациях мы копировали все исходные коды в рабочий каталог.


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


Конфигурация будет выглядеть примерно так.


# STAGE 1

FROM node:12-alpine AS build

WORKDIR /app

COPY package.json ./

RUN yarn  install

COPY . /app

RUN yarn build


# STAGE 2

FROM node:12-alpine

WORKDIR /app

RUN npm install -g webserver.local

COPY --from=build /app/build ./build

EXPOSE 3000

CMD webserver.local -d ./build

На первом этапе мы устанавливаем зависимости и собираем наш проект.


На втором этапе мы копируем содержимое папки сборки из предыдущего этапа и используем его для обслуживания нашего приложения.


Таким образом, у нас нет ненужных зависимостей и кода.


Далее видим образ из списка как и раньше. Теперь размер нашего образа составляет всего 97,5 МБ. Насколько это здорово?

Шаг 5. Используем NGINX


Мы используем сервер node для нашего приложения ReactJS, что не является лучшим вариантом для обслуживания статического контента.


Мы можем использовать более эффективный и легкий сервер, такой как **Nginx **. Наш окончательный конфигурационный файл Docker будет выглядеть примерно так.


# STAGE 1

FROM node:12-alpine AS build

WORKDIR /app

COPY package.json ./

RUN yarn  install

COPY . /app

RUN yarn build

# STAGE 2

FROM nginx:stable-alpine

COPY --from=build /app/build /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

Мы меняем второй этап нашей конфигурации, чтобы обслуживать приложение с помощью Nginx.


Затем мы создаем наш образ, используя эту текущую конфигурацию

Размер образа уменьшен всего до 22,4 МБ!


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


Мы можем проверить, работает ли оно, используя следующую команду.


docker run --rm  -it -p 3000:80/tcp docker-image-test:latest

Эти приемы вы можете применить к любому из ваших проектов NodeJS, чтобы значительно уменьшить размер образа. Теперь ваш контейнер действительно более портативный и эффективный.

Если у вас есть вопросы или нужна помощь в использовании Docker — обращайтесь к нам, мы всегда готовы помочь! Можем начать, например, с аудита инфраструктуры. Ну, или выбирайте ту услугу, которая более актуальна