Conteúdo
PostgreSQL com Docker: instalação, conexão, backup e atualização
Mudança importante no PostgreSQL 18: a partir de
postgres:18, o diretório de dados da imagem oficial passou a ser/var/lib/postgresql/18/docker, e o Volume deve ser montado em/var/lib/postgresql. A maioria dos tutoriais disponíveis na internet indica/var/lib/postgresql/data, que era o caminho usado até a versão 17. Na versão 18, esse caminho faz o contêiner falhar ao iniciar. Veja o teste abaixo.
Inicie com um comando
$ docker run -d --name pg -e POSTGRES_PASSWORD=secret -p 127.0.0.1:5432:5432 -v pgdata:/var/lib/postgresql --restart unless-stopped postgres:18
1b34d05a195f347c86e431441162b760167a5c04016a528e10342d0199be016d
$ docker logs pg 2>&1 | tail -n 3
2026-10-13 00:53:32.071 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2026-10-13 00:53:32.075 UTC [72] LOG: database system was shut down at 2026-10-13 00:53:31 UTC
2026-10-13 00:53:32.080 UTC [1] LOG: database system is ready to accept connections
$ docker exec pg psql -U postgres -c "SHOW data_directory;"
data_directory
-------------------------------
/var/lib/postgresql/18/docker
(1 row)
| Parâmetro | Descrição |
|---|---|
POSTGRES_PASSWORD | Senha do superusuário (obrigatória) |
-p 127.0.0.1:5432:5432 | Disponibiliza a porta apenas localmente |
-v pgdata:/var/lib/postgresql | Os dados ficam no Volume pgdata. Na versão 18, monte este caminho |
SHOW data_directory confirma que o diretório de dados efetivo é /var/lib/postgresql/18/docker, dentro de /var/lib/postgresql, que montamos. O nome do diretório inclui o número da versão principal, então os dados das versões nova e antiga podem coexistir no mesmo Volume durante uma futura atualização.
Outras variáveis de ambiente comuns:
| Variável de ambiente | Descrição | Valor padrão |
|---|---|---|
POSTGRES_USER | Nome do superusuário | postgres |
POSTGRES_DB | Banco de dados padrão | Igual a POSTGRES_USER |
PGDATA | Diretório de dados | /var/lib/postgresql/18/docker (versão 18) |
TZ | Fuso horário | UTC |
Assim como no MySQL, essas variáveis só têm efeito quando o diretório de dados está vazio. Alterar
POSTGRES_PASSWORDdepois não muda a senha existente. Para isso, useALTER USER ... PASSWORD '...'.
Teste: montar o caminho antigo na versão 18 falha
Se você seguir tutoriais antigos e montar o Volume em /var/lib/postgresql/data:
$ docker run -d --name pgold -e POSTGRES_PASSWORD=secret -v pgold:/var/lib/postgresql/data postgres:18
b480eb9c72b29fa99f1ed8df17972e2bfc2d6da4b86c058a36cf21fd63579bfa
$ docker ps -a --filter name=pgold --format "{{.Status}}"
Exited (1) 5 seconds ago
$ docker logs pgold 2>&1 | head -n 12
Error: in 18+, these Docker images are configured to store database data in a
format which is compatible with "pg_ctlcluster" (specifically, using
major-version-specific directory names). This better reflects how
PostgreSQL itself works, and how upgrades are to be performed.
See also https://github.com/docker-library/postgres/pull/1259
Counter to that, there appears to be PostgreSQL data in:
/var/lib/postgresql/data (unused mount/volume)
This is usually the result of upgrading the Docker image without
upgrading the underlying database using "pg_upgrade" (which requires both
O contêiner termina com Exited (1) em poucos segundos. A mensagem de erro explica que a versão 18 usa diretórios nomeados conforme a versão principal e encontrou uma “montagem não utilizada” em /var/lib/postgresql/data. Essa verificação evita que você pense que os dados foram salvos quando, na verdade, foram gravados dentro do contêiner e desaparecerão quando ele for removido. Basta mudar o caminho de montagem para /var/lib/postgresql.
Gerencie com Compose
Em projetos reais, recomendamos usar Compose. Crie a pasta pg-demo:
pg-demo/
├── compose.yaml
├── .env
└── initdb/
└── 01-init.sql
.env:
DB_PASSWORD=change-this-password
initdb/01-init.sql (executado na primeira inicialização para criar extensões, tabelas e dados de exemplo; o pg_sleep(8) final simula intencionalmente uma inicialização demorada, como a importação de muitos dados, para observar a verificação de integridade):
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE TABLE products (
id serial PRIMARY KEY,
name text NOT NULL,
price integer NOT NULL
);
INSERT INTO products (name, price) VALUES ('珍珠奶茶', 65), ('鳳梨酥', 45), ('牛肉麵', 180);
-- Simula uma inicialização demorada (por exemplo, a importação de muitos dados)
SELECT pg_sleep(8);
compose.yaml:
services:
db:
image: postgres:18
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: app
TZ: Asia/Taipei
command: ["postgres", "-c", "max_connections=200", "-c", "shared_buffers=256MB"]
ports:
- "127.0.0.1:5432:5432"
volumes:
- pgdata:/var/lib/postgresql
- ./initdb:/docker-entrypoint-initdb.d:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -U app -d app"]
interval: 2s
timeout: 3s
retries: 30
shm_size: 256mb
restart: unless-stopped
volumes:
pgdata:
| Configuração | Descrição |
|---|---|
POSTGRES_USER: app | Renomeia o superusuário para app; não haverá mais um usuário chamado postgres |
command: ["postgres", "-c", ...] | Passa configurações do PostgreSQL com -c, sem precisar preparar um arquivo de configuração separado |
pg_isready -h 127.0.0.1 | Ferramenta de verificação integrada do PostgreSQL. É essencial adicionar -h 127.0.0.1; veja o teste abaixo para saber o motivo |
shm_size: 256mb | A memória compartilhada padrão do Docker em /dev/shm tem apenas 64 MB; consultas mais complexas podem gerar o erro could not resize shared memory segment |
$ docker compose up -d --wait
[+] up 3/3
✔ Network pg-demo_default Created 0.0s
✔ Volume pg-demo_pgdata Created 0.0s
✔ Container pg-demo-db-1 Healthy 11.3s
$ docker compose exec db psql -U app -h 127.0.0.1 -c "SELECT * FROM products;"
id | name | price
----+----------+-------
1 | 珍珠奶茶 | 65
2 | 鳳梨酥 | 45
3 | 牛肉麵 | 180
(3 rows)
$ docker compose logs db 2>&1 | grep -E "running /docker-entrypoint-initdb.d|init process complete|listening on IPv4"
db-1 | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/01-init.sql
db-1 | PostgreSQL init process complete; ready for start up.
db-1 | 2026-10-13 08:52:58.663 CST [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
$ docker compose exec db psql -U app -c "SHOW max_connections;" -c "SHOW shared_buffers;" -c "SELECT now();"
max_connections
-----------------
200
(1 row)
shared_buffers
----------------
256MB
(1 row)
now
-------------------------------
2026-10-13 08:53:01.293902+08
(1 row)
$ docker compose exec db df -h /dev/shm
Filesystem Size Used Avail Use% Mounted on
shm 256M 1.1M 255M 1% /dev/shm
$ docker compose exec db psql -U app -c "\dx"
List of installed extensions
Name | Version | Default version | Schema | Description
---------+---------+-----------------+------------+-------------------------------------------------------------------
pg_trgm | 1.6 | 1.6 | public | text similarity measurement and index searching based on trigrams
plpgsql | 1.0 | 1.0 | pg_catalog | PL/pgSQL procedural language
(2 rows)
Healthylevou 11,3 segundos, exatamente o tempo da inicialização mais opg_sleep(8). Assim que ficou saudável, conectamos por TCP; os dados estavam todos lá e os caracteres chineses foram exibidos corretamente.- Os logs mostram que o script de inicialização foi executado e que o servidor começou a escutar em
0.0.0.0:5432somente depois de concluir a inicialização. max_connectionsé 200 eshared_buffersé 256MB; os parâmetros decommandforam aplicados.now()mostra o fuso horário+08./dev/shmtem 256M;shm_sizefoi aplicado.\dxlista as extensões instaladas;pg_trgmfoi criada pelo script de inicialização.
Armadilha da verificação de integridade: sem -h, pg_isready informa healthy cedo demais
Uma forma comum de escrever isso na internet é pg_isready -U app -d app (sem -h). Testamos alterando para essa forma:
$ docker compose up -d --wait
[+] up 3/3
✔ Network pg-demo_default Created 0.0s
✔ Volume pg-demo_pgdata Created 0.0s
✔ Container pg-demo-db-1 Healthy 3.2s
$ docker compose exec db psql -U app -h 127.0.0.1 -c "SELECT count(*) FROM products;"
psql: error: connection to server at "127.0.0.1", port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
$ docker compose logs db 2>&1 | grep -E "pg_sleep|init process complete|listening on IPv4"
Após apenas 3,2 segundos, o status passou a Healthy, mas a conexão por TCP retornou Connection refused.
O motivo é o mesmo do MySQL: durante a inicialização, o script de inicialização abre primeiro um servidor temporário que aceita somente conexões por Unix socket para executar os scripts de initdb. Sem -h, pg_isready usa o socket e informa que é possível conectar antes de a inicialização terminar. Aplicações que dependem dele (depends_on com condition: service_healthy) iniciam nesse momento, e a conexão por TCP falha. Adicione -h 127.0.0.1 para forçar o uso de TCP e aguardar até que o servidor definitivo seja iniciado.
Conexão e psql
Usando o psql
O contêiner inclui o cliente psql. Para usá-lo de forma interativa, execute docker compose exec db psql -U app (em um contêiner separado, use docker exec -it pg psql -U postgres), entre no prompt app=# e digite SQL ou os comandos abaixo. Você também pode executar um comando diretamente com -c:
$ docker compose exec db psql -U app -c "SELECT version();"
version
--------------------------------------------------------------------------------------------------------------------
PostgreSQL 18.6 (Debian 18.6-1.pgdg13+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
(1 row)
$ docker compose exec db psql -U app -c "\l"
List of databases
Name | Owner | Encoding | Locale Provider | Collate | Ctype | Locale | ICU Rules | Access privileges
-----------+-------+----------+-----------------+------------+------------+--------+-----------+-------------------
app | app | UTF8 | libc | en_US.utf8 | en_US.utf8 | | |
postgres | app | UTF8 | libc | en_US.utf8 | en_US.utf8 | | |
template0 | app | UTF8 | libc | en_US.utf8 | en_US.utf8 | | | =c/app +
| | | | | | | | app=CTc/app
template1 | app | UTF8 | libc | en_US.utf8 | en_US.utf8 | | | =c/app +
| | | | | | | | app=CTc/app
(4 rows)
$ docker compose exec db psql -U app -c "\dt"
List of tables
Schema | Name | Type | Owner
--------+----------+-------+-------
public | products | table | app
(1 row)
$ docker compose exec db psql -U app -c "\d products"
Table "public.products"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+--------------------------------------
id | integer | | not null | nextval('products_id_seq'::regclass)
name | text | | not null |
price | integer | | not null |
Indexes:
"products_pkey" PRIMARY KEY, btree (id)
$ docker compose exec db psql -U app -c "\du"
List of roles
Role name | Attributes
-----------+------------------------------------------------------------
app | Superuser, Create role, Create DB, Replication, Bypass RLS
| Comando | Função |
|---|---|
\l | Lista os bancos de dados |
\c nome | Alterna o banco de dados |
\dt | Lista as tabelas |
\d tabela | Mostra a estrutura da tabela |
\du | Lista os usuários (funções) |
\dx | Lista as extensões instaladas |
\q | Sai |
O comando \du mostra que app é Superuser, e o Owner de todos os bancos de dados em \l também é app: depois que você define POSTGRES_USER, ele substitui o usuário padrão postgres.
Por que não é preciso digitar a senha dentro do contêiner
Nos exemplos acima, o psql não pediu senha. Confira o arquivo pg_hba.conf no diretório de dados (as regras de autenticação de conexão do PostgreSQL):
$ docker compose exec db grep -v "^#" /var/lib/postgresql/18/docker/pg_hba.conf | grep -v "^$"
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
local replication all trust
host replication all 127.0.0.1/32 trust
host replication all ::1/128 trust
host all all all scram-sha-256
$ docker run --rm --network pg-demo_default -e PGPASSWORD=wrong postgres:18 psql -h db -U app -c "SELECT 1;"
psql: error: connection to server at "db" (172.19.0.2), port 5432 failed: FATAL: password authentication failed for user "app"
$ docker run --rm --network pg-demo_default -e PGPASSWORD=change-this-password postgres:18 psql -h db -U app -c "SELECT current_user, inet_server_addr();"
current_user | inet_server_addr
--------------+------------------
app | 172.19.0.2
(1 row)
- Configuração da imagem oficial: conexões dentro do contêiner (Unix socket,
127.0.0.1,::1) usamtruste não verificam a senha. - Conexões de outras origens (a última linha,
host all all all) usam autenticação por senhascram-sha-256. - Ao conectar a
dba partir de outro contêiner na mesma rede Compose, uma senha incorreta resulta empassword authentication failed; com a senha correta, a conexão é estabelecida.
Assim, quem consegue entrar no contêiner pode operar o banco de dados diretamente. Por isso, proteja as permissões do Docker (consulte Segurança do Docker). Ao conectar do host pela porta mapeada com -p, o IP de origem é o gateway da rede Docker, e também é preciso informar a senha.
Conectando do host e de outros contêineres
postgres://app:senha@127.0.0.1:5432/app # Do host (ferramenta GUI, aplicativo)
postgres://app:senha@db:5432/app # De outro serviço do mesmo projeto Compose
Erros comuns de conexão
$ docker compose exec db psql -c "SELECT 1;"
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: role "root" does not exist
$ docker compose exec db psql -U postgres -c "SELECT 1;"
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: role "postgres" does not exist
$ docker compose exec db psql -U app -d shop -c "SELECT 1;"
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: database "shop" does not exist
$ docker compose exec -e PGPASSWORD=wrong db psql -h 127.0.0.1 -U app -c "SELECT 1;"
?column?
----------
1
(1 row)
$ docker compose exec db psql -U app -h 127.0.0.1 -p 5433 -c "SELECT 1;"
psql: error: connection to server at "127.0.0.1", port 5433 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
| Erro | Causa |
|---|---|
role "root" does not exist | Você não incluiu -U no psql, então ele usa por padrão o nome do usuário atual do sistema (dentro do contêiner, root) |
role "postgres" does not exist | Você definiu POSTGRES_USER, então o usuário padrão postgres não existe |
database "shop" does not exist | POSTGRES_DB só cria o banco durante a inicialização; você precisa executar CREATE DATABASE para os demais bancos |
Connection refused | A porta está incorreta, o banco ainda não terminou de iniciar ou você se conectou ao host errado |
password authentication failed | A senha está incorreta ou o Volume foi inicializado com outra senha |
Observe o quarto comando: dentro do contêiner, a conexão a 127.0.0.1 funciona mesmo com uma senha incorreta. Essa é a regra trust mencionada acima.
Backup e restauração
$ docker compose exec -T db pg_dump -U app app > app.sql
$ ls -lh app.sql && grep -E "^CREATE (TABLE|EXTENSION)" app.sql
-rw-r--r-- 1 root root 2.3K Oct 13 00:53 app.sql
CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public;
CREATE TABLE public.products (
$ docker compose exec -T db pg_dump -U app -Fc app > app.dump
$ ls -lh app.dump
-rw-r--r-- 1 root root 3.1K Oct 13 00:53 app.dump
$ docker compose exec db psql -U app -c "DROP TABLE products;"
DROP TABLE
$ docker compose exec -T db pg_restore -U app -d app --clean --if-exists < app.dump
$ docker compose exec db psql -U app -c "SELECT count(*) FROM products;"
count
-------
3
(1 row)
$ rm app.sql app.dump
| Comando | Descrição |
|---|---|
pg_dump app > app.sql | Exporta em texto SQL puro, que você pode ler diretamente e importar com psql |
pg_dump -Fc app > app.dump | Formato customizado, já compactado; restaure com pg_restore e escolha restaurar apenas algumas tabelas |
pg_restore --clean --if-exists | Exclui os objetos existentes antes da restauração para evitar duplicatas |
exec -T | O exec do Compose aloca um TTY por padrão. Ao usar redirecionamento, adicione -T para desativá-lo |
O backup inclui CREATE EXTENSION; ao restaurá-lo em um banco de dados novo, a extensão também será criada. Como este exemplo tem poucos dados, o formato customizado (3.1K) acaba sendo maior que o texto puro (2.3K). Com um volume maior de dados, o formato customizado fica bem menor.
Outros comandos comuns:
# Fazer backup de todos os bancos de dados e papéis (usuários e senhas)
docker compose exec -T db pg_dumpall -U app > all.sql
# Restaurar SQL em texto puro
docker compose exec -T db psql -U app -d app < app.sql
Você pode usar o cron com os comandos acima para fazer backups periódicos e copiar os arquivos para outra máquina ou para um armazenamento na nuvem.
Backup e restauração no Windows
O PowerShell não oferece suporte a <, e o > do Windows PowerShell 5.1 altera a codificação do arquivo. O backup binário de -Fc pode até ser corrompido diretamente. Em vez disso, use pg_dump -f para gerar o arquivo dentro do contêiner e depois copie-o com docker compose cp. Essa forma funciona em todos os sistemas:
# Backup
docker compose exec db pg_dump -U app -Fc -f /tmp/app.dump app
docker compose cp db:/tmp/app.dump app.dump
# Restauração
docker compose cp app.dump db:/tmp/restore.dump
docker compose exec db pg_restore -U app -d app --clean --if-exists /tmp/restore.dump
Esses comandos não usam $(pwd), < nem >, e funcionam diretamente no bash, PowerShell e CMD. Teste prático (criar uma tabela, fazer backup, excluí-la e restaurá-la):
$ docker compose exec db psql -U app -c 'CREATE TABLE t (id int); INSERT INTO t VALUES (1),(2);'
CREATE TABLE
INSERT 0 2
$ docker compose exec db pg_dump -U app -Fc -f /tmp/app.dump app
$ docker compose cp db:/tmp/app.dump app.dump
pgwin-db-1 Copying pgwin-db-1:/tmp/app.dump to app.dump
pgwin-db-1 Copied pgwin-db-1:/tmp/app.dump to app.dump
$ ls -l app.dump
-rw-rw-rw- 1 root root 1251 Oct 13 05:30 app.dump
$ docker compose exec db psql -U app -c 'DROP TABLE t;'
DROP TABLE
$ docker compose cp app.dump db:/tmp/restore.dump
pgwin-db-1 Copying app.dump to pgwin-db-1:/tmp/restore.dump
pgwin-db-1 Copied app.dump to pgwin-db-1:/tmp/restore.dump
$ docker compose exec db pg_restore -U app -d app /tmp/restore.dump
$ docker compose exec db psql -U app -c 'SELECT count(*) FROM t;'
count
-------
2
(1 row)
Atualização de versão principal (por exemplo, 16 → 18)
Para uma atualização de versão secundária (por exemplo, 18.5 → 18.6), basta baixar a nova imagem e recriar o contêiner. Nas versões principais, é diferente: os formatos dos arquivos de dados não são compatíveis entre versões principais diferentes do PostgreSQL.
Primeiro, crie alguns dados usando a versão 16:
$ docker run -d --name pg16 -e POSTGRES_PASSWORD=secret -v pg16data:/var/lib/postgresql/data postgres:16
20691764a98828d24c958eaaa71e83c08ebff29b984350ff7f6782ba8d74b4ca
$ docker exec pg16 psql -U postgres -c "CREATE TABLE notes (id serial PRIMARY KEY, body text); INSERT INTO notes (body) VALUES ('written by 16');"
CREATE TABLE
INSERT 0 1
$ docker stop pg16
pg16
Trocar a imagem diretamente falha
Abra os dados da versão 16 com postgres:18 (aqui, PGDATA especifica o caminho antigo para simular a troca direta da tag de 16 para 18):
$ docker run --name pg18 -e POSTGRES_PASSWORD=secret -e PGDATA=/var/lib/postgresql/data -v pg16data:/var/lib/postgresql/data postgres:18 2>&1 | tail -n 3
2026-10-13 00:54:09.740 UTC [1] FATAL: database files are incompatible with server
2026-10-13 00:54:09.740 UTC [1] DETAIL: The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 18.6 (Debian 18.6-1.pgdg13+2).
$ docker rm pg18
pg18
database files are incompatible with server: o diretório de dados foi inicializado pela versão 16, e a versão 18.6 não pode usá-lo.
Exportar e importar
O método mais simples e seguro é exportar todos os dados com o pg_dumpall da versão antiga e importá-los em um novo Volume da versão nova.
$ docker start pg16
pg16
$ docker exec pg16 pg_dumpall -U postgres > upgrade.sql && ls -lh upgrade.sql
-rw-r--r-- 1 root root 3.4K Oct 13 00:54 upgrade.sql
$ docker run -d --name pg18 -e POSTGRES_PASSWORD=secret -v pg18data:/var/lib/postgresql postgres:18
ec651837b76a0c9cc8b2468ec5a2ff4002334dcf015514ef94490a6c38cfe73d
$ docker exec -i pg18 psql -U postgres -q < upgrade.sql
ERROR: role "postgres" already exists
set_config
------------
(1 row)
set_config
------------
(1 row)
setval
--------
1
(1 row)
$ docker exec pg18 psql -U postgres -c "SHOW server_version;" -c "SELECT * FROM notes;"
server_version
-------------------------------
18.6 (Debian 18.6-1.pgdg13+2)
(1 row)
id | body
----+---------------
1 | written by 16
(1 row)
$ rm upgrade.sql
- Você pode ignorar o
ERROR: role "postgres" already existsdurante a importação: o novo contêiner da versão 18 já criou o usuáriopostgres, e a saída dopg_dumpalltenta criá-lo novamente. - Por fim, confirme que a versão é 18.6 e que os dados gravados pela versão 16, como
written by 16, estão presentes. - Observe que o Volume do novo contêiner está montado em
/var/lib/postgresql(o novo caminho da versão 18).
Depois de confirmar que os dados e o aplicativo estão funcionando, exclua o contêiner e o Volume antigos. Se o volume de dados for muito grande e você não puder aceitar um longo período de inatividade, considere usar pg_upgrade ou replicação lógica (logical replication), mas as etapas são bem mais complexas. Faça um ensaio em um ambiente de testes primeiro.
Resumo
- O Volume do PostgreSQL 18 é montado em
/var/lib/postgresql. - A verificação de integridade usa
pg_isready -h 127.0.0.1. - As conexões dentro do contêiner usam trust; as conexões externas precisam de senha.
- Para atualizar a versão principal: exporte com o
pg_dumpallda versão antiga e importe em um novo Volume da versão nova.
Exercícios
Exercício 1: Use o psql para criar uma tabela notes no banco de dados app e, em seguida, confirme com \dt.
Resposta
docker compose exec db psql -U app -c "CREATE TABLE notes (id serial PRIMARY KEY, body text);"
docker compose exec db psql -U app -c "\dt"
Exercício 2: Qual é a diferença entre fazer um backup no formato personalizado (-Fc) e em SQL de texto simples?
Resposta
O formato personalizado é compactado e precisa ser restaurado com pg_restore; você pode optar por restaurar apenas algumas tabelas. O formato de texto simples pode ser lido diretamente e importado com psql.
Perguntas frequentes
postgres:18 inicia e encerra logo em seguida?
Na versão 18, monte /var/lib/postgresql. Se montar o caminho antigo /var/lib/postgresql/data, o contêiner encerra ao detectar um diretório incompatível. Veja o teste neste capítulo.
Como atualizar uma versão menor (18.5 → 18.6)?
Basta baixar a nova imagem e recriar o contêiner: docker compose pull db && docker compose up -d db. Só é preciso exportar e importar ao atualizar uma versão principal.
pg_restore falha no Windows?
O PowerShell não oferece suporte a <, e o > da versão 5.1 corrompe backups binários. Gere o arquivo dentro do contêiner com pg_dump -f e copie-o com docker compose cp. Este capítulo inclui os comandos.
Atualizado 14 de outubro de 2026