Пост

Работа с образами в Docker. Часть 2

Анализ Dockerfile и файлов образов

Приведу ряд полезных инструментов для работы с образами Docker как на этапе подготовки, так и после сборки.

⚒️ Hadolint

Hadolint - статический анализатор или линтер для Dockerfile. Поможет следовать best practices при построении докер файлов. Содержит множество правил и рекомендаций во избежание распространенных ошибок, представляя их в виде предупреждений. Можно собрать самостоятельно или воспользоваться релизными сборками под разные платформы в виде исполняемого файла. Также существует одноименное расширение для vscode, позволяющее в реальном времени контролировать правильность написания Dockerfile с выводом подсказок.

В качестве примера прогоним через hadolint представленный в предыдущей заметке файл сборки python сервиса

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM python:3.10 AS builder
COPY requirements.txt .

RUN pip install --user -r requirements.txt

FROM python:3.10-slim

COPY --from=builder /root/.local /root/.local
COPY . /myapp

WORKDIR /myapp

ENV PATH=/root/.local/bin:$PATH

CMD ["python", "-u", "-m", "src"]
1
2
3
4
hadolint Dockerfile

Dockerfile:2 DL3045 warning: `COPY` to a relative destination without `WORKDIR` set.
Dockerfile:4 DL3042 warning: Avoid use of cache directory with pip. Use `pip install --no-cache-dir <package>`

⚒️ Syft

Syft - утилита для генерации SBOMs (Software Bill of Materials) - составляет перечень зависимостей, библиотек и исполняемых файлов с детализацией путей, типов, версий и принадлежности к слою сформированного образа. Полезный источник информации как для первоначальной оценки наполнения полученного образа, так и для последующего аудита в том числе с точки зрения безопасности.

Собираем самостоятельно или забираем актуальный исполняемый файл под целевую платформу.

1
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

Формат представления и уровень детализации задаются параметрами запуска. Применим на все том же образе python сервиса с параметрами по умолчанию.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# syft <image id>
syft f47f0179743e
...
   ├── ✔ Packages                        [135 packages]
   ├── ✔ File digests                    [3,283 files]
   ├── ✔ File metadata                   [3,283 locations]
   └── ✔ Executables                     [814 executables]
adduser                 3.134                  deb
apt                     2.6.1                  deb
base-files              12.4+deb12u8           deb
base-passwd             3.6.1                  deb
bash                    5.2.15-2+b7            deb
ca-certificates         20230311               deb
certifi                 2024.6.2               python
charset-normalizer      3.3.2                  python
coreutils               9.1-1                  deb
cryptg                  0.4.0                  python
diffutils               1:3.8-4                deb
dpkg                    1.21.22                deb
findutils               4.9.0-4                deb
gcc-12-base             12.2.0-14              deb
gpgv                    2.2.40-1.1             deb
grep                    3.8-5                  deb
gzip                    1.12-1                 deb
hostname                3.23+nmu1              deb
idna                    3.7                    python
jmespath                1.0.1                  python
...

⚒️ Dive

Популярное приложение для анализа образов docker - dive. Незаменимая утилита для отладки и проверки корректности наполнения и сборки образов по слоям с детальным отображением происходящего на каждом этапе, исполняемых команд и формируемого контента, а также для оценки эффективности используемого дискового пространства получаемым результатом.

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

1
dive <image id>

⚒️ SecretScanner

Аналог уже опробованного поисковика утечек секретов в глубинах репозитория Gitleaks в контексте образов - SecretScanner. Ищет, структурирует и записывает забытые конфиденциальные данные в собранном docker образе по более чем 140 заготовленным правилам и типам.

Варианты конфигураций можно посмотреть в документации. Запускается прямо из docker, поэтому сразу пробуем:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
docker run -it --rm --name=deepfence-secretscanner -v $(pwd):/home/deepfence/output -v /var/run/docker.sock:/var/run/docker.sock deepfenceio/deepfence_secret_scanner:latest -image-name <target image name> --output json

summary:
  total=15 high=3 medium=3 low=9
{
  "Timestamp": "2024-12-18T05:47:41.169731493Z",
  "Image Name": "my-image-name",
  "Image ID": "blobs/sha256/f47f0179743ed8e0fd23183857c06abc17caf830075cb20c041551909bb19557",
  "Container ID": "",
  "Secrets": [
    {
      "Image Layer ID": "blobs/sha256/c3548211b8264f8bfa47a6727043a64f1791b82ac965a284a7ea187e971a95e2",
      "Matched Rule ID": 4,
      "Matched Rule Name": "Potential cryptographic key bundle",
      "Matched Part": "extension",
      "String to Match": ".asc",
      "Severity": "low",
      "Severity Score": 2.5,
      "Relative Starting Index of Match in Displayed Substring": 0,
      "Relative Ending Index of Match in Displayed Substring": 4,
      "Full File Name": "etc/apt/trusted.gpg.d/debian-archive-bookworm-automatic.asc",
      "Matched Contents": ".asc"
    },
    {
      "Image Layer ID": "blobs/sha256/e5d8b619f2cea803c9ccd7dcd6bba9c613f44c1d3c2750e1c21fc92884382fe2",
      "Matched Rule ID": 110,
      "Matched Rule Name": "Username and password in URI",
      "Matched Part": "contents",
      "Signature to Match": "([\\w+]{1,24})(://)([^$\u003c]{1})([^\\s\";]{1,}):([^$\u003c]{1})([^\\s\";/]{1,})@[-a>
      "Severity": "high",
      "Severity Score": 7.56,
      "Starting Index of Match in Original Content": 4862,
      "Relative Starting Index of Match in Displayed Substring": 14,
      "Relative Ending Index of Match in Displayed Substring": 46,
      "Full File Name": "usr/local/lib/python3.10/site-packages/pip/_vendor/urllib3/util/url.py",
      "Matched Contents": "\n            'http://username:password@host.com:80/path?query#fragment'"
    },
...
Больше полезной информации в Telegram-канале