Докер помогает создавать изолированную среду для разных сервисов, в том числе баз данных. В этой статье мы рассмотрим, как установить PostgreSQL и настроить подключение к базе данных.
Главное преимущество контейнеризации — сохранение и быстрое развертывание зависимостей. Для наглядности посмотрим, какие зависимые пакеты устанавливаются вместе с приложениями при установке СУБД на сервер с ОС Debian.
Заводим сервер на timeweb.cloud и устанавливаем PostgreSQL:
sudo apt install postgresql postgresql-contrib
При выполнении команды install postgresql
обращаем внимание на строчки в начале:
The following additional packages will be installed:
libllvm11 libpq5 libsensors-config libsensors5 libxslt1.1 libz3-4 postgresql-13 postgresql-client-13
Установка Постгрес приводит с собой ещё шесть библиотек: libllvm11
, libpq5
, libsensors-config
, libsensors5
, libxslt1.1
и libz3-4
.
Теперь посмотрим список зависимостей PostgreSQL 13:
sudo apt-cache depends postgresql-13
Получаем список из 25 зависимостей, из них только одна — рекомендуемая, остальные — обязательные.
Нет нужного пакета, не та версия — всё это приводит к конфликтам. Postgres в Docker помогает исключить большую часть проблем. Все зависимости сохраняются внутри контейнера. При загрузке образа пользователь получает полностью совместимую среду, готовую к работе.
Отсюда вытекает следующий плюс — воспроизводимость. Например, разработчик хочет протестировать новую фичу в продукте. С помощью изолированной среды он может в несколько кликов развернуть на локальной машине рабочее окружение. Или другая ситуация — в команду приходит новый разработчик. Контейнеры помогают заметно ускорить старт его работы.
И это не все преимущества PostgreSQL в Docker. С контейнерами возрастает и отказоустойчивость. Если сервер перестаёт работать, можно запустить контейнер на другой машине и не беспокоиться о параметрах конфигурации.
dbaas
Посмотрим, как выполняется установка PostgreSQL в Ubuntu. Сначала установим Докер.
Добавляем ключ для работы с Docker Hub:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Если Docker Hub недоступен, можно использовать наш бесплатный прокси, который возобновляет этот доступ.
Добавляем репозиторий в список локальных и устанавливаем Докер:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt install docker-ce
Запускаем Docker и настраиваем его автозагрузку с помощью системной утилиты systemctl
:
sudo systemctl start docker
sudo systemctl enable docker
Пока изолированная среда не запущена, в ней нет никаких данных. Нам это не подходит. Поэтому создаем Docker Postgres Volume — каталог для хранения данных.
mkdir -p $HOME/docker/volumes/postgres
Устанавливаем образ Postgres из Docker Hub с помощью команды docker pull
:
sudo docker pull postgres
Установка PostgreSQL завершена, всё готово к запуску.
Выполним команду docker run
:
sudo docker run --rm --name timeweb-pgdocker -e POSTGRES_PASSWORD=timeweb -e POSTGRES_USER=timeweb -e POSTGRES_DB=timeweb -d -p 5531:5531 -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data postgres
Разберём ключи, которые передали вместе с docker run
:
--rm
— после остановки контейнера он сам и его файловая система будут удалены. Полезно для экономии пространства на сервере.--name
— имя контейнера. Должно быть уникальным в пределах одного сервера вне зависимости от статуса.-e
— переменные окружения: пароль и имя суперпользователя, имя БД по умолчанию.-d
— запуск в фоновом (автономном) режиме. После его запуска управление возвращается пользователю.-p
— привязка Postgres к порту сервера.-v
— создание точки монтирования.При выполнении команды может возникнуть ошибка «Error starting userland proxy: listen tcp4 0.0.0.0:5531: bind: address already in use». В таком случае смотрим, какой процесс занимает порт 5531:
sudo ss -lptn 'sport = :5531'
Чтобы «убить» процесс, используем команду kill
. Передаём ей PID процесса, который занимает порт 5531:
sudo kill 2592
После устранения ошибки снова пробуем запустить Докер:
sudo docker run --rm --name timeweb-pgdocker -e POSTGRES_PASSWORD=timeweb -e POSTGRES_USER=timeweb -e POSTGRES_DB=timeweb -d -p 5531:5531 -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data postgres
Обычно в таком виде команду не используют. Гораздо удобнее хранить конфигурацию в Dockerfile. Там можно прописать Docker ADD, CMD, LABEL, ENV и другие инструкции, которые будут применены при запуске.
Сначала подключимся к изолированной среде с помощью утилиты psql
. Она входит в состав postgresql-client
. Выполняем install psql
:
sudo apt install postgresql-client
Подключаемся к БД и выполняем тестовый запрос:
psql -h 127.0.0.1 -U timeweb -d timeweb
Ответ должен быть таким:
Password for user timeweb:
psql (12.6 (Ubuntu 12.6-0ubuntu0.20.04.1), server 13.2 (Debian 13.2-1.pgdg100+1))
Type "help" for help.
timeweb=#
Приглашение к вводу запроса с именем пользователя говорит о том, что соединение установлено корректно.
Подключиться к контейнеру можно и с помощью docker exec
с ключами:
sudo docker exec -it timeweb-pgdocker psql -U timeweb
Результат тот же — приглашение к вводу запросов:
psql (12.6 (Debian 13.2-1.pgdg100+1))
Type "help" for help.
timeweb=#
Ключи выглядят непонятно, давайте их разберём:
-i
— активация интерактивной работы с терминалом.-t
— запуск псевдо-терминала.timeweb-pogdocker
— имя контейнера, к которому будут обращены вызовы.psql
— запуск утилиты для подключения к БД.-U
— пользовательское имя для подключения к БД.Чтобы протестировать соединение, создадим новую таблицу, заполним её и выполним запрос:
timeweb=# create table cities (name varchar(80));
CREATE TABLE
timeweb=# insert into cities values ('Moscow');
INSERT 0 1
timeweb=# select * from cities;
name
--------
Moscow
(1 row)
После выполнения запроса остановим контейнер командой docker stop
:
sudo docker stop timeweb-pgdocker
Здесь мы обнаруживаем брешь в безопасности. Файлы и процессы, которые создаёт контейнер, принадлежат внутреннему пользователю postgres
. Из-за отсутствия пространства имён внутри контейнера UID и GID могут быть произвольными.
Проблема в том, что на самом сервере с этими же UID и GID могут быть другие привилегированные пользователи и группы. Потенциально это приводит к ситуации, когда пользователь получает доступ к каталогам хоста и может завершить любой процесс. Избежать такой ситуации можно, указав при запуске переменные USERMAP_UID
и USERMAP_GID
.
Пример команды:
sudo docker run --rm --name timeweb-pgdocker -e POSTGRES_PASSWORD=timeweb -e POSTGRES_USER=timeweb -e POSTGRES_DB=timeweb -e USERMAP_UID=999 -e USERMAP_GID=999 -d -p 5432:5432 -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data postgres
Рассмотрим ещё один вариант запуска — Docker Compose.
Сначала создадим файл YAML:
version: '3.1'
volumes:
pg_timeweb:
services:
pg_db:
image: postgres
restart: always
environment:
- POSTGRES_PASSWORD=timeweb
- POSTGRES_USER=timeweb
- POSTGRES_DB=timeweb
volumes:
- pg_project:/var/lib/postgresql/data
ports:
- ${POSTGRES_PORT:-5531}:5531
Затем установим Docker Compose:
sudo apt install docker-compose
И запустим:
sudo docker-compose up -d
Проверим, что к базе данных можно подключиться:
psql -h 192.168.0.4 -U timeweb -d timeweb
Пример ответа:
Password for user timeweb:
psql (12.6 (Ubuntu 12.6-0ubuntu0.20.04.1), server 13.2 (Debian 13.2-1.pgdg100+1))
Type "help" for help.
timeweb=#
Если в терминале появилось приглашение к вводу запроса, значит подключение прошло успешно.
Выполним docker-compose stop
, чтобы остановить контейнер:
sudo docker-compose stop
Чтобы быстро узнавать, что с изолированной средой что-то не так, используем healthcheck. Настроим автоматический перезапуск при обнаружении проблем.
Примерная PostgreSQL-настройка в YAML-файле:
version: "3.9"
services:
postgres:
image: postgres:13.3
environment:
POSTGRES_DB: "twdb"
POSTGRES_USER: "twpguser"
POSTGRES_PASSWORD: "785564tw"
PGDATA: "/var/lib/postgresql/data/pgdata"
volumes:
- ../2. Init Database:/docker-entrypoint-initdb.d
- .:/var/lib/postgresql/data
ports:
- "5531:5531"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U twpguser -d twdb"]
interval: 15s
timeout: 10s
retries: 7
start_period: 12s
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1'
memory: 4GB
Обратите внимание на секцию resources
. В ней можно ограничить ресурсы для БД. Такой подход разумен для локального запуска и экспериментов.
Подготовили для вас выгодные тарифы на DBaaS
В этом руководстве мы изучили нужные для установки PostgreSQL-команды Docker и Docker Compose, а также особенности развертывания контейнера и соединения с локальной машиной.
В зависимости от архитектуры приложения вы можете развернуть базу данных с помощью Docker или Docker Compose. Второй сценарий будет встречаться чаще, поэтому обратите больше внимания на конфигурацию, которую нужно описывать в файле docker-compose.yaml
.
я сделал это. Подключаюсь через Deaver - всё хорошо, потом пробую создать бд через dbeaver, она создаётся, в логах контейнера тоже пишется, но потом я обновляю соединение, ну типа посмотреть и базы данных уже нет. Так происходит всегда, в логах ничего не пишет. Я не понимаю что это
Значит не была создана точка монтирования