Безопасность Docker: Усиление защиты контейнерной среды
Лучшие практики безопасности Docker: пользователь без root, файловая система только для чтения, профили seccomp, сканирование образов, безопасность Docker socket, сетевая изоляция и управление секретами.
Содержание
Безопасность Docker: Усиление защиты контейнерной среды
Docker-контейнеры в конфигурации по умолчанию могут содержать множество уязвимостей. Контейнеры, работающие от root, чрезмерно привилегированные контейнеры и небезопасные образы представляют серьёзные риски. В этом руководстве мы рассмотрим безопасность Docker послойно.
1. Запуск от имени пользователя без root
Самая фундаментальная мера безопасности: запуск контейнеров от имени пользователя без root.
Определение пользователя в Dockerfile
# Плохая практика — запуск от root
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]
# Хорошая практика — пользователь без root
FROM node:20
# Создать пользователя и группу
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
WORKDIR /app
COPY --chown=appuser:appgroup . .
RUN npm ci --only=production
# Переключиться на пользователя без root
USER appuser
CMD ["node", "server.js"]
Указание пользователя во время выполнения
# Запустить с конкретным пользователем
docker run -d --user 1000:1000 myapp:latest
# Запустить с текущим пользователем
docker run -d --user $(id -u):$(id -g) myapp:latest
2. Файловая система только для чтения
# Запустить с корневой файловой системой только для чтения
docker run -d \
--name myapp \
--read-only \
--tmpfs /tmp \
--tmpfs /var/run \
myapp:latest
# docker-compose.yml
services:
app:
image: myapp:latest
read_only: true
tmpfs:
- /tmp
- /var/run
volumes:
- app-logs:/app/logs
3. Управление capabilities
# Удалить все capabilities, добавить только необходимые
docker run -d \
--name myapp \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
myapp:latest
# НИКОГДА не использовать привилегированный режим
# docker run --privileged myapp # ПЛОХАЯ ПРАКТИКА
services:
app:
image: myapp:latest
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
- CHOWN
4. Профили Seccomp
# Запустить с профилем seccomp по умолчанию (рекомендуется)
docker run -d --security-opt seccomp=default myapp:latest
# Пользовательский профиль seccomp
docker run -d \
--security-opt seccomp=/path/to/seccomp-profile.json \
myapp:latest
5. Безопасность Docker-образов
Безопасные практики Dockerfile
# Минимальный образ с многоэтапной сборкой
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Production-образ — минимальный
FROM node:20-alpine
# Применить обновления безопасности
RUN apk update && apk upgrade && apk add --no-cache dumb-init
# Пользователь без root
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
USER appuser
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget -qO- http://localhost:3000/health || exit 1
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/server.js"]
Сканирование образов
# Сканирование с Trivy (рекомендуется)
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy:latest image myapp:latest
# Только критические и высокие уязвимости
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy:latest image \
--severity CRITICAL,HIGH \
myapp:latest
6. Безопасность Docker Socket
# Монтировать Docker socket только для чтения (для мониторинга)
docker run -d \
--name monitoring \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
monitoring-app:latest
# НИКОГДА не монтировать Docker socket в production-контейнерах!
7. Управление секретами
# Использовать Docker secrets (режим Swarm)
echo "StrongPass123!" | docker secret create db_password -
docker service create \
--name myapp \
--secret db_password \
myapp:latest
# Секрет доступен по пути /run/secrets/db_password
8. Сетевая безопасность
# Открывать только необходимые порты
docker run -d \
--name myapp \
-p 127.0.0.1:8080:8080 \
myapp:latest
9. Лимиты ресурсов
# Лимиты CPU и памяти
docker run -d \
--name myapp \
--memory 512m \
--memory-swap 512m \
--cpus 1.0 \
--pids-limit 100 \
myapp:latest
10. Безопасность Docker Daemon
// /etc/docker/daemon.json
{
"icc": false,
"no-new-privileges": true,
"userns-remap": "default",
"live-restore": true,
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Заключение
Безопасность Docker требует многоуровневого подхода. Начните с пользователя без root, файловой системы только для чтения, минимальных capabilities и сканирования образов. Никогда не передавайте секреты как переменные окружения, не монтируйте Docker socket без необходимости и защищайтесь от DoS-атак с помощью лимитов ресурсов. С этими мерами безопасности на серверах REXE вы можете обеспечить безопасность контейнерной инфраструктуры.
Связанные статьи
Установка Kubernetes с K3s: Лёгкая оркестрация контейнеров
Настройка одно- и многоузлового кластера Kubernetes с K3s, использование kubectl, создание deployments и services, управление приложениями с Helm. Руководство по Kubernetes для VPS.
Управление Docker Volume и сетями: Постоянное хранилище и сетевая конфигурация
Типы Docker volume (named, bind mount, tmpfs), управление volumes, режимы Docker-сетей (bridge, host, overlay), создание пользовательских сетей и взаимодействие контейнеров. Полное руководство.
Логирование контейнеров: Управление логами Docker и Kubernetes
Драйверы логов Docker, команда docker logs, логи подов Kubernetes, централизованный сбор логов (Loki, ELK Stack), ротация логов и лучшие практики управления логами в production.