Бесплатная миграция IT-инфраструктуры в облако

Установка и настройка PostgreSQL в Docker

Команда Timeweb Cloud
Команда Timeweb Cloud
Наши инженеры, технические писатели, редакторы и маркетологи
21 декабря 2021 г.
18661
8 минут чтения
Средний рейтинг статьи: 5

Докер помогает создавать изолированную среду для разных сервисов, в том числе баз данных. В этой статье мы рассмотрим, как установить PostgreSQL и настроить подключение к базе данных.

Установка И Настройка Postgre SQL В Docker

Зачем добавлять 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 в Докер из образа

Посмотрим, как выполняется установка 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 и другие инструкции, которые будут применены при запуске.

Подключение к PostgreSQL

Сначала подключимся к изолированной среде с помощью утилиты 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

Запуск PostgreSQL с помощью docker-compose

Рассмотрим ещё один вариант запуска — 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.

Хотите внести свой вклад?
Участвуйте в нашей контент-программе за
вознаграждение или запросите нужную вам инструкцию
img-server
21 декабря 2021 г.
18661
8 минут чтения
Средний рейтинг статьи: 5
Комментарии 2
BAD Pazific
BAD Pazific
13.05.2024, 17:49

я сделал это. Подключаюсь через Deaver - всё хорошо, потом пробую создать бд через dbeaver, она создаётся, в логах контейнера тоже пишется, но потом я обновляю соединение, ну типа посмотреть и базы данных уже нет. Так происходит всегда, в логах ничего не пишет. Я не понимаю что это

Гапонов
18.08.2024, 16:57

Значит не была создана точка монтирования