Docker сборка azure -> большая разница на идентичной кодовой базе из-за COPY node_modules. Местный пробег не дает различий - PullRequest
0 голосов
/ 17 января 2020

У меня есть Azure конвейер Devops, который создает docker образов, которые будут запускаться на разных устройствах IoT-Edge. Устройства имеют очень плохое соединение inte rnet, поэтому очень важен маленький размер docker diff.

База кода состоит из сервера nodejs машинописного текста (следовательно, yarn build), который нуждается в node_modules, которые требуют сборки с make g cc et c.

Когда я запускаю процесс сборки docker локально на моей машине, docker использует промежуточные слои из предыдущих сборок, поэтому разница при использовании docker history <image_id> составляет всего 700 КБ. , (фактическая кодовая база). Я вижу в журналах сборки, что yarn install берется из кэша, поэтому слой ha sh становится идентичным.

При построении изображения в azure, разность становится 90 МБ. (Копируются все node_modules) Я извлек node_modules из каждого изображения и сравнил хэши для всех файлов в каждой папке с HashMyFiles.exe, сравнивая SHA-1 и SHA-256.

Но несжатый tar ha sh не является идентичным со ссылкой на этот пост о том, как docker слои хэшируются: Как Docker вычисляет га sh каждого слоя? Это детерминировано c?


Итак, вопрос в том, как мне избежать необходимости извлекать целые модули node_mo для каждого изменения кода при построении изображения в azure.


Одно из обсуждавшихся нами решений - создать предустановку docker image-image с нашими желаемыми модулями node_modules. Но это не является предпочтительным и требует дополнительной работы при смене модулей.

Docker история из двух идентичных кодовых баз, встроенных в azure: 1

PS C:\temp\cby> docker history a8f3453f4c1c
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
a8f3453f4c1c        2 hours ago         /bin/sh -c #(nop)  CMD ["node" "./dist/index…   0B
<missing>           2 hours ago         /bin/sh -c #(nop)  ENV NODE_ENV=production      0B
<missing>           2 hours ago         /bin/sh -c mkdir ./logs/                        0B
<missing>           2 hours ago         /bin/sh -c yarn run build                       3.34MB
<missing>           2 hours ago         /bin/sh -c #(nop) COPY dir:31a5b4423ce7e6928…   323kB
<missing>           2 hours ago         /bin/sh -c #(nop) COPY dir:a234dce19106582d9…   93.7MB
<missing>           2 hours ago         /bin/sh -c #(nop) WORKDIR /app                  0B
<missing>           2 hours ago         /bin/sh -c apk add --no-cache udev              1.83MB
<missing>           2 days ago                                                          70.2MB              merge sha256:eef5dfda7c2565cba57f222376d551426487839af67cf659bb3bb4fa51ef688a to sha256:6d1ef012b5674ad8a127ecfa9b5e6f5178d171b90ee462846974177fd9bdd39f
<missing>           2 days ago          /bin/sh -c rm -rf latest.tar.gz* /tmp/*     …   0B
<missing>           2 days ago          /bin/sh -c apk del curl gnupg                   0B
<missing>           2 days ago          /bin/sh -c curl -sfSL -O https://yarnpkg.com…   0B
<missing>           2 days ago          /bin/sh -c for server in ipv4.pool.sks-keyse…   0B
<missing>           2 days ago          /bin/sh -c /usr/lib/node_modules/npm/bin/npm…   0B
<missing>           2 days ago          /bin/sh -c apk upgrade --no-cache -U &&   ap…   0B
<missing>           2 days ago          /bin/sh -c #(nop) COPY file:fc6fb2d3d0d591f8…   0B
<missing>           2 days ago          /bin/sh -c #(nop) COPY dir:3d23406cd5b322399…   0B
<missing>           2 days ago          /bin/sh -c #(nop) COPY dir:857b32a43b41ef438…   0B
<missing>           3 days ago          /bin/sh -c #(nop) COPY file:20cc2cc5b0ae7508…   0B
<missing>           10 months ago       /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           10 months ago       /bin/sh -c #(nop) ADD file:aa17928040e31624c…   4.21MB

2

PS C:\temp\cby> docker history 2fc80525d55e
IMAGE               CREATED              CREATED BY                                      SIZE                COMMENT
2fc80525d55e        45 seconds ago       /bin/sh -c #(nop)  CMD ["node" "./dist/index…   0B
<missing>           46 seconds ago       /bin/sh -c #(nop)  ENV NODE_ENV=production      0B
<missing>           46 seconds ago       /bin/sh -c mkdir ./logs/                        0B
<missing>           48 seconds ago       /bin/sh -c yarn run build                       3.34MB
<missing>           57 seconds ago       /bin/sh -c #(nop) COPY dir:31a5b4423ce7e6928…   323kB
<missing>           About a minute ago   /bin/sh -c #(nop) COPY dir:a234dce19106582d9…   93.7MB
<missing>           About a minute ago   /bin/sh -c #(nop) WORKDIR /app                  0B
<missing>           About a minute ago   /bin/sh -c apk add --no-cache udev              1.83MB
<missing>           2 days ago                                                           70.2MB              merge sha256:eef5dfda7c2565cba57f222376d551426487839af67cf659bb3bb4fa51ef688a to sha256:6d1ef012b5674ad8a127ecfa9b5e6f5178d171b90ee462846974177fd9bdd39f
<missing>           2 days ago           /bin/sh -c rm -rf latest.tar.gz* /tmp/*     …   0B
<missing>           2 days ago           /bin/sh -c apk del curl gnupg                   0B
<missing>           2 days ago           /bin/sh -c curl -sfSL -O https://yarnpkg.com…   0B
<missing>           2 days ago           /bin/sh -c for server in ipv4.pool.sks-keyse…   0B
<missing>           2 days ago           /bin/sh -c /usr/lib/node_modules/npm/bin/npm…   0B
<missing>           2 days ago           /bin/sh -c apk upgrade --no-cache -U &&   ap…   0B
<missing>           2 days ago           /bin/sh -c #(nop) COPY file:fc6fb2d3d0d591f8…   0B
<missing>           2 days ago           /bin/sh -c #(nop) COPY dir:3d23406cd5b322399…   0B
<missing>           2 days ago           /bin/sh -c #(nop) COPY dir:857b32a43b41ef438…   0B
<missing>           3 days ago           /bin/sh -c #(nop) COPY file:20cc2cc5b0ae7508…   0B
<missing>           10 months ago        /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           10 months ago        /bin/sh -c #(nop) ADD file:aa17928040e31624c…   4.21MB

Мой Dockerfile, я пробовал несколько dockerfile, с многоступенчатой ​​сборкой и без нее, с одинаковыми результатами. Azure дает большую разницу при загрузке изображения:

FROM mhart/alpine-node:10
RUN apk add --no-cache make gcc g++ python linux-headers udev
WORKDIR /app

# Install node modules first (avoids reinstalling for every source code change).
COPY package.json yarn.lock ./
RUN yarn install


FROM mhart/alpine-node:10
RUN apk add --no-cache udev
WORKDIR /app
COPY --from=0 /app/node_modules ./node_modules
COPY . .
RUN yarn run build

RUN mkdir ./logs/

ENV NODE_ENV production

CMD ["node", "./dist/index.js"]

.dockerignore

node_modules
/build
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

/logs
/tests
/testlogs
/dist
/ota

.vscode
.git

РЕДАКТИРОВАТЬ + Временное решение

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

Я не уверен, почему сборка docker дает новый га sh каждый раз, когда мы запускаем сборку для каждой операции.

Время сборки все равно будет медленным, если бы ha sh были одинаковыми, потому что azure агенты сборки каждый раз запускаются с чистой машины.

Ответы [ 2 ]

0 голосов
/ 17 января 2020

Docker кэширует результаты отдельных шагов в Dockerfile. Это довольно все или ничего; если предыдущий шаг был кэширован, и вы делаете шаг, идентичный тому, что вы делали раньше, то docker build будет использовать кэшированный результат, но если он не идентичен, из кеша с этого момента вообще ничего не будет вкл.

В частности, на этапе сборки, когда вы

COPY . ./

делают кеш недействительным, если любой файл изменяется; затем, когда вы запустите yarn install на следующей строке, это почти всегда будет повторяться. На данный момент вам нужны только файлы метаданных пакета, так что вы можете вместо этого

COPY package.json yarn.lock ./
RUN yarn install

, и это не повторится при перестроениях.


Если размер изображения имеет значение, Вы также можете yarn install --production, чтобы не устанавливать devDependencies из вашего package.json. При обычном использовании вы можете сделать это в вашем окончательном образе среды выполнения, но в вашем случае вам понадобится C набор инструментов для построения этих зависимостей. Это означает, что в Dockerfile у вас будет три этапа:

  1. на основе узла, плюс набор инструментов C, который устанавливает все зависимости и запускает yarn build
  2. на основе на узле, плюс C набор инструментов, который запускает только yarn install --production
  3. на основе узла, который только COPY --from=... создает приложение на первом этапе и время выполнения node_modules на втором этапе, и затем имеет обычные EXPOSE и CMD метаданные
0 голосов
/ 17 января 2020

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

Перед запуском yarn build вам нужно только скопировать пакет *. json, а не все в контексте (имейте в виду, что ваш локальный контекст уже содержит node_modules но ваш удаленный сервер этого не делает).

Когда вы делаете следующее:

COPY --from=0 /app/node_modules ./node_modules
COPY . .

вы фактически перезаписываете папку node_modules тем, что у вас есть в вашем контексте, поэтому в основном ваши предыдущие шаги были бесполезны ,

Я предлагаю вам попробовать что-то вроде этого:

FROM mhart/alpine-node:10
RUN apk add --no-cache udev
WORKDIR /app

COPY package*.json ./
RUN yarn install

COPY index.js ./
# also copy here any other project files if any

RUN yarn run build

RUN mkdir ./logs/

ENV NODE_ENV production

CMD ["node", "./dist/index.js"]
...