Как я могу защитить свое Dockerized приложение Django + PostgreSQL в рабочей среде на VPS с помощью Nginx?
Я использую Django и PostgreSQL для своего веб-проекта, который я контейнеризировал с помощью Docker. Я запускаю его на VPS и обслуживаю с помощью Nginx (работающего вне Docker).
Я обеспокоен безопасностью своей базы данных PostgreSQL и хочу убедиться, что она должным образом заблокирована. В частности, я хочу понять рекомендации по защите базы данных в следующих случаях:
- Контейнеры Docker работают в автономном режиме
- Служба PostgreSQL находится внутри Docker
- Nginx действует как веб-точка входа с хоста
Мои вопросы:
- Как я могу гарантировать, что мой контейнер PostgreSQL не будет доступен в общедоступном Интернете?
- Какие улучшения безопасности, специфичные для Docker и PostgreSQL, я могу применить?
- Следует ли мне внести какие-либо изменения в следующий файл Dockerfile или docker-compose-prod.yml?
Мой текущий файл Dockerfile
FROM python:3.x.x
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=x
ENV PYTHONUNBUFFERED=x
WORKDIR /src
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Install Poetry
RUN curl -sSL https://install.python-poetry.org | python3 - && \
export PATH="/root/.local/bin:$PATH"
# Add this line to make sure Poetry is in the PATH for subsequent commands
ENV PATH="/root/.local/bin:$PATH"
COPY pyproject.toml poetry.lock* ./
# # Install dependencies
RUN poetry config virtualenvs.create false \
&& poetry install --no-interaction --no-ansi
# Copy the rest of the code
COPY . .
Мой текущий файл docker-compose-prod.yml
services:
web:
restart: always
build:
context: .
command: bash -c "demo command"
ports:
- "8002:8002"
volumes:
- .:/src
- other-demo-volumes....
depends_on:
- db
environment:
- demo environment
db:
restart: always
image: postgres:16.2
volumes:
- app-pg-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=${DB_NAME}
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB_HOST=${POSTGRES_HOST}
- POSTGRES_PORT=${DB_PORT}
volumes:
app-pg-data:
other-demo-volumes....
- Улучшена четкость и сфокусированность. Добавлен соответствующий код для проверки
- Устранены проблемы с безопасностью PostgreSQL в Docker на VPS
Как я могу гарантировать, что мой контейнер PostgreSQL не будет доступен в общедоступном Интернете?
Если у него нет функции Compose ports:
, он недоступен по сети. (Для полноты картины, network_mode: host
также сделает его доступным по сети, но, как правило, вам следует избегать этой опции.)
Какие улучшения безопасности, специфичные для Docker и PostgreSQL, я могу применить?
Убедитесь, что ваш контейнер не имеет доступа к файловой системе хоста; удалите volumes:
из файла Compose, который (для чтения и записи) монтирует содержимое хоста в контейнер. Соответственно, обычно вам следует убедиться, что содержимое вашего изображения принадлежит пользователю root и недоступно для записи во всем мире, а затем запускается от имени пользователя, не являющегося пользователем root. Это предотвратит случайную перезапись кода приложения или статических ресурсов.
FROM python:3.x.x
# Create the non-root user.
#
# This is independent of the application content, so you save a minor bit of time
# during rebuilds doing it first. The syntax is different for Alpine-based images
# (but Python should almost always use a Debian/Ubuntu base). The user ID does not
# need to match anything else in particular and you shouldn't need to manually
# specify it.
#
# Do NOT chown files to this user.
RUN adduser --system appuser
# Do all the other setup as before, still as root.
ENV ...
COPY ...
RUN pip install ...
# Switch to the non-root user only at the end, when you're otherwise specifying
# what the default runtime behavior is.
USER appuser
CMD ["demo", "command"]
Следует ли мне внести какие-либо изменения в следующий файл Dockerfile или docker-compose-prod.yml?
Рассмотрите возможность использования многоступенчатой сборки, чтобы избежать сохранения очень тяжелого набора инструментов C из пакета build-essential
в конечном образе.
Предпочтительнее указывать значение по умолчанию CMD
в файле Docker, а не переопределять значение command:
в файле Compose. Предпочитайте sh -c
вместо bash -c
и избегайте синтаксиса, специфичного для bash; для простых команд, которые не используют несколько команд, замену окружения или другие функции оболочки, полностью пропустите оболочку.
Не монтируйте содержимое в контейнер, который скрывает содержимое изображения. Таргетинг на монтирование /src
скрывает почти все, что есть в образе, и это означает, что вы запускаете все, что есть на целевой машине, а не то, что вы тестировали в своей среде CI.
По возможности, также избегайте монтирования чего-либо еще в контейнер вашего приложения. Обычно это означает, что все данные хранятся в базе данных или в каком-либо доступном по сети хранилище. Если у вас есть тома для "обмена файлами" между контейнером приложения и обратным прокси-сервером, имейте в виду, что это не особенно надежный подход, и, в частности, вы не увидите обновлений своего статического содержимого, если обновите изображение. Контейнеры с отслеживанием состояния сложнее запускать в таких средах, как Kubernetes, где хранилище файловой системы должно быть доступно по сети и где у вас часто будет запущено несколько копий вашего контейнера.