Skip to content

Commit

Permalink
Analyse layers /w filesystem diff
Browse files Browse the repository at this point in the history
  • Loading branch information
mvorisek committed Nov 26, 2023
1 parent 64cd18a commit 16d5102
Show file tree
Hide file tree
Showing 39 changed files with 921 additions and 858 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ jobs:
run: >-
docker history --no-trunc --format "table {{.CreatedSince}}\t{{.Size}}\t{{.CreatedBy}}" $(docker inspect --format="{{.Id}}" "ci-target:basic")
&& docker images --no-trunc --format "Total size: {{.Size}}\t{{.ID}}" | grep $(docker inspect --format="{{.Id}}" "ci-target:basic") | cut -f1
&& php analyse-layers.php "ci-target:basic" "ci-target:base"
- name: 'Target "node" - build'
# try to build twice to suppress random network issues with Github Actions
Expand All @@ -663,6 +664,7 @@ jobs:
run: >-
docker history --no-trunc --format "table {{.CreatedSince}}\t{{.Size}}\t{{.CreatedBy}}" $(docker inspect --format="{{.Id}}" "ci-target:node")
&& docker images --no-trunc --format "Total size: {{.Size}}\t{{.ID}}" | grep $(docker inspect --format="{{.Id}}" "ci-target:node") | cut -f1
&& php analyse-layers.php "ci-target:node" "ci-target:base"
- name: 'Target "selenium" - build'
# try to build twice to suppress random network issues with Github Actions
Expand All @@ -682,6 +684,7 @@ jobs:
run: >-
docker history --no-trunc --format "table {{.CreatedSince}}\t{{.Size}}\t{{.CreatedBy}}" $(docker inspect --format="{{.Id}}" "ci-target:selenium")
&& docker images --no-trunc --format "Total size: {{.Size}}\t{{.ID}}" | grep $(docker inspect --format="{{.Id}}" "ci-target:selenium") | cut -f1
&& php analyse-layers.php "ci-target:selenium" "ci-target:node"
- name: Login to registry
uses: docker/login-action@v2
Expand Down
130 changes: 130 additions & 0 deletions analyse-layers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

declare(strict_types=1);

function myexec(string $cmd): string
{
exec($cmd, $lines, $resCode);
if ($resCode !== 0) {
throw new \Exception(
'Non-zero exit' . "\n"
. 'code: ' . $resCode . "\n"
. 'cmd: ' . $cmd . "\n"
. 'output:' . implode("\n", $lines) . "\n"
);
}

return implode("\n", $lines);
}

class FileEntry
{
/** @var int */
public $size;
/** @var int concat(device_id, inode_id, hash) */
public $inode;
/** @var int */
public $hash;
}

$targetImageId = myexec('docker inspect --format="{{.Id}}" "' . $argv[1] . '"');

$baseImageId = null;
if (count($argv) > 2) {
$baseImageId = myexec('docker inspect --format="{{.Id}}" "' . $argv[2] . '"');
}

$out = myexec('docker history --no-trunc --format "table {{.ID}}\t{{.CreatedBy}}" ' . $targetImageId);

$layers = [];
foreach (array_reverse(array_slice(explode("\n", $out), 1 /* first line is header */)) as $l) {
[$lId, $lCmd] = preg_split('~\t| {2,}~', $l, 2);
if ($lId === '<missing>') {
continue;
} elseif ($lId === $baseImageId) {
$layers = [];
$baseImageId = null;
}

$layers[] = [$lId, $lCmd];
}

// analyse filesystem diff between each layer
foreach (array_slice($layers, 1 /* skip one image for prev */, null, true) as $k => $lArr) {
$lArrPrev = $layers[$k - 1];
echo '--> analysing diff between:' . "\n";
echo '--> ' . implode(' ', $lArrPrev) . "\n";
echo '--> ' . implode(' ', $lArr) . "\n";

$getImageFilesFx = function (string $imageId): array {
$out = myexec('docker run "' . $imageId . '" /bin/sh -c \'find / -xdev -type f -exec du -b {} \; -exec stat -c %D_%i {} \; -exec sha256sum {} \;\'');
$res = [];
foreach (array_chunk(explode("\n", $out), 3) as [$l, $lDevInode, $lHash]) {
[$size, $path] = preg_split('~\t| {2,}~', $l, 2);
$hash = explode(' ', $lHash, 2)[0];
$fileEntry = new FileEntry();
$fileEntry->size = $size + 0;
$fileEntry->inode = $lDevInode . '_' . $hash;
$fileEntry->hash = $hash;
$res[$path] = $fileEntry;
}
ksort($res);

return $res;
};
$fsPrev = $getImageFilesFx($lArrPrev[0]);
$fsCurr = $getImageFilesFx($lArr[0]);

// calc dedup, prev must be always first
$psByInode = [];
$psByHash = [];
foreach ($fsPrev as $p => $f) {
$psByInode[$f->inode][] = $p;
$psByHash[$f->hash][] = $p;
}
foreach ($fsCurr as $p => $f) {
if (!isset($fsPrev[$p]) || $f->inode !== $fsPrev[$p]->inode) {
$psByInode[$f->inode][] = $p;
}
if (!isset($fsPrev[$p]) || $f->hash !== $fsPrev[$p]->hash) {
$psByHash[$f->hash][] = $p;
}
}

// merge all seen paths and sort by largest size
$pSorted = array_unique(array_merge(array_keys($fsPrev), array_keys($fsCurr)));
usort($pSorted, function (string $pA, string $pB) use ($fsPrev, $fsCurr): int {
$aSize = max(isset($fsCurr[$pA]) ? $fsCurr[$pA]->size : 0, isset($fsPrev[$pA]) ? $fsPrev[$pA]->size : 0);
$bSize = max(isset($fsCurr[$pB]) ? $fsCurr[$pB]->size : 0, isset($fsPrev[$pB]) ? $fsPrev[$pB]->size : 0);

return $bSize <=> $aSize;
});

// show removed/added files
foreach ($pSorted as $p) {
if (isset($fsPrev[$p]) && isset($fsCurr[$p]) && $fsPrev[$p]->inode === $fsCurr[$p]->inode
|| in_array($p, ['/.dockerenv', '/etc/hostname', '/etc/hosts', '/etc/resolv.conf'], true)) {
continue;
}

foreach ([1 => $fsPrev, 0 => $fsCurr] as $isPrev => $fs) {
if (!isset($fs[$p])) {
continue;
}
$f = $fs[$p];

echo $isPrev ? '-' : '+';
if ($p !== reset($psByInode[$f->inode])) {
echo '(deduped by inode from ' . reset($psByInode[$f->inode]) . ')';
} else {
if ($f->size !== 0 && $p !== reset($psByHash[$f->hash])) {
echo '(deduped by hash from ' . reset($psByHash[$f->hash]) . ')';
}
echo number_format($f->size / 1000, 3, '.', ' ') . 'K';
}
echo ' ' . $p . "\n";
}
}

echo "\n\n";
}
46 changes: 22 additions & 24 deletions data/7.4-alpine/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,32 @@ RUN apk update \

# install common PHP extensions
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
RUN IPE_ICU_EN_ONLY=1 install-php-extensions \
bcmath \
exif \
gd \
gmp \
igbinary \
imagick \
imap \
intl \
mysqli \
oci8 \
opcache \
pcntl \
pdo_mysql \
pdo_oci \
pdo_pgsql \
pdo_sqlsrv \
redis \
sockets \
tidy \
xdebug \
xsl \
zip \
RUN IPE_ICU_EN_ONLY=1 install-php-extensions bcmath
RUN IPE_ICU_EN_ONLY=1 install-php-extensions exif
RUN IPE_ICU_EN_ONLY=1 install-php-extensions gd
RUN IPE_ICU_EN_ONLY=1 install-php-extensions gmp
RUN IPE_ICU_EN_ONLY=1 install-php-extensions igbinary
RUN IPE_ICU_EN_ONLY=1 install-php-extensions imagick \
# remove Ghostscript binary, reduce Alpine image size by 23 MB, remove once https://gitlab.alpinelinux.org/alpine/aports/-/issues/13415 is fixed
&& rm /usr/bin/gs \
&& rm /usr/bin/gs
RUN IPE_ICU_EN_ONLY=1 install-php-extensions imap
RUN IPE_ICU_EN_ONLY=1 install-php-extensions intl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions mysqli
RUN IPE_ICU_EN_ONLY=1 install-php-extensions opcache
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pcntl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_mysql
RUN IPE_ICU_EN_ONLY=1 install-php-extensions oci8 pdo_oci \
# pack Oracle Instant Client libs, reduce image size by 85 MB
&& rm /usr/lib/oracle/*/client64/lib/*.jar && tar -czvf /usr/lib/oracle-pack.tar.gz -C / /usr/lib/oracle /usr/local/etc/php/conf.d/docker-php-ext-pdo_oci.ini /usr/local/etc/php/conf.d/docker-php-ext-oci8.ini && rm -r /usr/lib/oracle/* /usr/local/etc/php/conf.d/docker-php-ext-pdo_oci.ini /usr/local/etc/php/conf.d/docker-php-ext-oci8.ini && mv /usr/lib/oracle-pack.tar.gz /usr/lib/oracle/pack.tar.gz \
&& { echo '#!/bin/sh'; echo 'if [ ! -d /usr/lib/oracle/*/client64 ]; then'; echo ' tar -xzf /usr/lib/oracle/pack.tar.gz -C / && rm /usr/lib/oracle/pack.tar.gz'; echo 'fi'; } > /usr/lib/oracle/setup.sh && chmod +x /usr/lib/oracle/setup.sh
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_pgsql
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_sqlsrv
RUN IPE_ICU_EN_ONLY=1 install-php-extensions redis
RUN IPE_ICU_EN_ONLY=1 install-php-extensions sockets
RUN IPE_ICU_EN_ONLY=1 install-php-extensions tidy
RUN IPE_ICU_EN_ONLY=1 install-php-extensions xdebug
RUN IPE_ICU_EN_ONLY=1 install-php-extensions xsl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions zip

# install Composer
RUN install-php-extensions @composer
Expand Down
44 changes: 21 additions & 23 deletions data/7.4-debian/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,30 @@ RUN (seq 1 8 | xargs -I{} mkdir -p /usr/share/man/man{}) \

# install common PHP extensions
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
RUN IPE_ICU_EN_ONLY=1 install-php-extensions \
bcmath \
exif \
gd \
gmp \
igbinary \
imagick \
imap \
intl \
mysqli \
oci8 \
opcache \
pcntl \
pdo_mysql \
pdo_oci \
pdo_pgsql \
pdo_sqlsrv \
redis \
sockets \
tidy \
xdebug \
xsl \
zip \
RUN IPE_ICU_EN_ONLY=1 install-php-extensions bcmath
RUN IPE_ICU_EN_ONLY=1 install-php-extensions exif
RUN IPE_ICU_EN_ONLY=1 install-php-extensions gd
RUN IPE_ICU_EN_ONLY=1 install-php-extensions gmp
RUN IPE_ICU_EN_ONLY=1 install-php-extensions igbinary
RUN IPE_ICU_EN_ONLY=1 install-php-extensions imagick
RUN IPE_ICU_EN_ONLY=1 install-php-extensions imap
RUN IPE_ICU_EN_ONLY=1 install-php-extensions intl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions mysqli
RUN IPE_ICU_EN_ONLY=1 install-php-extensions opcache
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pcntl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_mysql
RUN IPE_ICU_EN_ONLY=1 install-php-extensions oci8 pdo_oci \
# pack Oracle Instant Client libs, reduce image size by 85 MB
&& rm /usr/lib/oracle/*/client64/lib/*.jar && tar -czvf /usr/lib/oracle-pack.tar.gz -C / /usr/lib/oracle /usr/local/etc/php/conf.d/docker-php-ext-pdo_oci.ini /usr/local/etc/php/conf.d/docker-php-ext-oci8.ini && rm -r /usr/lib/oracle/* /usr/local/etc/php/conf.d/docker-php-ext-pdo_oci.ini /usr/local/etc/php/conf.d/docker-php-ext-oci8.ini && mv /usr/lib/oracle-pack.tar.gz /usr/lib/oracle/pack.tar.gz \
&& { echo '#!/bin/sh'; echo 'if [ ! -d /usr/lib/oracle/*/client64 ]; then'; echo ' tar -xzf /usr/lib/oracle/pack.tar.gz -C / && rm /usr/lib/oracle/pack.tar.gz'; echo 'fi'; } > /usr/lib/oracle/setup.sh && chmod +x /usr/lib/oracle/setup.sh
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_pgsql
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_sqlsrv
RUN IPE_ICU_EN_ONLY=1 install-php-extensions redis
RUN IPE_ICU_EN_ONLY=1 install-php-extensions sockets
RUN IPE_ICU_EN_ONLY=1 install-php-extensions tidy
RUN IPE_ICU_EN_ONLY=1 install-php-extensions xdebug
RUN IPE_ICU_EN_ONLY=1 install-php-extensions xsl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions zip

# install Composer
RUN install-php-extensions @composer
Expand Down
46 changes: 22 additions & 24 deletions data/7.4-debug-alpine/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,32 @@ RUN apk update \

# install common PHP extensions
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
RUN IPE_ICU_EN_ONLY=1 install-php-extensions \
bcmath \
exif \
gd \
gmp \
igbinary \
imagick \
imap \
intl \
mysqli \
oci8 \
opcache \
pcntl \
pdo_mysql \
pdo_oci \
pdo_pgsql \
pdo_sqlsrv \
redis \
sockets \
tidy \
xdebug \
xsl \
zip \
RUN IPE_ICU_EN_ONLY=1 install-php-extensions bcmath
RUN IPE_ICU_EN_ONLY=1 install-php-extensions exif
RUN IPE_ICU_EN_ONLY=1 install-php-extensions gd
RUN IPE_ICU_EN_ONLY=1 install-php-extensions gmp
RUN IPE_ICU_EN_ONLY=1 install-php-extensions igbinary
RUN IPE_ICU_EN_ONLY=1 install-php-extensions imagick \
# remove Ghostscript binary, reduce Alpine image size by 23 MB, remove once https://gitlab.alpinelinux.org/alpine/aports/-/issues/13415 is fixed
&& rm /usr/bin/gs \
&& rm /usr/bin/gs
RUN IPE_ICU_EN_ONLY=1 install-php-extensions imap
RUN IPE_ICU_EN_ONLY=1 install-php-extensions intl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions mysqli
RUN IPE_ICU_EN_ONLY=1 install-php-extensions opcache
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pcntl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_mysql
RUN IPE_ICU_EN_ONLY=1 install-php-extensions oci8 pdo_oci \
# pack Oracle Instant Client libs, reduce image size by 85 MB
&& rm /usr/lib/oracle/*/client64/lib/*.jar && tar -czvf /usr/lib/oracle-pack.tar.gz -C / /usr/lib/oracle /usr/local/etc/php/conf.d/docker-php-ext-pdo_oci.ini /usr/local/etc/php/conf.d/docker-php-ext-oci8.ini && rm -r /usr/lib/oracle/* /usr/local/etc/php/conf.d/docker-php-ext-pdo_oci.ini /usr/local/etc/php/conf.d/docker-php-ext-oci8.ini && mv /usr/lib/oracle-pack.tar.gz /usr/lib/oracle/pack.tar.gz \
&& { echo '#!/bin/sh'; echo 'if [ ! -d /usr/lib/oracle/*/client64 ]; then'; echo ' tar -xzf /usr/lib/oracle/pack.tar.gz -C / && rm /usr/lib/oracle/pack.tar.gz'; echo 'fi'; } > /usr/lib/oracle/setup.sh && chmod +x /usr/lib/oracle/setup.sh
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_pgsql
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_sqlsrv
RUN IPE_ICU_EN_ONLY=1 install-php-extensions redis
RUN IPE_ICU_EN_ONLY=1 install-php-extensions sockets
RUN IPE_ICU_EN_ONLY=1 install-php-extensions tidy
RUN IPE_ICU_EN_ONLY=1 install-php-extensions xdebug
RUN IPE_ICU_EN_ONLY=1 install-php-extensions xsl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions zip

# install Composer
RUN install-php-extensions @composer
Expand Down
44 changes: 21 additions & 23 deletions data/7.4-debug-debian/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,30 @@ RUN (seq 1 8 | xargs -I{} mkdir -p /usr/share/man/man{}) \

# install common PHP extensions
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
RUN IPE_ICU_EN_ONLY=1 install-php-extensions \
bcmath \
exif \
gd \
gmp \
igbinary \
imagick \
imap \
intl \
mysqli \
oci8 \
opcache \
pcntl \
pdo_mysql \
pdo_oci \
pdo_pgsql \
pdo_sqlsrv \
redis \
sockets \
tidy \
xdebug \
xsl \
zip \
RUN IPE_ICU_EN_ONLY=1 install-php-extensions bcmath
RUN IPE_ICU_EN_ONLY=1 install-php-extensions exif
RUN IPE_ICU_EN_ONLY=1 install-php-extensions gd
RUN IPE_ICU_EN_ONLY=1 install-php-extensions gmp
RUN IPE_ICU_EN_ONLY=1 install-php-extensions igbinary
RUN IPE_ICU_EN_ONLY=1 install-php-extensions imagick
RUN IPE_ICU_EN_ONLY=1 install-php-extensions imap
RUN IPE_ICU_EN_ONLY=1 install-php-extensions intl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions mysqli
RUN IPE_ICU_EN_ONLY=1 install-php-extensions opcache
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pcntl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_mysql
RUN IPE_ICU_EN_ONLY=1 install-php-extensions oci8 pdo_oci \
# pack Oracle Instant Client libs, reduce image size by 85 MB
&& rm /usr/lib/oracle/*/client64/lib/*.jar && tar -czvf /usr/lib/oracle-pack.tar.gz -C / /usr/lib/oracle /usr/local/etc/php/conf.d/docker-php-ext-pdo_oci.ini /usr/local/etc/php/conf.d/docker-php-ext-oci8.ini && rm -r /usr/lib/oracle/* /usr/local/etc/php/conf.d/docker-php-ext-pdo_oci.ini /usr/local/etc/php/conf.d/docker-php-ext-oci8.ini && mv /usr/lib/oracle-pack.tar.gz /usr/lib/oracle/pack.tar.gz \
&& { echo '#!/bin/sh'; echo 'if [ ! -d /usr/lib/oracle/*/client64 ]; then'; echo ' tar -xzf /usr/lib/oracle/pack.tar.gz -C / && rm /usr/lib/oracle/pack.tar.gz'; echo 'fi'; } > /usr/lib/oracle/setup.sh && chmod +x /usr/lib/oracle/setup.sh
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_pgsql
RUN IPE_ICU_EN_ONLY=1 install-php-extensions pdo_sqlsrv
RUN IPE_ICU_EN_ONLY=1 install-php-extensions redis
RUN IPE_ICU_EN_ONLY=1 install-php-extensions sockets
RUN IPE_ICU_EN_ONLY=1 install-php-extensions tidy
RUN IPE_ICU_EN_ONLY=1 install-php-extensions xdebug
RUN IPE_ICU_EN_ONLY=1 install-php-extensions xsl
RUN IPE_ICU_EN_ONLY=1 install-php-extensions zip

# install Composer
RUN install-php-extensions @composer
Expand Down
Loading

0 comments on commit 16d5102

Please sign in to comment.