С появлением Docker стали бурно развиваться контейнеры. Одним из главных преимуществ по сравнению с виртуальными машинами была скорость запуска и размер контейнеров, а также экономия ресурсов хостовой машины. Разработчики активно начали развивать идею с размером образов. Насколько маленьким он может быть?
Сначала по привычке использовали образы на основе традиционных Linux систем - Debian, Centos и т.д. Потом появился очень маленький Alpine, затем пустой образ scratch. Сейчас дошли до distroless образов, где вообще нет привязки к какой-то конкретной системе. Насколько я могу понять архитектуру подобных образов, там только ядро Linux, а из user space вырезано вообще всё (пакетный менеджер, оболочки и т.д.), что не требуется для запуска приложения.
В погоне за минимализмом как-то стали забывать о производительности. Я встречал информацию, что некоторые приложения в образах Alpine работают заметно медленнее. Разница с типовым образом на Debian может достигать 20-30%. А ещё все эти минимальные образы очень неудобно отлаживать. В итоге экономия места оборачивается повышенной тратой рабочего времени разработчиков и поддержки.
Насколько я понимаю, вся эта тема с минимализмом актуальна на очень больших инфраструктурах с сотнями серверов и тысячами контейнеров. Первые distroless образы анонсировал Google. У него есть несколько базовых образов для python, java, nodejs. Сейчас эту тему подхватили и начали развивать. Например, есть большая коллекция готовых distroless образов у chainguard. Там не только среда исполнения для различных языков, но и distroless образы nginx, php, posgresql и т.д.
💡Я к чему всё это написал. Если у вас нет большой необходимости в очень маленьких образах, то не используйте всех этих кастратиков. Постоянно приходится пользоваться готовыми образами. Очень не нравится, когда внутри ничего нет. Экономия на спичках оборачивается потом лишними хлопотами в отладке.
#docker #devops
Сначала по привычке использовали образы на основе традиционных Linux систем - Debian, Centos и т.д. Потом появился очень маленький Alpine, затем пустой образ scratch. Сейчас дошли до distroless образов, где вообще нет привязки к какой-то конкретной системе. Насколько я могу понять архитектуру подобных образов, там только ядро Linux, а из user space вырезано вообще всё (пакетный менеджер, оболочки и т.д.), что не требуется для запуска приложения.
В погоне за минимализмом как-то стали забывать о производительности. Я встречал информацию, что некоторые приложения в образах Alpine работают заметно медленнее. Разница с типовым образом на Debian может достигать 20-30%. А ещё все эти минимальные образы очень неудобно отлаживать. В итоге экономия места оборачивается повышенной тратой рабочего времени разработчиков и поддержки.
Насколько я понимаю, вся эта тема с минимализмом актуальна на очень больших инфраструктурах с сотнями серверов и тысячами контейнеров. Первые distroless образы анонсировал Google. У него есть несколько базовых образов для python, java, nodejs. Сейчас эту тему подхватили и начали развивать. Например, есть большая коллекция готовых distroless образов у chainguard. Там не только среда исполнения для различных языков, но и distroless образы nginx, php, posgresql и т.д.
💡Я к чему всё это написал. Если у вас нет большой необходимости в очень маленьких образах, то не используйте всех этих кастратиков. Постоянно приходится пользоваться готовыми образами. Очень не нравится, когда внутри ничего нет. Экономия на спичках оборачивается потом лишними хлопотами в отладке.
#docker #devops
Для быстрой и простой проверки Docker образов на уязвимости существует популярный Open Source инструмент — Trivy. Я покажу на примере, как им пользоваться. Получится готовая мини инструкция по установке и использованию.
Установить Trivy можно разными способами: из репозитория с пакетами, собрать с помощью Nix, воспользоваться bash скриптом, запустить в Docker. Все способы описаны в документации. Я установлю в Debian из репозитория.
Теперь скачиваем любой образ и проверяем его на уязвимости. Покажу на примере заведомо уязвимого образа.
Результат проверки будет в файле nginx.1.21.6.json, что удобно для последующего автоматического анализа. Можно наглядно посмотреть результат в консоли:
Trivy отлично подходит для автоматической проверки образов перед их отправкой в registry. Да и просто для быстрого анализа созданного или скачанного образа. Помимо проверки образов, он умеет сканировать git репозитории, файлы с зависимостями (Gemfile.lock, Pipfile.lock, composer.lock, package-lock.json, yarn.lock, Cargo.lock).
Следующей будет заметка с описанием автоматического исправления уязвимостей в образах на основе отчётов trivy.
⇨ Сайт / Исходники
#security #docker #devops
Установить Trivy можно разными способами: из репозитория с пакетами, собрать с помощью Nix, воспользоваться bash скриптом, запустить в Docker. Все способы описаны в документации. Я установлю в Debian из репозитория.
# apt install wget apt-transport-https gnupg lsb-release
# wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key \
| gpg --dearmor | tee /usr/share/keyrings/trivy.gpg > /dev/null
# echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] \
https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" \
| tee -a /etc/apt/sources.list.d/trivy.list
# apt update
# apt install trivy
Теперь скачиваем любой образ и проверяем его на уязвимости. Покажу на примере заведомо уязвимого образа.
# docker pull mcr.microsoft.com/oss/nginx/nginx:1.21.6
# trivy image --vuln-type os --ignore-unfixed \
-f json -o nginx.1.21.6.json mcr.microsoft.com/oss/nginx/nginx:1.21.6
Результат проверки будет в файле nginx.1.21.6.json, что удобно для последующего автоматического анализа. Можно наглядно посмотреть результат в консоли:
# trivy image --vuln-type os \
--ignore-unfixed mcr.microsoft.com/oss/nginx/nginx:1.21.6
Trivy отлично подходит для автоматической проверки образов перед их отправкой в registry. Да и просто для быстрого анализа созданного или скачанного образа. Помимо проверки образов, он умеет сканировать git репозитории, файлы с зависимостями (Gemfile.lock, Pipfile.lock, composer.lock, package-lock.json, yarn.lock, Cargo.lock).
Следующей будет заметка с описанием автоматического исправления уязвимостей в образах на основе отчётов trivy.
⇨ Сайт / Исходники
#security #docker #devops
Продолжаю тему безопасности Docker контейнеров. С помощью Trivy можно проверить образ на уязвимости. Теперь расскажу, как их автоматически исправить. Для этого нам понадобится Copacetic. Он будет брать информацию из отчётов Trivy. Для запуска copa cli нам нужно:
1️⃣ Установить Go v1.19 или новее.
2️⃣ Собрать и установить runc.
3️⃣ Установить buildkit v0.10.5 или новее.
4️⃣ Собрать и установить copa.
Я кратко без пояснений покажу как это сделать на примере Debian. Все подробности есть в самих репозиториях программ.
✅ Устанавливаем GO.
✅ Устанавливаем runc.
✅ Устанавливаем buildkit.
✅ Устанавливаем copacetic.
Все необходимые компоненты установили. Теперь патчим уязвимый контейнер. Для этого предварительно в фоне запускаем buildkitd:
Copa не перезаписывает старый образ, а создаёт новый с тэгом patched. Можете сразу его посмотреть и проверить:
Ну и убедиться, что он нормально запускается:
Copa, используя информацию о версиях пакетов из отчёта Trivy, обновила все уязвимые системные пакеты в образе. Можете проверить уже пропатченный образ:
Я показал набор софта и пример обновления контейнера. Получилась готовая инструкция, которую я лично проверил. Используя эту информацию и информацию из репозиториев, можно настроить подобные обновления для своей среды.
⇨ Исходники Copacetic
#security #docker #devops
1️⃣ Установить Go v1.19 или новее.
2️⃣ Собрать и установить runc.
3️⃣ Установить buildkit v0.10.5 или новее.
4️⃣ Собрать и установить copa.
Я кратко без пояснений покажу как это сделать на примере Debian. Все подробности есть в самих репозиториях программ.
✅ Устанавливаем GO.
# wget https://go.dev/dl/go1.19.5.linux-amd64.tar.gz
# tar -C /usr/local -xzf go1.19.5.linux-amd64.tar.gz
# ln -s /usr/local/go/bin/go /usr/bin/go
# go version
✅ Устанавливаем runc.
# apt install make git gcc build-essential pkgconf libtool libsystemd-dev \
libprotobuf-c-dev libcap-dev libseccomp-dev libyajl-dev libgcrypt20-dev \
go-md2man autoconf python3 automake
# git clone https://github.com/opencontainers/runc
# cd runc
# make
# make install
✅ Устанавливаем buildkit.
# wget https://github.com/moby/buildkit/releases/download/v0.11.0/buildkit-v0.11.0.linux-amd64.tar.gz
# tar -C /usr -xzf buildkit-v0.11.0.linux-amd64.tar.gz
✅ Устанавливаем copacetic.
# git clone https://github.com/project-copacetic/copacetic
# cd copacetic
# make
# mv dist/linux_amd64/release/copa /usr/local/bin/
Все необходимые компоненты установили. Теперь патчим уязвимый контейнер. Для этого предварительно в фоне запускаем buildkitd:
# buildkitd &
# copa patch -i mcr.microsoft.com/oss/nginx/nginx:1.21.6 -r nginx.1.21.6.json -t 1.21.6-patched
Copa не перезаписывает старый образ, а создаёт новый с тэгом patched. Можете сразу его посмотреть и проверить:
# docker images
# docker history mcr.microsoft.com/oss/nginx/nginx:1.21.6-patched
Ну и убедиться, что он нормально запускается:
# docker run -it --rm --name nginx-test mcr.microsoft.com/oss/nginx/nginx:1.21.6-patched
Copa, используя информацию о версиях пакетов из отчёта Trivy, обновила все уязвимые системные пакеты в образе. Можете проверить уже пропатченный образ:
# trivy image --vuln-type os --ignore-unfixed mcr.microsoft.com/oss/nginx/nginx:1.21.6-patched
Я показал набор софта и пример обновления контейнера. Получилась готовая инструкция, которую я лично проверил. Используя эту информацию и информацию из репозиториев, можно настроить подобные обновления для своей среды.
⇨ Исходники Copacetic
#security #docker #devops
Существует популярный маркетплейс готовых приложений на базе Docker или образов виртуальных машин Bitnami. Это довольно известный сервис для тех, кто пользуется западными облачными провайдерами. Bitnami их партнёр и продаёт по подписке возможность работы со своими образами напрямую через сервисы провайдеров.
А все остальные могут совершенно бесплатно и свободно использовать их в своей работе, разворачивая в ручном режиме. Сразу возникает вопрос, а зачем это нужно? Всё просто. Bitnami берёт популярные наборы софта, пакует их в образы и поддерживает. То есть максимально быстро выпускает обновлённые версии образов.
Docker контейнеры Bitnami собраны на базе Debian. То есть это не кастратики по типу distroless, а более ли менее типовые контейнеры. Также они партнёры Docker, контейнеры подписаны доверенными цифровыми подписями. Докерфайлы всех контейнеров есть на github. То есть это контейнеры, которым можно доверять и использовать в продакшене.
Помимо контейнеров, есть готовые образы виртуальных машин в формате .ova для VirtualBox. Без проблем конвертируется в qcow2 или lvm с помощью qemu-img для запуска в Proxmox.
В каталоге много популярного софта. Так что если надо что-то посмотреть или потестировать, то можно смело брать и смотреть. В прод уже на своё усмотрение.
⇨ Сайт / Контейнеры / Виртуальные машины
#docker #devops
А все остальные могут совершенно бесплатно и свободно использовать их в своей работе, разворачивая в ручном режиме. Сразу возникает вопрос, а зачем это нужно? Всё просто. Bitnami берёт популярные наборы софта, пакует их в образы и поддерживает. То есть максимально быстро выпускает обновлённые версии образов.
Docker контейнеры Bitnami собраны на базе Debian. То есть это не кастратики по типу distroless, а более ли менее типовые контейнеры. Также они партнёры Docker, контейнеры подписаны доверенными цифровыми подписями. Докерфайлы всех контейнеров есть на github. То есть это контейнеры, которым можно доверять и использовать в продакшене.
Помимо контейнеров, есть готовые образы виртуальных машин в формате .ova для VirtualBox. Без проблем конвертируется в qcow2 или lvm с помощью qemu-img для запуска в Proxmox.
В каталоге много популярного софта. Так что если надо что-то посмотреть или потестировать, то можно смело брать и смотреть. В прод уже на своё усмотрение.
⇨ Сайт / Контейнеры / Виртуальные машины
#docker #devops
На днях в рассылке увидел любопытный инструмент, на который сразу обратил внимание. Название простое и неприметное — Task. Это утилита, написанная на Gо, которая умеет запускать задачи на основе конфигурации в формате yaml. Сейчас сразу на примерах покажу, как это работает, чтобы было понятно, для чего может быть нужно.
Сама программа это просто одиночный бинарник, который можно установить кучей способов, описанных в документации. Его даже в винде можно установить через winget.
Создаём файл с задачами Taskfile.yml:
Сохраняем и запускаем. Для начала посмотрим список задач:
Запустим первую задачу:
Или сразу обе, запустив task без параметров. Запустится задача default, которую мы описали в самом начале:
Идею, думаю, вы поняли. Это более простая и лёгкая в освоении замена утилиты make, которая используется в основном для сбора софта из исходников.
Первое, что приходит в голову, где утилита task может быть полезна, помимо непосредственно сборки из исходников, как замена make — сборка docker образов. Если у вас длинный RUN, который неудобно читать, поддерживать и отлаживать из-за его размера, то его можно заменить одной задачей с task. Это позволит упростить написание и поддержку, а также избавить от необходимости разбивать этот RUN на несколько частей, что порождает создание дополнительных слоёв.
Вместо того, чтобы описывать все свои действия в длиннющем RUN, оформите все свои шаги через task и запустите в RUN только его. Примерно так:
Скопировали бинарник + yaml с задачами и запустили их. А там они могут быть красиво оформлены по шагам. Писать и отлаживать эти задачи будет проще, чем сразу в Dockerfile. Для task написано расширение в Visual Studio Code.
Task поддерживает:
◽переходы по директориям
◽зависимости задач
◽импорт в Taskfile из другого Taskfile
◽динамические переменные
◽особенности OS, можно явно указать Taskfile_linux.yml или Taskfile_windows.yml
и многое другое. Всё это описано в документации.
Я немного поразбирался с Task. Он мне показался более простой заменой одиночных сценариев для ansible. Это когда вам не нужен полноценный playbook, а достаточно простого набора команд в едином файле, чтобы быстро его запустить и выполнить небольшой набор действий. Только в Task нет никаких модулей, только cmds.
#devops #script #docker
Сама программа это просто одиночный бинарник, который можно установить кучей способов, описанных в документации. Его даже в винде можно установить через winget.
Создаём файл с задачами Taskfile.yml:
version: "3"
tasks:
default:
desc: Run all tasks
cmds:
- task: task01
- task: task02
task01:
desc: Task 01
cmds:
- echo "Task 01"
task02:
desc: Task 02
cmds:
- echo "Task 02"
Сохраняем и запускаем. Для начала посмотрим список задач:
# task --list
task: Available tasks for this project:
* default: Run all tasks
* task01: Task 01
* task02: Task 02
Запустим первую задачу:
# task task01
task: [task01] echo "Task 01"
Или сразу обе, запустив task без параметров. Запустится задача default, которую мы описали в самом начале:
# task
task: [task01] echo "Task 01"
Task 01
task: [task02] echo "Task 02"
Task 02
Идею, думаю, вы поняли. Это более простая и лёгкая в освоении замена утилиты make, которая используется в основном для сбора софта из исходников.
Первое, что приходит в голову, где утилита task может быть полезна, помимо непосредственно сборки из исходников, как замена make — сборка docker образов. Если у вас длинный RUN, который неудобно читать, поддерживать и отлаживать из-за его размера, то его можно заменить одной задачей с task. Это позволит упростить написание и поддержку, а также избавить от необходимости разбивать этот RUN на несколько частей, что порождает создание дополнительных слоёв.
Вместо того, чтобы описывать все свои действия в длиннющем RUN, оформите все свои шаги через task и запустите в RUN только его. Примерно так:
COPY --from=bins /usr/bin/task /usr/local/bin/task
COPY tasks/Taskfile.yaml ./Taskfile.yaml
RUN task
Скопировали бинарник + yaml с задачами и запустили их. А там они могут быть красиво оформлены по шагам. Писать и отлаживать эти задачи будет проще, чем сразу в Dockerfile. Для task написано расширение в Visual Studio Code.
Task поддерживает:
◽переходы по директориям
◽зависимости задач
◽импорт в Taskfile из другого Taskfile
◽динамические переменные
◽особенности OS, можно явно указать Taskfile_linux.yml или Taskfile_windows.yml
и многое другое. Всё это описано в документации.
Я немного поразбирался с Task. Он мне показался более простой заменой одиночных сценариев для ansible. Это когда вам не нужен полноценный playbook, а достаточно простого набора команд в едином файле, чтобы быстро его запустить и выполнить небольшой набор действий. Только в Task нет никаких модулей, только cmds.
#devops #script #docker
Если вам приходится самому писать Dockerfiles для сборки образов, то рекомендую удобный и функциональный линтер для проверки синтаксиса и общих рекомендаций по оптимизации — Hadolint (Haskell Dockerfile Linter). Он проверяет Dockerfile на предмет использования общепринятых best practice, а shell код в
Hadolint можно использовать как локально, так и с помощью веб сервиса. Работает он чётко, все рекомендации по делу. Покажу несколько примеров. Простенький Dockerfile:
Казалось бы, что тут может быть не так. Проверяем рекомендации hadolint:
-:6 DL3007 warning: Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag
-:7 DL3018 warning: Pin versions in apk add. Instead of `apk add <package>` use `apk add <package>=<version>`
Вполне резонные замечания. Он не рекомендует использовать тэг latest и советует явно указывать версию софта в пакетном менеджере. В данном случае это скорее всего не критично. Но в общем случае за этим стоит следить, особенно за latest. Это разом может всё сломать в самый неподходящий момент.
Ещё небольшой пример:
Проверяем:
-:2 DL3008 warning: Pin versions in apt get install. Instead of `apt-get install <package>` use `apt-get install <package>=<version>`
-:2 DL3009 info: Delete the apt-get lists after installing something
-:2 DL3015 info: Avoid additional packages by specifying `--no-install-recommends`
Здесь та же рекомендация — указывать конкретную версию в установке пакетов. Дальше рекомендация подчистить за работой apt-get. Речь тут скорее всего про что-то типа в самом конце:
Ну и последняя рекомендация добавить ключ
То есть hadolint рекомендует привести
Как видите, все рекомендации адекватные, хотя каких-то явных ошибок тут нет.
#devops #docker
RUN
с помощью рекомендаций ShellCheck.Hadolint можно использовать как локально, так и с помощью веб сервиса. Работает он чётко, все рекомендации по делу. Покажу несколько примеров. Простенький Dockerfile:
FROM golang:1.7.3 AS build
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=build /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
Казалось бы, что тут может быть не так. Проверяем рекомендации hadolint:
# docker run --rm -i hadolint/hadolint < Dockerfile
-:6 DL3007 warning: Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag
-:7 DL3018 warning: Pin versions in apk add. Instead of `apk add <package>` use `apk add <package>=<version>`
Вполне резонные замечания. Он не рекомендует использовать тэг latest и советует явно указывать версию софта в пакетном менеджере. В данном случае это скорее всего не критично. Но в общем случае за этим стоит следить, особенно за latest. Это разом может всё сломать в самый неподходящий момент.
Ещё небольшой пример:
FROM debian:stable
RUN apt-get update && apt-get install -y --force-yes apache2
EXPOSE 80 443
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
Проверяем:
# docker run --rm -i hadolint/hadolint < Dockerfile
-:2 DL3008 warning: Pin versions in apt get install. Instead of `apt-get install <package>` use `apt-get install <package>=<version>`
-:2 DL3009 info: Delete the apt-get lists after installing something
-:2 DL3015 info: Avoid additional packages by specifying `--no-install-recommends`
Здесь та же рекомендация — указывать конкретную версию в установке пакетов. Дальше рекомендация подчистить за работой apt-get. Речь тут скорее всего про что-то типа в самом конце:
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
Ну и последняя рекомендация добавить ключ
--no-install-recommends
в apt-get, что тоже не лишено смысла. То есть hadolint рекомендует привести
RUN
к следующему виду:RUN apt-get update && \
apt-get install -y --force-yes --no-install-recommends apache2=2.4 \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
Как видите, все рекомендации адекватные, хотя каких-то явных ошибок тут нет.
#devops #docker
Разбираю ещё один документ от CIS с рекомендациями по настройке Docker. Напомню, что ранее я уже делал выжимки по настройке Nginx, MySQL, Apache, Debian 11. Используя эти руководства нелишним будет освежить свои инструкции и принять некоторую информацию к сведению.
📌 Директорию для информации
📌 У Docker высокие полномочия для доступа к хостовой системе. Следите за тем, чтобы в системной группе docker не было лишних пользователей.
📌 Для повышения безопасности рекомендуется настроить аудит службы docker, например с помощью auditd. Ставим службу:
Добавляем правило в
Перезапускаем службу:
Для повышенной безопасности можно настроить аудит и за файлами и директориями Docker, за конфигурационными файлами, за юнитом systemd, за сокетом. Это общая рекомендация для служб, которые работают с правами root.
📌 Разделяйте контейнеры по отдельным сетям для межконтейнерного взаимодействия. Если этого не делать, они будут взаимодействовать через общий системный бридж, который docker создаёт по умолчанию.
📌 Включите уровень логирования службы "info", добавив в файл конфигурации
Для повышения безопасности логи имеет смысл хранить где-то во вне. Их можно направить по syslog. Пример:
📌 Если используете подключение к службе Docker по TCP, не забудьте настроить аутентификацию по TLS и ограничьте сетевой доступ.
📌 Используйте параметр no-new-privileges при создании контейнеров, либо добавьте этот параметр в настройку службы по умолчанию.
Это предотвратит повышение привилегий в контейнере от пользователя до root. Подробнее тут.
📌 Включите параметр live-restore:
Это позволит не останавливать контейнеры в случае остановки самой службы docker, что позволит обновлять её без остановки сервисов. По умолчанию он отключен.
📌 Отключите использование userland-proxy.
В подавляющем большинстве случаев для проброса портов в контейнеры используется NAT. Отключение прокси уменьшает вектор атак.
📌 Чаще всего файл с настройками
📌 Не используйте без крайней необходимости в контейнерах пользователя root. Хорошая практика запускать всё от обычного пользователя.
📌 Ограничивайте использование памяти контейнерами так, чтобы они не могли использовать всю доступную память хоста. Для этого запускайте их с параметром
📌 Ограничивайте количество попыток перезапуска контейнера в случае ошибок. То есть не запускайте их с параметром
Было много советов по написанию DockerFile. Не стал их разбирать, так как мне кажется, это отдельная тема, которая к самой службе не имеет отношения. Также было много советов по запуску контейнеров. Например, не запускать там службу sshd, не монтировать системные директории и т.д. Это тоже отдельная тема, пропускал такие рекомендации.
К данной заметке будет актуальна ссылка на автоматическую проверку контейнеров с помощью Trivy и исправление с помощью Copacetic. Я написал небольшую статью:
⇨ Проверка безопасности Docker образов с помощью Trivy
Данный список составил на основе переработки вот этого документа: CIS Docker Benchmark v1.5.0 - 12-28-2022. Там подробное описание с обоснованием всех рекомендаций.
#cis #docker
📌 Директорию для информации
/var/lib/docker
рекомендуется вынести на отдельный раздел. Docker постоянно потребляет свободное место, так что переполнение раздела нередкое явление. 📌 У Docker высокие полномочия для доступа к хостовой системе. Следите за тем, чтобы в системной группе docker не было лишних пользователей.
📌 Для повышения безопасности рекомендуется настроить аудит службы docker, например с помощью auditd. Ставим службу:
# apt install auditd
Добавляем правило в
/etc/audit/rules.d/audit.rules
:-w /usr/bin/dockerd -k docker
Перезапускаем службу:
# systemctl restart auditd
Для повышенной безопасности можно настроить аудит и за файлами и директориями Docker, за конфигурационными файлами, за юнитом systemd, за сокетом. Это общая рекомендация для служб, которые работают с правами root.
📌 Разделяйте контейнеры по отдельным сетям для межконтейнерного взаимодействия. Если этого не делать, они будут взаимодействовать через общий системный бридж, который docker создаёт по умолчанию.
📌 Включите уровень логирования службы "info", добавив в файл конфигурации
/etc/docker/daemon.json
параметр:"log-level": "info"
Для повышения безопасности логи имеет смысл хранить где-то во вне. Их можно направить по syslog. Пример:
{
"log-driver": "syslog",
"log-opts": {
"syslog-address": "tcp://192.xxx.xxx.xxx"
}
}
📌 Если используете подключение к службе Docker по TCP, не забудьте настроить аутентификацию по TLS и ограничьте сетевой доступ.
📌 Используйте параметр no-new-privileges при создании контейнеров, либо добавьте этот параметр в настройку службы по умолчанию.
"no-new-privileges": true
Это предотвратит повышение привилегий в контейнере от пользователя до root. Подробнее тут.
📌 Включите параметр live-restore:
"live-restore": true
Это позволит не останавливать контейнеры в случае остановки самой службы docker, что позволит обновлять её без остановки сервисов. По умолчанию он отключен.
📌 Отключите использование userland-proxy.
"userland-proxy": false
В подавляющем большинстве случаев для проброса портов в контейнеры используется NAT. Отключение прокси уменьшает вектор атак.
📌 Чаще всего файл с настройками
/etc/docker/daemon.json
по умолчанию отсутствует и вы его создаёте сами, когда нужно задать те или иные параметры. Проследите, чтобы доступ на запись к нему имел только root (root:root 644). 📌 Не используйте без крайней необходимости в контейнерах пользователя root. Хорошая практика запускать всё от обычного пользователя.
📌 Ограничивайте использование памяти контейнерами так, чтобы они не могли использовать всю доступную память хоста. Для этого запускайте их с параметром
--memory
и задайте объём, к примеру, 1024m
. 📌 Ограничивайте количество попыток перезапуска контейнера в случае ошибок. То есть не запускайте их с параметром
--restart=always
. Используйте вместо этого --restart=on-failure:5
. Будет сделано 5 попыток запуска в случае ошибки. Было много советов по написанию DockerFile. Не стал их разбирать, так как мне кажется, это отдельная тема, которая к самой службе не имеет отношения. Также было много советов по запуску контейнеров. Например, не запускать там службу sshd, не монтировать системные директории и т.д. Это тоже отдельная тема, пропускал такие рекомендации.
К данной заметке будет актуальна ссылка на автоматическую проверку контейнеров с помощью Trivy и исправление с помощью Copacetic. Я написал небольшую статью:
⇨ Проверка безопасности Docker образов с помощью Trivy
Данный список составил на основе переработки вот этого документа: CIS Docker Benchmark v1.5.0 - 12-28-2022. Там подробное описание с обоснованием всех рекомендаций.
#cis #docker
Рекомендую очень простой и удобный портал для управления запущенными сервисами на Linux — Runtipi. Он позиционирует себя для домашнего использования, что подтверждает набор сервисов. Позволяет очень просто и быстро запускать приложения. А тем, кто с Linux на ВЫ, позволит без особых усилий пощупать руками его возможности в плане использования готовых сервисов.
По своей сути Runtipi обычная веб панель для запуска Docker контейнеров. У неё минимум возможностей и настроек. Есть магазин приложений, которые устанавливаются в пару кликов. Каждое приложение запускается на своём порту, а вы с помощью дашборда Runtipi легко их открываете, запускаете, устанавливаете, делаете базовую настройку, обновляете.
Я развернул у себя и запустил, попробовал. Реально удобно. Под капотом обычный Docker и контейнеры, которые пишет не сам автор, а использует готовые либо от разработчиков, либо от каких-то доверенных издателей, типа linuxserver.io.
Список поддерживаемых приложений можно посмотреть на отдельной странице. Сейчас их там 132 штуки. Некоторые примеры, про которые я писал: Adguard, Pi-Hole, Duplicati, File Browser, Gitea, Grafana, Joplin Server, Minio, n8n, Nextcloud, Portainer, Revolt Chat, Syncthing, Uptime Kuma, ZeroTier, Wireguard.
Все эти приложения легко развернуть, попробовать, удалить и т.д. Я хотел быстренько попробовать клиента для ChatGPT (там есть для него приложение). К сожалению, доступ к API у меня был заблокирован. Возвращает 404 ошибку. Похоже надо прокси использовать. Подскажите, кто как работает с ChatGPT с территории РФ.
⇨ Сайт / Исходники
#docker #linux
По своей сути Runtipi обычная веб панель для запуска Docker контейнеров. У неё минимум возможностей и настроек. Есть магазин приложений, которые устанавливаются в пару кликов. Каждое приложение запускается на своём порту, а вы с помощью дашборда Runtipi легко их открываете, запускаете, устанавливаете, делаете базовую настройку, обновляете.
Я развернул у себя и запустил, попробовал. Реально удобно. Под капотом обычный Docker и контейнеры, которые пишет не сам автор, а использует готовые либо от разработчиков, либо от каких-то доверенных издателей, типа linuxserver.io.
Список поддерживаемых приложений можно посмотреть на отдельной странице. Сейчас их там 132 штуки. Некоторые примеры, про которые я писал: Adguard, Pi-Hole, Duplicati, File Browser, Gitea, Grafana, Joplin Server, Minio, n8n, Nextcloud, Portainer, Revolt Chat, Syncthing, Uptime Kuma, ZeroTier, Wireguard.
Все эти приложения легко развернуть, попробовать, удалить и т.д. Я хотел быстренько попробовать клиента для ChatGPT (там есть для него приложение). К сожалению, доступ к API у меня был заблокирован. Возвращает 404 ошибку. Похоже надо прокси использовать. Подскажите, кто как работает с ChatGPT с территории РФ.
⇨ Сайт / Исходники
#docker #linux
Объясню простыми словами отличия современных систем контейнеризации. Для тех, кто с ними постоянно не работает, не очевидно, что они могут различаться принципиально по областям применения. Акцент сделаю на наиболее популярных Docker и LXC, а в конце немного по остальным пройдусь.
Все контейнеры используют одно и то же ядро операционной системы Linux и работают в его рамках. Это принципиальное отличие от виртуальных машин. А принципиальное отличие Docker от LXC в том, что Docker ориентируется на запуск приложений, а LXC на запуск системы.
Поясню на конкретном примере. Допустим, вам надо запустить в работу веб сервер. Если вы будете делать это с помощью Docker, то на хостовой машине запустите контейнер с Nginx, контейнер с Php-fpm, создадите на хосте локальные директории с файлами сайта и конфигурациями сервисов и пробросите их внутрь контейнеров, чтобы у них был доступ к ним. В самих контейнерах кроме непосредственно сервисов Nginx и Php-fpm практически ничего не будет.
Если ту же задачу решать с помощью LXC, то вы просто запустите контейнер с нужной базовой системой внутри. Зайдёте внутрь контейнера и настроите там всё, как обычно это делаете на отдельной виртуальной машине. То есть LXC максимально повторяет работу полноценной системы, только работает на базе ядра хоста.
☝ Docker - это один контейнер, одна служба, LXC - набор служб для решения конкретной задачи. При этом в образ Docker тоже можно поместить практически полноценную систему, но так обычно никто не делает, хотя и есть исключения.
Исходя из этих пояснений, становятся понятны плюсы и минусы каждого подхода. Плюсы Docker:
◽минимальный объём образов, соответственно, максимальная скорость запуска нужных сервисов;
◽для бэкапа достаточно сохранить непосредственно данные, образы можно опустить, так как они типовые.
Минусы:
◽более сложная настройка по сравнению с обычной виртуальной машиной, особенно что касается сети и диагностики в целом.
Плюсы LXC:
◽настройка практически такая же, как на обычной VM, заходишь внутрь контейнера по SSH и настраиваешь.
Минусы LXC:
◽итоговые образы бОльшего объёма, так как содержат всё окружение стандартных систем.
◽сложнее автоматизировать и стандартизировать разворачивание масштабных сервисов.
LXC отлично подходит как замена полноценной VM. Его удобно настроить, забэкапить в единый образ и развернуть в том же виде в другом месте. Docker идеален для максимальной плотности сервисов на одном сервере. Думаю именно за это он стал так популярен. На больших масштабах это заметная экономия средств, поэтому крупные компании его активно используют и продвигают.
Аналогом Docker в плане подхода в виде запуска отдельных служб в контейнерах является Podman. Там есть незначительные отличия в реализации, но в целом они очень похожи. Это продукт компании RedHat, и они его всячески продвигают.
Ещё упомяну про LXD, который иногда сравнивают с LXC, хотя это разные вещи. По сути, LXD - надстройка над LXC, предоставляющая REST API для работы с контейнерами LXC. Она упрощает работу с ними, стандартизирует и даёт удобные инструменты управления. При этом LXD может работать не только с контейнерами LXC, но и с виртуальными машинами QEMU.
Надеюсь ничего нигде не напутал. Писал своими словами по памяти, так как с Docker и LXC практически постоянно работаю и примерно представляю, как они устроены.
#docker #lxc
Все контейнеры используют одно и то же ядро операционной системы Linux и работают в его рамках. Это принципиальное отличие от виртуальных машин. А принципиальное отличие Docker от LXC в том, что Docker ориентируется на запуск приложений, а LXC на запуск системы.
Поясню на конкретном примере. Допустим, вам надо запустить в работу веб сервер. Если вы будете делать это с помощью Docker, то на хостовой машине запустите контейнер с Nginx, контейнер с Php-fpm, создадите на хосте локальные директории с файлами сайта и конфигурациями сервисов и пробросите их внутрь контейнеров, чтобы у них был доступ к ним. В самих контейнерах кроме непосредственно сервисов Nginx и Php-fpm практически ничего не будет.
Если ту же задачу решать с помощью LXC, то вы просто запустите контейнер с нужной базовой системой внутри. Зайдёте внутрь контейнера и настроите там всё, как обычно это делаете на отдельной виртуальной машине. То есть LXC максимально повторяет работу полноценной системы, только работает на базе ядра хоста.
☝ Docker - это один контейнер, одна служба, LXC - набор служб для решения конкретной задачи. При этом в образ Docker тоже можно поместить практически полноценную систему, но так обычно никто не делает, хотя и есть исключения.
Исходя из этих пояснений, становятся понятны плюсы и минусы каждого подхода. Плюсы Docker:
◽минимальный объём образов, соответственно, максимальная скорость запуска нужных сервисов;
◽для бэкапа достаточно сохранить непосредственно данные, образы можно опустить, так как они типовые.
Минусы:
◽более сложная настройка по сравнению с обычной виртуальной машиной, особенно что касается сети и диагностики в целом.
Плюсы LXC:
◽настройка практически такая же, как на обычной VM, заходишь внутрь контейнера по SSH и настраиваешь.
Минусы LXC:
◽итоговые образы бОльшего объёма, так как содержат всё окружение стандартных систем.
◽сложнее автоматизировать и стандартизировать разворачивание масштабных сервисов.
LXC отлично подходит как замена полноценной VM. Его удобно настроить, забэкапить в единый образ и развернуть в том же виде в другом месте. Docker идеален для максимальной плотности сервисов на одном сервере. Думаю именно за это он стал так популярен. На больших масштабах это заметная экономия средств, поэтому крупные компании его активно используют и продвигают.
Аналогом Docker в плане подхода в виде запуска отдельных служб в контейнерах является Podman. Там есть незначительные отличия в реализации, но в целом они очень похожи. Это продукт компании RedHat, и они его всячески продвигают.
Ещё упомяну про LXD, который иногда сравнивают с LXC, хотя это разные вещи. По сути, LXD - надстройка над LXC, предоставляющая REST API для работы с контейнерами LXC. Она упрощает работу с ними, стандартизирует и даёт удобные инструменты управления. При этом LXD может работать не только с контейнерами LXC, но и с виртуальными машинами QEMU.
Надеюсь ничего нигде не напутал. Писал своими словами по памяти, так как с Docker и LXC практически постоянно работаю и примерно представляю, как они устроены.
#docker #lxc
Предлагаю вашему вниманию любопытный проект по мониторингу одиночного хоста с Docker - domolo. Сразу скажу, что это продукт уровня курсовой работы с каких-нибудь курсов по DevOps на тему мониторинга. Он представляет из себя преднастроенный набор контейнеров на современном стеке.
Domolo состоит из:
◽Prometheus вместе с Pushgateway, AlertManager и Promtail
◽Grafana с набором дашбордов
◽Loki для сбора логов с хоста и контейнеров
◽NodeExporter - для сбора метрик хоста
◽cAdvisor - для сбора метрик контейнеров
◽Caddy - реверс прокси для prometheus и alertmanager
Сначала подумал, что это какая-та ерунда. Не думал, что заработает без напильника. Но, на моё удивление, это не так. Всё заработало вообще сразу:
Идём в Grafana по адресу http://ip-хоста:3000, учётка admin / changeme. Здесь мы можем наблюдать уже настроенные дашборды на все случаи жизни. Там есть буквально всё, что надо и не надо. Loki и сбор логов тоже работает сразу же без напильника. Идём в Explore, выбираем Datasource Loki и смотрим логи.
Если вам нужно мониторить одиночный хост с контейнерами, то это прям полностью готовое решение. Запускаете и наслаждаетесь. Репозиторий domolo удобен и для того, чтобы научиться всё это дело настраивать. Все конфиги и docker-compose файлы присутствуют. На мой взгляд для обучения это удобнее, чем какая-нибудь статья или обучающее видео. Здесь всё в одном месте и гарантированно работает.
Можно разобраться, настроить под себя и, к примеру, добавить туда поддержку внешних хостов. Надо будет добавить новые внешние Datasources и какие-то метки внедрить, чтобы различать хосты и делать общие дашборды. Получится ещё одна курсовая работа.
Сам проект не развивается и не обновляется. Так что ждать от него чего-то сверх того, что там есть, не имеет смысла.
#мониторинг #grafana #docker #prometheus
Domolo состоит из:
◽Prometheus вместе с Pushgateway, AlertManager и Promtail
◽Grafana с набором дашбордов
◽Loki для сбора логов с хоста и контейнеров
◽NodeExporter - для сбора метрик хоста
◽cAdvisor - для сбора метрик контейнеров
◽Caddy - реверс прокси для prometheus и alertmanager
Сначала подумал, что это какая-та ерунда. Не думал, что заработает без напильника. Но, на моё удивление, это не так. Всё заработало вообще сразу:
# git clone https://github.com/ductnn/domolo.git
# cd domolo
# docker-compose up -d
Идём в Grafana по адресу http://ip-хоста:3000, учётка admin / changeme. Здесь мы можем наблюдать уже настроенные дашборды на все случаи жизни. Там есть буквально всё, что надо и не надо. Loki и сбор логов тоже работает сразу же без напильника. Идём в Explore, выбираем Datasource Loki и смотрим логи.
Если вам нужно мониторить одиночный хост с контейнерами, то это прям полностью готовое решение. Запускаете и наслаждаетесь. Репозиторий domolo удобен и для того, чтобы научиться всё это дело настраивать. Все конфиги и docker-compose файлы присутствуют. На мой взгляд для обучения это удобнее, чем какая-нибудь статья или обучающее видео. Здесь всё в одном месте и гарантированно работает.
Можно разобраться, настроить под себя и, к примеру, добавить туда поддержку внешних хостов. Надо будет добавить новые внешние Datasources и какие-то метки внедрить, чтобы различать хосты и делать общие дашборды. Получится ещё одна курсовая работа.
Сам проект не развивается и не обновляется. Так что ждать от него чего-то сверх того, что там есть, не имеет смысла.
#мониторинг #grafana #docker #prometheus