Введение
Docker — удобный инструмент для создания изолированных сред. Именно этой своей особенностью он и удобен для разворачивания различных приложений, требующих дополнительных зависимостей.
Зачем использовать PostgreSQL в контейнере
Чтобы больше понять о преимуществах контейнеризации PostgreSQL, немного забежим вперед и для примера посмотрим на те зависимые пакеты, которые автоматически будут установлены вместе с приложениями, относящимся непосредственно к PostgreSQL, если мы будем ставить СУБД на сервер:
sudo apt install postgresql postgresql-contrib
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
libllvm10 libpq5 libxslt1.1 postgresql-12 postgresql-client-12
postgresql-client-common postgresql-common
Suggested packages:
postgresql-doc postgresql-doc-12 libjson-perl
Recommended packages:
sysstat
В нашем примере их три: libllvm10, libpq5, libxslt1.1. В зависимости от дистрибутива их может быть больше. Посмотрим, от каких пакетов на самом деле зависит пакет postgresql-12 (спойлер: 25 обязательных пакетов и 1 рекомендованный):
sudo apt-cache depends postgresql-12
postgresql-12
|Depends: locales
Depends: locales-all
Depends: postgresql-client-12
Depends: postgresql-common
Depends: ssl-cert
Depends: tzdata
|Depends: debconf
Depends: <debconf-2.0>
cdebconf
debconf
Depends: libc6
Depends: libgcc-s1
Depends: libgssapi-krb5-2
Depends: libicu66
Depends: libldap-2.4-2
Depends: libllvm10
Depends: libpam0g
Depends: libpq5
Depends: libselinux1
Depends: libssl1.1
Depends: libstdc++6
Depends: libsystemd0
Depends: libuuid1
Depends: libxml2
Depends: libxslt1.1
Depends: zlib1g
Recommends: sysstat
Наличие или отсутствие тех или иных пакетов, различные версии и другие факторы напрямую влияют на стабильность работы PostgreSQL. Используя контейнеризацию, возможные конфликты несовместимости нивелируются, т.к. все необходимые зависимости уже будут находиться в среде контейнера. Если загрузить готовый образ контейнера с ресурса Docker Hub (об этом ниже в статье), мы получим протестированную на совместимость и полностью готовую к работе среду.
Еще одно важное преимущество использования контейнеризации среды PostgreSQL — воспроизводимость. Разработчики и те, кто вносит какие-либо изменения в код процедур или добавляет новый функционал, могут быстро развернуть тестовую среду, полностью идентичную боевой, чтобы проверить свои гипотезы.
И наконец, отказоустойчивость. Если с сервером что-то случится, точно такой же контейнер может быть запущен на другом сервере с уже примонтированным хранилищем датафайлов.
Откроем панель управления Selectel, перейдем в представление Облачная платформа и нажмем на кнопку Создать сервер.
Далее вводим имя сервера, выбираем образ операционной системы (остановимся на Ubuntu 20.04 LTS 64-bit) и фиксированную конфигурацию сервера с 2 vCPU и 4 ГБ RAM. Объем дискового пространства диска установим в 20 ГБ. Еще раз проверяем конфигурацию сервера и нажимаем Создать.
Проверим сетевые настройки, копируем пароль для root и удостоверимся в нижней части экрана, что все настройки корректны. Нажмем кнопку Создать.
Подождем минуту или две пока сервер не перейдет в состояние Active.
Теперь можем приступать к установке PostgreSQL в Docker. Поехали!
Как установить PostgreSQL в Docker из образа
Перед началом работы с PostgreSQL в контейнере Docker, установим сам Docker. Предварительно, добавим ключ для работы с репозиторием Docker Hub:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Добавим этот репозиторий в локальный список репозиториев и установим Docker:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt install docker-ce
Запустим демон Docker и активируем его автозапуск:
sudo systemctl start docker
sudo systemctl enable docker
Поскольку за пределами жизненного цикла контейнера не остается каких либо данных, на файловой системе сервера (или другом файловом хранилище) необходимо создать каталог для хранения данных, которые будут появятся в процессе работы экземпляра PostgreSQL.
mkdir -p $HOME/docker/volumes/postgres
Чтобы получить из репозитория Docker Hub готовый образ контейнера с PostgreSQL, выполним следующую команду:
sudo docker pull postgres
Using default tag: latest
latest: Pulling from library/postgres
f7ec5a41d630: Pull complete
d073cd070242: Pull complete
03790957a916: Pull complete
b3776ac15dab: Pull complete
7144fd00aec4: Pull complete
54f6491bd120: Pull complete
247ab23c6036: Pull complete
57800498c536: Pull complete
bcb15a4d14f4: Pull complete
cfc751ecbc6e: Pull complete
bbf042afd4a4: Pull complete
453056a20de6: Pull complete
d5b1a75378ef: Pull complete
7841e2074775: Pull complete
Digest: sha256:61d5d8ef6cb4e2035f053f26b6b455c201a809354084cc8426b6904b8dd35602
Status: Downloaded newer image for postgres:latest
docker.io/library/postgres:latest
Теперь все готово к запуску.
Как запустить контейнер PostgreSQL
Выполним команду docker с ключом run:
sudo docker run --rm --name selectel-pgdocker -e POSTGRES_PASSWORD=selectel -e POSTGRES_USER=selectel -e POSTGRES_DB=selectel -d -p 5432:5432 -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data postgres
Если возникла ошибка вида: «Error starting userland proxy: listen tcp4 0.0.0.0:5432: bind: address already in use.», то следует вначале посмотреть какой процесс задействует порт 5432:
sudo ss -lptn 'sport = :5432'
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 244 127.0.0.1:5432 0.0.0.0:* users:(("postgres",pid=2592,fd=3)
Затем прибить” процесс по его PID и вновь выполнить запуск Docker-контейнера:
sudo kill 2592
Разберем ключи, которые мы использовали для запуска контейнера:
- —rm — ключ активирует автоматическое удаление контейнера и связанную с ним файловую систему после остановки контейнера. Полезный ключ для экономии дискового пространства.
- —name — ключ устанавливает имя контейнера. В пределах одного сервера имена контейнеров должны быть уникальны. Даже если один из них остановлен.
- -e — ключ задает переменные окружения, с которыми будет запущен контейнер. В нашей ситуации мы добавляем пароль суперпользователя, (POSTGRES_PASSWORD=selectel), имя суперпользователя (POSTGRES_USER=selectel) и имя базы данных по умолчанию (POSTGRES_DB=selectel) к базе данных.
- -d — ключ указывает, что контейнер должен быть запущен в в фоновом режиме (возвращает управление после его запуска).
- -p — ключ указывает на привязку внутреннего порта контейнера к порту сервера (используем порт по умолчанию 5432).
- -v — ключ создает точку монтирования каталога $HOME/docker/volumes/postgres на сервере к каталогу /var/lib/postgresql/data внутри контейнера.
Как подключиться к PostgreSQL в контейнере
После успешного запуска контейнера с PostgreSQL, попробуем к нему подключиться при помощи утилиты psql. Установим ее из пакета postgresql-client:
sudo apt install postgresql-client
Теперь можно подключиться и выполнить тестовый SQL-запрос:
psql -h 127.0.0.1 -U selectel -d selectel
Password for user selectel:
psql (12.6 (Ubuntu 12.6-0ubuntu0.20.04.1), server 13.2 (Debian 13.2-1.pgdg100+1))
WARNING: psql major version 12, server major version 13.
Some psql features might not work.
Type "help" for help.
selectel=#
Если появилось приглашение к вводу запроса, значит все действия были выполнены правильно.
Еще один вариант подключиться к базе данных, не устанавливая дополнительных утилит — подключиться непосредственно к Docker-контейнеру. Для этого выполним команду docker exec с дополнительными ключами:
sudo docker exec -it selectel-pgdocker psql -U selectel
psql (13.2 (Debian 13.2-1.pgdg100+1))
Type "help" for help.
selectel=#
Приглашение к вводу запроса будет означать корректность ввода команды. Разберем ключи, которые мы использовали для выполнения команды:
- -i — ключ активирует интерактивную работу с терминалом.
- -t — ключ запускает псевдо-терминал (pseudo-TTY).
- selectel-pgdocker — имя контейнера, к которому выполняется подключение.
- psql — указание на запуск утилиты для подключение к базе данных PostgreSQL.
- -U — ключ указывает на имя пользователя, которое будет использоваться для подключения к базе данных.
Теперь попробуем создать новую таблицу, добавить в нее данные и выполнить запрос:
selectel=# create table cities (name varchar(80));
CREATE TABLE
selectel=# insert into cities values ('Moscow');
INSERT 0 1
selectel=# select * from cities;
name
--------
Moscow
(1 row)
Чтобы остановить запущенный контейнер выполним docker stop и укажем имя контейнера:
sudo docker stop selectel-pgdocker
Файлы и процессы, созданные контейнером, принадлежат пользователю postgres, который является внутренним по отношению к контейнеру. В отсутствие пространства имен пользователей внутри контейнера, UID и GID в контейнере могут иметь произвольное значение. На самом сервере этим UID и GID могут соответствовать привилегированные пользователи или группы соответственно.
Например, пользователь на хосте с тем же UID или GID, что и пользователь postgres в контейнере, сможет получить доступ к данным в различных каталогах хоста, а также сможет завершить любой запущенный процесс. Чтобы избежать такой бреши в безопасности, укажем при запуске контейнера специализированные переменные USERMAP_UID и USERMAP_GID:
sudo docker run --rm --name selectel-pgdocker -e POSTGRES_PASSWORD=selectel -e POSTGRES_USER=selectel -e POSTGRES_DB=selectel -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
Еще одним вариантом запуска PostgreSQL в Docker-контейнере, является запуск контейнера с базой данных в составе docker-compose. В первую очередь, создадим соответствующий yml-файл:
nano docker-compose.yml
version: '3.1'
volumes:
pg_selectel:
services:
pg_db:
image: postgres
restart: always
environment:
- POSTGRES_PASSWORD=selectel
- POSTGRES_USER=selectel
- POSTGRES_DB=selectel
volumes:
- pg_project:/var/lib/postgresql/data
ports:
- ${POSTGRES_PORT:-5432}:5432
Затем установим docker-compose:
sudo apt install docker-compose
Теперь запустим контейнер:
sudo docker-compose up -d
Ключ -d указывает, что docker-compose должен быть запущен в в фоновом режиме (вернет управление после его запуска).
Проверим возможность подключения к базе данных:
psql -h 192.168.0.4 -U selectel -d selectel
Password for user selectel:
psql (12.6 (Ubuntu 12.6-0ubuntu0.20.04.1), server 13.2 (Debian 13.2-1.pgdg100+1))
WARNING: psql major version 12, server major version 13.
Some psql features might not work.
Type "help" for help.
selectel=#
Появление приглашения к вводу команд для PostgreSQL означает корректность выполненных настроек.
Чтобы остановить запущенный контейнер, выполним docker-compose stop:
sudo docker-compose stop
Заключение
Мы рассказали о работе с базой данных PostgreSQL в контейнере Docker, запуске, выполнении запросов и остановке. Как и говорили в начале статьи, работа с контейнеризованной в Docker базой данных упрощает процесс разработки и администрирование. Контейнеры могут быть легко перезапущены на другом сервере и сервис, предоставляемый базой данных, не прервется.