Crea imágenes de Docker con datos precargados
No pierdas a tu audiencia: genera tests fiables y reproducibles
Cuando preparamos una clase o una demo, lo último que queremos es perder la atención de nuestra audiencia a los 3 minutos. Tenemos que encontrar la manera para tener entornos de pruebas - ya sea para enseñar o testear - que sean fáciles de usar y reproducibles en el tiempo.
Por suerte, hay bases de datos que nos permiten distribuir imágenes de Docker que ya contengan los ingredientes que necesitas para tu próxima charla (o benchmark)!
Veamos como podemos conseguirlo sin dolores de cabeza con Postgres.
1. Preparar los datos
Para empezar necesitamos un fichero SQL que se encargue de:
Crear el usuario y contraseña que usaremos para conectarnos a la DB, ya que no necesariamente queremos usar los usuarios administrativos por defecto.
Definir el modelo de datos (esquemas, tablas,…)
Un ejemplo sencillo en Postgres podría ser:
CREATE USER demo WITH PASSWORD ‘password’;
GRANT ALL PRIVILEGES ON DATABASE postgres TO demo;
-- CREATE TABLE...En este caso, vamos a escribir un script algo más interesante que nos ayudará a generar datos para una tabla EMPLOYEES. Sí, hay librerías como Faker en Python que nos ayudan una barbaridad y tienen funciones super sencillas para generar nombres, direcciones, textos,… Aún así, tener herramientas a mano para poder jugar directamente en una DB puede resultar útil.
No siempre será todo SQL o todo Python. La herramienta o el lenguaje es lo de menos, aprendamos a usar bien todo lo que tenemos a mano.
CREATE TABLE EMPLOYEES (
id SERIAL PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50),
email VARCHAR(50),
mobile_no BIGINT,
date_of_birth DATE
);
ALTER TABLE public.employees OWNER TO demo;
CREATE FUNCTION get_random_string() RETURNS TEXT LANGUAGE SQL AS $$
SELECT STRING_AGG (SUBSTR(’abcdefghijklmnopqrstuvwxyz’, CEIL(RANDOM() * 26)::integer, 1), ‘’)
FROM GENERATE_SERIES(1, 10)
$$;
CREATE FUNCTION insert_record() RETURNS VOID LANGUAGE PLPGSQL AS $$
DECLARE first_name TEXT= INITCAP(get_random_string());
DECLARE last_name TEXT= INITCAP(get_random_string());
DECLARE email TEXT= LOWER(CONCAT(first_name, ‘.’, last_name, ‘@gmail.com’));
DECLARE mobile_no BIGINT=CAST(1000000000 + FLOOR(RANDOM() * 9000000000) AS BIGINT);
DECLARE date_of_birth DATE= CAST(NOW() - INTERVAL ‘100 year’ * RANDOM() AS DATE);
BEGIN
INSERT INTO EMPLOYEES (
first_name,
last_name,
email,
mobile_no,
date_of_birth
) VALUES (first_name, last_name, email, mobile_no, date_of_birth);
END;
$$;
SELECT insert_record() FROM GENERATE_SERIES(1, 1000000);Este script nos ayuda a generar INSERTs mediante funciones definidas directamente en Postgres, con strings, números y fechas aleatorias. Gracias al GENERATE_SERIES podemos fácilmente ejecutar la función insert_record 1M de veces, con lo que la tabla EMPLOYEES acabará con 1M de registros.
Además, si no conocíais la tabla pg_stat_statements, os recomiendo habilitarla para poder revisar estadísticas de ejecución de queries y planes de ejecución:
CREATE EXTENSION pg_stat_statements;
GRANT pg_read_all_stats TO demo;Cerramos el primer capítulo guardando nuestro fichero SQL con el nombre como queramos, por ejemplo postgres-script.sql.
2. Crear el Dockerfile
Ahora toca asegurarnos que el script se va a cargar cuando se genere la imagen de nuestra DB:
FROM postgres:16
WORKDIR /docker-entrypoint-initdb.d
COPY ./postgres-script.sql .
RUN chmod -R 775 /docker-entrypoint-initdb.dPostgres tiene un directorio /docker-entrypoint-initdb.d donde si ponemos ficheros de SQL, van a ejecutarse cuando la DB arranque. Copiando nuestro script ahí nos aseguramos que cuando alguien use nuestra imagen, tenga el usuario y los datos que hemos definido.
3. Construir y ejecutar
Vamos a crear la imagen con:
docker build . -t demo/postgres:localy la ejecutamos mapeando bien los puertos:
docker run \
-p 5432:5432 \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_USER=postgres \
--name demo_pg \
--rm \
demo/postgres:local postgres \
-c shared_preload_libraries=pg_stat_statements \
-c pg_stat_statements.track=all \
-c max_connections=200Ya sólo queda conectarnos a localhost:5432 (yo uso DBeaver) y estamos listos!
Un abrazo.


