Как лучше сэкономить место при использовании докера для CI / CD? - PullRequest
3 голосов
/ 02 апреля 2019

Я использую CircleCI и докер для CI / CD конвейера. По сути, я помещаю приложение (python) и среду в новый образ докера каждый раз, когда помещаю новый код в GitHub. Затем я помещаю образ в свой личный реестр Docker, размещенный на Nexus, и внедряю мое приложение, извлекая последний образ из этого реестра и запускаю контейнер.

Моя проблема в том, что эти изображения докера занимают тонны пространства:

    REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
my-app   0.1.23              6f13476770c2        3 minutes ago       1.99GB
my-app   0.1.22              7ff62dddb50a        10 minutes ago      1.99GB
my-app   0.1.21              55af2d3235c7        3 hours ago         1.99GB
my-app   0.1.20              304543b7fc71        5 hours ago         1.99GB
my-app   0.1.17              fddcef3f262b        2 weeks ago         1.99GB
my-app   0.1.16              a62c9ba1f997        2 weeks ago         1.99GB
my-app   0.1.12              a8d87d86699a        2 weeks ago         1.99GB

Поскольку работающая среда занимает много места в изображении и не меняется часто (не так часто, как при изменении кода), я предполагаю, что много места просто теряется, создавая одни и те же зависимости / среду снова и снова. Итак, вопрос в том, правильно ли я это делаю? Если нет, то какова лучшая практика. Заранее спасибо!

P.S. Среда, которую я использую, требует некоторых зависимостей (numpy, tenorflow и т. Д.), Которым требуется GCC, поэтому я не могу не использовать изображение Python Alpine, если я не ошибаюсь.

Мой Dockerfile:

FROM python:3.6-stretch
# Install app dependencies
RUN apt-get update && apt-get install -y \
    python3-dev \
    python3-pip

RUN mkdir /opt/working_dir/
WORKDIR /opt/working_dir/

# Copy the entire project into the current directory
COPY . ./
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

Некоторые истории докеров:

$ docker image history my-app:0.1.23
6f13476770c2        19 hours ago        /bin/sh -c pip install -r requirements.txt      955MB               
<missing>           19 hours ago        /bin/sh -c pip install --upgrade pip            4.97MB              
<missing>           19 hours ago        /bin/sh -c #(nop) COPY dir:5bb6533618d16964c…   16.5MB              
<missing>           19 hours ago        /bin/sh -c #(nop) WORKDIR /opt/reco_engine/     0B                  
<missing>           19 hours ago        /bin/sh -c mkdir /opt/reco_engine/              0B                  
<missing>           19 hours ago        /bin/sh -c apt-get update && apt-get install…   90.6MB              
<missing>           6 days ago          /bin/sh -c #(nop)  CMD ["python3"]              0B                  
<missing>           6 days ago          /bin/sh -c set -ex;   wget -O get-pip.py 'ht…   6.04MB              
<missing>           6 days ago          /bin/sh -c #(nop)  ENV PYTHON_PIP_VERSION=19…   0B                  
<missing>           6 days ago          /bin/sh -c cd /usr/local/bin  && ln -s idle3…   32B                 
<missing>           6 days ago          /bin/sh -c set -ex   && wget -O python.tar.x…   65.3MB              
<missing>           6 days ago          /bin/sh -c #(nop)  ENV PYTHON_VERSION=3.6.8     0B                  
<missing>           6 days ago          /bin/sh -c #(nop)  ENV GPG_KEY=0D96DF4D4110E…   0B                  
<missing>           6 days ago          /bin/sh -c apt-get update && apt-get install…   16.9MB              
<missing>           6 days ago          /bin/sh -c #(nop)  ENV LANG=C.UTF-8             0B                  
<missing>           6 days ago          /bin/sh -c #(nop)  ENV PATH=/usr/local/bin:/…   0B                  
<missing>           6 days ago          /bin/sh -c set -ex;  apt-get update;  apt-ge…   562MB               
<missing>           6 days ago          /bin/sh -c apt-get update && apt-get install…   142MB               
<missing>           6 days ago          /bin/sh -c set -ex;  if ! command -v gpg > /…   7.81MB              
<missing>           6 days ago          /bin/sh -c apt-get update && apt-get install…   23.2MB              
<missing>           6 days ago          /bin/sh -c #(nop)  CMD ["bash"]                 0B                  
<missing>           6 days ago          /bin/sh -c #(nop) ADD file:843b8a2a9df1a0730…   101MB 

$ docker image history my-app:0.1.22
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
7ff62dddb50a        19 hours ago        /bin/sh -c pip install -r requirements.txt      955MB               
<missing>           19 hours ago        /bin/sh -c pip install --upgrade pip            4.97MB              
<missing>           19 hours ago        /bin/sh -c #(nop) COPY dir:f054e43f5766a4738…   16.5MB              
<missing>           19 hours ago        /bin/sh -c #(nop) WORKDIR /opt/reco_engine/     0B                  
<missing>           19 hours ago        /bin/sh -c mkdir /opt/reco_engine/              0B                  
<missing>           19 hours ago        /bin/sh -c apt-get update && apt-get install…   90.6MB              
<missing>           6 days ago          /bin/sh -c #(nop)  CMD ["python3"]              0B                  
<missing>           6 days ago          /bin/sh -c set -ex;   wget -O get-pip.py 'ht…   6.04MB              
<missing>           6 days ago          /bin/sh -c #(nop)  ENV PYTHON_PIP_VERSION=19…   0B                  
<missing>           6 days ago          /bin/sh -c cd /usr/local/bin  && ln -s idle3…   32B                 
<missing>           6 days ago          /bin/sh -c set -ex   && wget -O python.tar.x…   65.3MB              
<missing>           6 days ago          /bin/sh -c #(nop)  ENV PYTHON_VERSION=3.6.8     0B                  
<missing>           6 days ago          /bin/sh -c #(nop)  ENV GPG_KEY=0D96DF4D4110E…   0B                  
<missing>           6 days ago          /bin/sh -c apt-get update && apt-get install…   16.9MB              
<missing>           6 days ago          /bin/sh -c #(nop)  ENV LANG=C.UTF-8             0B                  
<missing>           6 days ago          /bin/sh -c #(nop)  ENV PATH=/usr/local/bin:/…   0B                  
<missing>           6 days ago          /bin/sh -c set -ex;  apt-get update;  apt-ge…   562MB               
<missing>           6 days ago          /bin/sh -c apt-get update && apt-get install…   142MB               
<missing>           6 days ago          /bin/sh -c set -ex;  if ! command -v gpg > /…   7.81MB              
<missing>           6 days ago          /bin/sh -c apt-get update && apt-get install…   23.2MB              
<missing>           6 days ago          /bin/sh -c #(nop)  CMD ["bash"]                 0B                  
<missing>           6 days ago          /bin/sh -c #(nop) ADD file:843b8a2a9df1a0730…   101MB  

Ответы [ 4 ]

3 голосов
/ 02 апреля 2019
  1. Выясните, что общего у ваших приложений.Это становится вашим базовым образом для развертываемого приложения.
  2. Создайте базовый образ, названный в честь вашей компании.Назовите это app-base.
  3. Каждое изображение основано на базе приложения.Это делает шаг сборки, который использует базу.Просмотрите многоэтапные сборки.
  4. Ваше изображение app-base абсолютно настолько маленькое, насколько вы можете его сделать.Он не включает в себя то, что делает виртуальная машина.Вы начинаете с небольшого базового образа, и вы работаете, работаете, работаете, чтобы сделать его очень маленьким.
  5. Фиксирует и развертывает небольшие изменения.Ваше приложение опирается на app-base.Размер вашего приложения зависит, но вы не должны поставлять инструменты разработки.

Я собираюсь предположить, что вы используете Python.Например, ваши изображения 2 ГБ.Размер установочного образа Alpine Linux Python составляет 80 МБ.Ваше приложение может добавить, скажем, еще 100 МБ.Если у вас много нативных зависимостей, может быть трудно разбить их или использовать Alpine (скажем, вам нужен GCC).

Если все повезет, базовый образ вашего приложения будет 80 МБ, а образ встроенного приложения CI - выбудет развернуто будет 100 МБ.80 МБ не будут использоваться снова и снова, потому что ваш сервер Nexus будет повторно использовать app-base, в котором есть Python (из Alpine Python или из ваших собственных настроек).Использование такого подхода может сэкономить вам много места (что означает скорость).

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

«Лучшие» практики (такой вещи нетно вот несколько советов):

  • Используйте изображения Alpine Linux в качестве базовой линии, если можете.Обменивайтесь с GCC Deps.
  • Создайте свои собственные крошечные изображения для своей компании, настройте, если вам нужно.
  • Добавьте как можно меньше.Если вам нужно что-то скомпилировать, добавьте инструменты компиляции в качестве этапа и не отправляйте его.Вам это не нужно.
  • Другими словами, используйте многоэтапные сборки
  • Нацеливайтесь на небольшие двоичные файлы, если можете.Вы можете скомпилировать в бинарный файл?Огромная экономия.
  • Старайтесь не подходить к нему как к виртуальным машинам.т.е.: не устанавливать ssh.
2 голосов
/ 02 апреля 2019

Большинство примеров Python Dockerfile обрабатывают файл require.txt отдельно от остальной части кода Python, например:

FROM python:3.6-stretch
# Install app dependencies
RUN apt-get update && apt-get install -y \
    python3-dev \
    python3-pip

RUN mkdir /opt/working_dir/
WORKDIR /opt/working_dir/

# Copy the entire project into the current directory
RUN pip install --upgrade pip
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY . ./

Благодаря этому ваши сборки будут намного быстрее и будут повторно использовать все, кроме последнего слоя, если не будет обновлен файл needs.txt. Вы по-прежнему будете видеть большие изображения в выводе image ls, но если вы осмотрите слои, вы увидите, что почти все они одинаковы для всех изображений.

1 голос
/ 02 апреля 2019

Есть много способов оптимизировать ваши изображения.Если вы публикуете свой Dockerfile, я могу дать вам подсказки.

Вы также можете просмотреть историю изображения:

docker image history my-app:0.1.23

Это говорит вам, сколько места добавляет каждая команда с определенным слоемbuilds.

Также вы можете просмотреть ваши изображения и посмотреть, сколько общих слоев используется:

docker inspect my-app:0.1.23
0 голосов
/ 03 апреля 2019

Добавлен docker_layer_caching в ваш конфигурационный файл:

jobs:
 jobName:
   machine:
     enabled: true
     docker_layer_caching: true

После этого все старые слои кэшируются в CircleCI.

...