Как сделать базу данных (или её часть) доступной для облачного процессора данных?

Меня интересовало использование ETL-сервисов, таких как Stitch Data или Skyvia, для интеграции различных источников данных (включая мою базу данных Discourse), но сотрудник Skyvia сообщил мне, что это невозможно:

Skyvia может подключаться к PostgreSQL через SSH, однако подключение невозможно, если PostgreSQL находится внутри контейнера Docker, а SSH-сервер расположен не внутри контейнера, а перед ним.

Вот их требования для подключения к PostgreSQL.

Есть ли очевидное решение этой проблемы?

Вы можете включить SSH в контейнере Discourse (на нестандартном порту), а затем разрешить им подключение к нему. Я думаю, что пример может быть в каталоге samples репозитория Discourse_docker.

Спасибо, Джей. В итоге я использовал docker-ssh с аутентификацией по публичному ключу. :+1:

Похоже, мне не хватает ключевой концепции, так как я могу подключиться через SSH с нестандартным портом и выполнить su postgres -c 'psql discourse' без проблем. В этом двухшаговом подходе всё работает, но, думаю, для прямого подключения через pgAdmin (например) требуется что-то немного другое.

Вот команда, которую я использую для проброса нестандартного порта:

docker run -d -p 2222:22 \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v ~/.ssh/authorized_keys:/authorized_keys \
        --name my-sshd \
        -e FILTERS={\"name\":[\"^/app$\"]} -e AUTH_MECHANISM=publicKey \
        -e AUTHORIZED_KEYS=/authorized_keys \
        jeroenpeeters/docker-ssh

Это позволяет мне позже выполнить следующее напрямую (без запуска контейнера Docker через launcher enter app):

ssh whatever@host -p 2222
su postgres -c 'psql discourse'

Я пробовал несколько вариантов, но безуспешно. Мне кажется, должен существовать способ выполнить ssh whatever@host -p XXXX и подключиться напрямую к базе данных (что, вероятно, и ожидает pgAdmin).

У вас не устанавливается соединение или возникла проблема с правами доступа?

Я могу подключиться через командную строку с помощью ssh, а затем psql. Подключение через pgAdmin не удаётся.

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

В файле app.yml, в верхней части, вы видите открытые порты 80 и 443. Вы можете добавить ещё одну строку для порта 5432 для PostgreSQL.

Тем не менее, это, скорее всего, очень плохая идея. База данных перешла от принятия только локальных подключений к открытию доступа для всего интернета.

Если вам нужно лишь иногда формировать отчёты, возможно, достаточно периодически загружать CSV-файлы из Data Explorer и открывать их в предпочитаемом вами инструменте. Вы также можете скачать резервные копии Discourse (без вложений), которые представляют собой стандартный формат дампа PostgreSQL. Имея такой дамп, вы сможете восстановить его в локальном экземпляре PostgreSQL для анализа.

Спасибо, Рафаэль

Я сделал это и пересобрал контейнер. Но это всё равно не работает (у меня отображается реальный IP-адрес вместо XX.XX.XX.XX)

А на вкладке SSH Tunnel:

Вот ошибка, которую я получаю:

Касательно этого: я понимаю, что это один слой защиты меньше, но всё же требуется наличие приватного SSH-ключа. Разве нет?

Если вы добавите 5432 в app.yml, порт будет открыт напрямую, без необходимости использования SSH-туннеля.

Я не могу дать совет по поводу SSH-туннеля в pgAdmin, так как никогда его не использовал. Предполагаю, что он ожидает, что порт будет слушать локальные подключения, поэтому его не нужно открывать для доступа из интернета.

Попробуйте:

expose:
  - "80:80"
  - "443:443"
  - "5432"

Но пароля для PostgreSQL нет, так как требуется доступ суперпользователя: в файле pg_hba.conf разрешения на подключение «local» установлены в «peer», поэтому подключение зависит от пользователя UNIX, что требует входа через SSH, верно?

Это не работает: psql -h XX.XX.XX.XX -p 5432 -U postgres -d discourse

Вы можете подключиться к psql как суперпользователь:

./launcher enter app
su postgres
psql

и создать необходимого пользователя с нужными правами для вашей системы отчетности.

Правильно, у меня нет проблем с подключением из контейнера Docker приложения. Моя проблема заключается в прямом подключении к базе данных PostgreSQL с локальной машины (чтобы я мог использовать pgAdmin) или из облачного процессора данных, например Stitch. Оба этих инструмента ожидают IP-адрес хоста и учетные данные SSH, но мне не удалось заставить их работать (я получаю ошибку, которую показал выше).

Единственное, что мне удалось сделать, — это использовать docker-ssh для прямого доступа к контейнеру Docker приложения (через открытый ключ) с локального компьютера (без выполнения launcher enter app), но мне всё ещё нужно выполнить su postgres 'psql discourse', чтобы получить доступ к базе данных. Я предполагаю, что именно это является проблемой для pgAdmin/Stitch — они ожидают прямое подключение.

Вы пробовали создать новый PostgreSQL с паролем и передать его вашему сервису?

Да, у них довольно длительная процедура.

Но у меня возникает та же проблема при простом использовании pgAdmin с моего локального компьютера.

Я полагаю, что в руководстве Как перейти от автономного контейнера к отдельным веб- и контейнерам данных могут быть инструкции по установке пароля.

Также, я думаю, вы можете привязать порт PostgreSQL только к адресу 127.0.0.1.

expose:
  - "80:80"
  - "443:443"
  - "127.0.0.1:5432:5432"

Я решил немного отступить и посмотреть, смогу ли я подключиться к базе данных, не открывая никаких портов. :grin:

Если я войду в контейнер, то увижу следующее:

# netstat -lp | grep postgres
tcp        0      0 0.0.0.0:postgresql      0.0.0.0:*               LISTEN      -
tcp6       0      0 [::]:postgresql         [::]:*                  LISTEN      -
unix  2      [ ACC ]     STREAM     LISTENING     263612292 -                    /var/run/postgresql/.s.PGSQL.5432

Если я выйду из контейнера и окажусь на своём удалённом сервере (пока ещё не на локальном компьютере), разве я не должен иметь возможность подключиться с помощью этой команды?

/var/discourse# psql -h localhost -d discourse -U postgres

Проблема в том, что появляется запрос пароля. Поскольку у пользователя postgres пароля нет, я попытался создать другого пользователя и назначить ему пароль:

CREATE USER whatever_user WITH ENCRYPTED PASSWORD '<whatever password>';
GRANT CONNECT ON DATABASE discourse TO whatever_user;
GRANT USAGE ON SCHEMA public TO whatever_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO whatever_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO whatever_user;

Я добавил строку для этого пользователя с методом md5 в файл pg_hba.conf и перезапустил PostgreSQL командой service postgresql restart:

# Database administrative login by Unix domain socket
local   all             postgres                                peer
local   all             whatever_user                      md5

Однако при попытке подключиться с удалённого сервера я получаю ошибку аутентификации:

# psql -h localhost -d discourse -U whatever_user
Password for user whatever_user:
psql: FATAL:  password authentication failed for user "whatever_user"
FATAL:  password authentication failed for user "whatever_user"

Что я упускаю? Я хотя бы хочу иметь возможность подключаться к базе данных с того же сервера. Шаг 2 — сделать то же самое через SSH-туннель, но, думаю, сначала нужно разобраться с первым шагом. Буду благодарен за любую помощь.

Хорошо. Я наконец-то разобрался :tada:

Я изменил это:

на это - "127.0.0.1:5433:5432", потому что получил ошибку о том, что порт уже занят.

Я пересобрал контейнер и проверил, что порт действительно открыт:

$ sudo docker ps
CONTAINER ID        IMAGE                           COMMAND             CREATED             STATUS              PORTS                      NAMES
whatever_id        local_discourse/app             "/sbin/boot"        20 minutes ago      Up 20 minutes       127.0.0.1:5433->5432/tcp   app

Теперь я могу создать SSH-туннель и подключиться с моего удалённого сервера, используя учётную запись с паролем:

# создаём туннель (можно также использовать ssh -f для запуска в фоновом режиме)
ssh -v -N -L 5433:localhost:5433 SERVER_IP_ADDRESS

# подключитесь в другой вкладке и введите пароль
psql -h localhost -d discourse -U whatever_user -p 5433

Если кто-то пытается сделать то же самое и сталкивается с проблемами, дайте знать.