Всем привет, сегодня я хочу рассказать вам о своем опыте постановки PostgreSQL на сервере и какие при этом возникли сложности, а также о том как все это решилось.
А с какой целью?
При разработке нашего проекте мы дошли до того этапа, когда база данных в Docker-контейнере уже слишком ненадежный метод хранения информации, но при этом проект еще недостаточно разросся, чтобы использовать K8s и его возможностей.
Что было сначала
Изначальная конфигурация приложения:
services:
backend:
image: application:latest
ports:
- "127.0.0.1:8000:8000"
env_file:
- ../../.env
links:
- "postgres:db"
depends_on:
- postgres
volumes:
- ../../:/app
postgres:
image: postgres:17.2-alpine3.21
env_file:
- ../../.env
volumes:
- postgres:/var/lib/postgresql/data
healthcheck:
test: [ "CMD-SHELL", "POSTGRES_PASSWORD=postgres pg_isready -U postgres" ]
retries: 10
interval: 5s
timeout: 5s
volumes:
postgres:
В наше приложение данные для подключения к базе данных попадают из .env файла и выглядят следующим образом:
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_PORT=5432
POSTGRES_HOST=db
Теперь мы вынесем базу данных и установим её на машину. Для этого:
sudo apt install postgresql
После этого требуется настроить, откуда можно будет получать доступ к базе данных. Для этого переходим в файл /etc/postgresql/*/main/postgresql.conf. Меняем строку listen_addresses и убираем комментарий с неё
listen_addresses = '*'
После этого заходим в дефолтную базу данных template1 для настройки и меняем пароль пользователя postgres:
sudo -u postgres psql template1
ALTER USER postgres with encrypted password 'your_password';
После этого для входа под этим пользователем потребуется вводить пароль. Для этого необходимо изменить конфигурацию в файле /etc/postgresql/*/main/pg_hba.conf . Найти строку, настраивающую администратора, и заменить peer на scram-sha-256:
local all postgres scram-sha-256
Также следует добавить новую строку для предоставления доступа Docker к базе данных:
host postgres postgres 172.18.0.0/16 scram-sha-256
После всех этих преобразований наша база данных настроена и готова к использованию. (В целях демонстрации я не буду создавать отдельного пользователя и все действия будут выполнять пользователем postgres в дефолтной базе данных postgres, чего я настоятельно не рекомендую делать в рабочих проектах).
Однако если мы попробуем сейчас подключиться к нашей базе данных из нашего приложения, ничего не выйдет, так как в данных момент в .env файле хост базы данных стоит db (имя старого контейнера). Можно было бы заменить его на localhost, однако по стандарту Docker-контейнер не имеет доступа к сети машины, на которой он запущен. Для этого изменяем исходную конфигурацию приложения:
services:
backend:
image: application:latest
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- "127.0.0.1:8000:8000"
env_file:
- ../../.env
volumes:
- ../../:/app
Таким образом, база данных вынесена, а также добавлена настройка extra_hosts для доступа к внешней сети. После этого изменяем .env файл, указав в нём host.docker.internal в качестве хоста.
После этого приложение сможет подключаться к базе данных на локальной машине. Стоит отметить, что в идеальном сценарии следует создавать отдельного пользователя и предоставлять ему доступ, настраивая его для конкретных задач с целью повышения безопасности приложения. Это, тем не менее, не влияет на описанные выше этапы.
Что-то еще?
Если на сервере включён UFW (фаерволл), он может конфликтовать с текущей конфигурацией, не позволяя Docker-сети использовать порт 5432. Для исправления этой ситуации следует добавить новые правила, предварительно полностью открыв порт 5432:
sudo ufw delete deny 5432/tcp
После этого:
sudo ufw allow from 172.17.0.0/16 to any port 5432
sudo ufw allow from 172.18.0.0/16 to any port 5432
sudo ufw deny 5432/tcp
Здесь мы разрешаем доступ к базе данных для подсетей Docker и запрещаем доступ извне.
Резюме
В итоге нам удалось полностью перевести приложение на локальную базу данных, настроить доступ к ней, наладить взаимодействие между базой данных и Docker, а также сделать всё это достаточно безопасно