Cómo hacer que la base de datos (o parte de ella) sea accesible para un procesador de datos en la nube

Estaba interesado en usar servicios ETL como Stitch Data o Skyvia para integrar diferentes fuentes de datos (incluida mi base de datos de Discourse), pero alguien de Skyvia me dijo que esto no es posible:

Skyvia puede conectarse a PostgreSQL a través de SSH; sin embargo, no es posible conectarse cuando está dentro de un contenedor Docker y el servidor SSH no está dentro del contenedor, sino frente a él.

Estos son sus requisitos para conectarse a PostgreSQL.

¿Existe alguna solución obvia?

Podrías habilitar SSH en el contenedor de Discourse (en un puerto no estándar) y luego permitirles conectarse allí. Creo que puede haber un ejemplo en el directorio de muestras de Discourse_docker.

3 Me gusta

Gracias, Jay. Al final usé docker-ssh con autenticación mediante clave pública. :+1:

2 Me gusta

Parece que me falta un concepto clave, ya que puedo conectarme mediante SSH con el puerto personalizado y luego ejecutar su postgres -c 'psql discourse' sin problemas. Todo funciona con este enfoque de dos pasos, pero creo que lo que necesito para conectarme directamente desde pgAdmin (por ejemplo) es algo ligeramente diferente.

Este es el comando que estoy usando para exponer un puerto personalizado:

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

Lo que me permite hacer esto más adelante directamente (sin ejecutar el contenedor Docker mediante launcher enter app):

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

He probado varias cosas, pero sin éxito. Siento que debería haber una forma de ejecutar ssh whatever@host -p XXXX y conectarme directamente a la base de datos (que es probablemente lo que pgAdmin espera).

¿No estás conectando o tienes un problema de permisos?

Puedo conectarme desde la línea de comandos mediante ssh y luego psql. No puedo conectarme a través de pgAdmin.

1 me gusta

Necesitas exponer el puerto de PostgreSQL directamente para poder conectarte mediante pgAdmin.

En el archivo app.yml, cerca de la parte superior, verás que los puertos 80 y 443 están abiertos. Puedes agregar otra línea para el puerto 5432 de PostgreSQL.

Dicho esto, esto es casi con total seguridad una muy mala idea. La base de datos pasó de aceptar solo conexiones locales a estar expuesta a todo internet.

Si lo único que necesitas es generar informes ocasionales, descargar algunos archivos CSV desde el Explorador de Datos y cargarlos en tu herramienta preferida podría ser suficiente. También puedes descargar copias de seguridad de Discourse (sin archivos adjuntos), las cuales están en el formato estándar de volcado de PostgreSQL. Con eso en mano, podrás restaurarlas en una instancia local de PostgreSQL para realizar el análisis.

1 me gusta

Gracias, Rafael

He hecho esto y he vuelto a construir el contenedor, pero esto sigue sin funcionar (tengo la IP real en lugar de XX.XX.XX.XX)

Y en la pestaña Túnel SSH:

Este es el error que obtengo:

Respecto a esto, entiendo que es una capa menos de protección, pero aún así requiere tener la clave privada SSH, ¿no es así?

Si agregas 5432 al app.yml, queda expuesto directamente, sin necesidad del túnel SSH.

No puedo dar consejos sobre el túnel SSH de pgAdmin, ya que nunca lo he usado. Supongo que espera que el puerto escuche conexiones locales, por lo que no necesita estar expuesto a internet.

Prueba con:

expose:
  - "80:80"
  - "443:443"
  - "5432"
1 me gusta

Pero no hay contraseña de PostgreSQL porque requiere ser superusuario: el archivo pg_hba.conf tiene los permisos de conexión “local” configurados en “peer”, por lo que depende del usuario UNIX, lo cual requiere iniciar sesión vía SSH, ¿verdad?

Esto no funciona: psql -h XX.XX.XX.XX -p 5432 -U postgres -d discourse

Puedes conectarte a psql como superusuario

./launcher enter app
su postgres
psql

y crear el usuario necesario con los permisos adecuados para tus informes.

Correcto, no tengo ningún problema al conectarme desde el contenedor Docker de la aplicación. Mi problema es conectarme directamente a la base de datos PostgreSQL desde mi máquina local (para poder usar pgAdmin) o desde un procesador de datos en la nube como Stitch. Ambos esperan una dirección IP de host y credenciales SSH, pero no he logrado que funcionen (recibo el error que mostré anteriormente).

Lo único que he logrado hacer es usar docker-ssh para acceder directamente al contenedor Docker de la aplicación (mediante clave pública) desde mi computadora local (sin ejecutar launcher enter app), pero aún necesito ejecutar su postgres 'psql discourse' para acceder a la base de datos. Supongo que ese es el problema con pgAdmin/Stitch: ellos esperan una conexión directa.

¿Has intentado crear una nueva instancia de PostgreSQL con una contraseña y proporcionársela a tu servicio?

Sí, tienen un procedimiento bastante extenso.

Pero tengo el mismo problema simplemente usando pgAdmin desde mi computadora local.

Creo que la guía Cómo migrar de un contenedor independiente a contenedores web y de datos separados puede tener instrucciones para establecer una contraseña.

Además, creo que podrías vincular el puerto de PostgreSQL solo a 127.0.0.1.

expose:
  - "80:80"
  - "443:443"
  - "127.0.0.1:5432:5432"
1 me gusta

He decidido dar un paso atrás para ver si puedo conectarme a la BD sin exponer ningún puerto. :grin:

Si entro al contenedor, veo esto:

# 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

Si salgo del contenedor y estoy en mi servidor remoto (aún no en mi computadora local), ¿no debería poder conectarme usando esto?

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

El problema es que me aparece un prompt de contraseña. Como el usuario postgres no tiene una, intenté crear un usuario diferente y asignarle una contraseña:

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;

Añadí una línea para ese usuario con md5 en pg_hba.conf y reinicié PG con service postgresql restart

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

Sin embargo, cuando intento conectarme desde el servidor remoto, obtengo un fallo de autenticación:

# 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"

¿Qué me estoy perdiendo? Estoy intentando al menos poder conectarme a la BD desde el mismo servidor. El paso 2 sería hacer lo mismo usando un túnel SSH, pero supongo que primero debo resolver el paso 1. Agradezco cualquier ayuda.

¡Ok! Finalmente lo entendí :tada:

Cambié esto:

por esto: - "127.0.0.1:5433:5432" porque recibí un error indicando que el puerto ya estaba en uso.

Reconstruí el contenedor y verifiqué que el puerto estuviera efectivamente abierto:

$ 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

Ahora puedo crear un túnel SSH y conectarme desde mi servidor remoto usando un usuario con contraseña:

# crear el túnel (también podrías usar ssh -f para ejecutarlo en segundo plano)
ssh -v -N -L 5433:localhost:5433 SERVER_IP_ADDRESS

# conectarse en otra pestaña e ingresar la contraseña
psql -h localhost -d discourse -U whatever_user -p 5433

Si alguien está intentando hacer esto y tiene algún problema, házmelo saber.

4 Me gusta