Работа с образами в 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'"
},
...
