PostgreSQL: Inicializar Banco de Dados com Docker

Tags: PostgreSQL, Docker, pt-BR

Este texto serve como um complemento a um texto anterior daqui do blog, PostgreSQL: Dicas para Uso de Arquivos SQL.

Antes de Prosseguir

Esse texto oferece uma abordagem do PostgreSQL com imagem Docker. Caso esse não seja o seu caso, recomendo conferir a documentação do banco de dados e/ou das ferramentas do ambiente que você está usando.

A Situação

Na criação de um projeto, eu já tinha um arquivo SQL preparado para a criação do meu banco de dados, semelhante ao arquivo descrito no post citado acima. Vou chamar aqui nesse texto esse arquivo de env/db/database.sql, como abaixo:

/* application será o nome do banco de dados */
SELECT 'CREATE DATABASE application'
	WHERE NOT EXISTS
		(SELECT FROM pg_database WHERE datname = 'application')\gexec

/* Selecionando o banco application */
\c application

/* Definindo timezone */
SET timezone = 'America/Sao_Paulo';

/* UUID */
BEGIN;
  CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
COMMIT;

/* Tabela users */
BEGIN;
  CREATE TABLE IF NOT EXISTS users (
	  id         SERIAL       PRIMARY KEY,
	  uuid       uuid         UNIQUE DEFAULT uuid_generate_v4 (),
	  name       VARCHAR(100) NOT NULL,
	  document   CHAR(11)     UNIQUE NOT NULL,
	  created_on TIMESTAMPTZ  NOT NULL DEFAULT NOW()
  );
COMMIT;

Observação: adicionei o uso de transações nesse projeto, pois diferente da amostra acima, o arquivo original possui várias operações que precisavam de uma garantia de transação. Contudo, as instruções acima podem ser executadas sem BEGIN; e COMMIT; 😉

Em outros projetos, a criação de um banco de dados “pronto para ação” era lenta, dependendo da disponibilidade do Postgres. Eu precisava de algo rápido, quase instantâneo, e efetivo.

A Solução

Lendo a documentação da imagem oficial do PostgreSQL no Docker Hub, encontrei algo que parecia atender o que eu queria.

No tópico Initialization scripts, há um parágrafo explicando:

If you would like to do additional initialization in an image derived from this one, add one or more *.sql, *.sql.gz, or *.sh scripts under /docker-entrypoint-initdb.d (creating the directory if necessary). After the entrypoint calls initdb to create the default postgres user and database, it will run any *.sql files, run any executable *.sh scripts, and source any non-executable *.sh scripts found in that directory to do further initialization before starting the service.

Traduzindo (de forma simples):

Para executar qualquer ação ao initializar uma imagem derivada da imagem oficial, você pode colocar seus arquivos *.sql, *.sql.gz ou *.sh (não executável) no diretório /docker-entrypoint-initdb.d, que esses arquivos serão executados logo após a criação do banco de dados e usuário padrões e antes de inicializar o serviço.

Então, criei uma nova imagem Docker a partir da imagem oficial, ./env/Dockerfile.db como abaixo:

FROM postgres:9.6

COPY ./db/database.sql /docker-entrypoint-initdb.d/

Nele, há 2 instruções:

Com a instrução FROM, eu defino que esta imagem tem como base a imagem postgres, na tag 9.6. E com a instrução COPY, eu copio o arquivo ./env/db/database.sql na minha máquina para o diretório /docker-entrypoint-initdb.d da minha imagem.

Com isso, ao inicializar o meu ambiente, a imagem criada com o arquivo acima executava o meu arquivo SQL imediatamente, sem que eu precise me preocupar com essa tarefa.


Post anterior:
Próximo post:

Davi Marcondes Moreira avatar
Sobre Davi Marcondes Moreira
Desenvolvedor de software, palestrante, evangelista de trabalho remoto e home office, amante de MTB/XCO e entusiasta de café. Ele/Dele. Leia mais