Skip to content

Commit 955c955

Browse files
Merge pull request #24068 from igor-alexandrov/postgresql-guide
Postgresql guide
1 parent 8f0cf55 commit 955c955

5 files changed

Lines changed: 1196 additions & 0 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
title: PostgreSQL specific guide
3+
linkTitle: PostgreSQL
4+
description: Containerize PostgreSQL databases using Docker
5+
keywords: Docker, getting started, postgresql, language
6+
summary: |
7+
This guide explains how to containerize PostgreSQL databases using
8+
Docker.
9+
toc_min: 1
10+
toc_max: 2
11+
tags: [databases]
12+
params:
13+
time: 20 minutes
14+
---
15+
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
---
2+
title: Advanced Configuration and Initialization
3+
weight: 20
4+
description: Configure PostgreSQL initialization scripts, tune performance parameters, and set timezone and locale settings for containerized deployments.
5+
keywords:
6+
- PostgreSQL Docker
7+
- Docker Compose PostgreSQL
8+
- container database
9+
- PostgreSQL performance tuning
10+
---
11+
12+
With persistent storage configured in the previous section, you're ready to customize PostgreSQL for real-world use. This guide covers advanced configuration techniques for running PostgreSQL in Docker containers, including automated database initialization, performance tuning, and timezone configuration.
13+
14+
## Overview
15+
16+
While PostgreSQL containers can be started quickly with default settings, production environments require customized configurations. This guide explains how to:
17+
18+
- Automate database, schema, and user creation during container startup
19+
- Tune PostgreSQL performance parameters for containerized workloads
20+
- Configure timezone and locale settings
21+
22+
## Initialization scripts
23+
24+
The official PostgreSQL Docker image supports running initialization scripts automatically when the container starts for the first time. Any files placed in the `/docker-entrypoint-initdb.d/` directory are executed in alphabetical order.
25+
26+
### How initialization works
27+
28+
When the container starts, it checks whether the PostgreSQL data directory is empty. If the directory already contains data, PostgreSQL starts immediately without running any initialization. If the directory is empty, the container runs `initdb` to create a new database cluster, then executes all scripts in `/docker-entrypoint-initdb.d/` in alphabetical order before starting PostgreSQL.
29+
30+
### Supported file formats
31+
32+
| Format | Description |
33+
|--------|-------------|
34+
| `.sql` | SQL commands executed directly |
35+
| `.sql.gz` | Gzip-compressed SQL files |
36+
| `.sh` | Shell scripts executed with bash |
37+
38+
> [!IMPORTANT]
39+
>
40+
> Initialization scripts only run when the PostgreSQL data directory (`/var/lib/postgresql/data`) is empty. If you mount a volume containing existing data, initialization is skipped. This behavior prevents overwriting existing databases.
41+
42+
## Mounting initialization scripts
43+
44+
Use Docker Compose to mount initialization scripts into the container. First, create a project directory:
45+
46+
```console
47+
$ mkdir -p postgres-project/init-db
48+
$ cd postgres-project
49+
```
50+
51+
Create a `compose.yaml` file:
52+
53+
```yaml
54+
services:
55+
db:
56+
image: postgres:18
57+
volumes:
58+
- ./init-db:/docker-entrypoint-initdb.d
59+
- postgres_data:/var/lib/postgresql
60+
environment:
61+
POSTGRES_PASSWORD: mysecretpassword
62+
63+
volumes:
64+
postgres_data:
65+
```
66+
67+
All scripts in the `./init-db` directory execute when the container starts for the first time. This is great for bootstrapping databases.
68+
69+
## Initialization script example
70+
71+
Create a file named `init.sql` in your `init-db` directory:
72+
73+
```sql
74+
CREATE TABLE users (
75+
id SERIAL PRIMARY KEY,
76+
email VARCHAR(255) UNIQUE NOT NULL,
77+
name VARCHAR(100) NOT NULL,
78+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
79+
);
80+
```
81+
82+
This script runs automatically when the container starts for the first time, creating your initial database schema.
83+
84+
> [!NOTE]
85+
>
86+
> Ensure initialization scripts have proper read permissions. If you encounter "Permission denied" errors, run `chmod 644 init-db/*.sql` to make the files readable by the container.
87+
88+
## Performance tuning
89+
90+
Default PostgreSQL settings are conservative to work on systems with limited resources. For production workloads, you should tune these parameters based on your container's allocated resources.
91+
92+
### Method 1: Custom configuration file
93+
94+
For complete control, mount a custom `postgresql.conf` file. First, extract the default configuration:
95+
96+
```console
97+
$ docker run -i --rm postgres:18 cat /usr/share/postgresql/postgresql.conf.sample > my-postgres.conf
98+
```
99+
100+
Edit `my-postgres.conf` with your desired settings, then mount it in your Compose file:
101+
102+
```yaml
103+
services:
104+
db:
105+
image: postgres:18
106+
volumes:
107+
- ./my-postgres.conf:/etc/postgresql/postgresql.conf
108+
- ./init-db:/docker-entrypoint-initdb.d
109+
- postgres_data:/var/lib/postgresql
110+
command: postgres -c config_file=/etc/postgresql/postgresql.conf
111+
environment:
112+
POSTGRES_PASSWORD: mysecretpassword
113+
114+
volumes:
115+
postgres_data:
116+
```
117+
118+
## Key configuration parameters
119+
120+
The following tables list important `postgresql.conf` parameters for containerized PostgreSQL deployments.
121+
122+
### Connection settings
123+
124+
| Parameter | Description | Default |
125+
|-----------|-------------|---------|
126+
| `listen_addresses` | IP addresses to listen on | `localhost` |
127+
| `port` | TCP port number | `5432` |
128+
| `max_connections` | Maximum concurrent connections | `100` |
129+
130+
### Memory settings
131+
132+
| Parameter | Description | Recommended starting value |
133+
|-----------|-------------|---------------------------|
134+
| `shared_buffers` | Shared memory for caching | 25% of container memory |
135+
| `work_mem` | Memory per query operation | 4MB - 64MB |
136+
| `maintenance_work_mem` | Memory for VACUUM, CREATE INDEX | 64MB - 256MB |
137+
| `effective_cache_size` | Planner's cache size estimate | 50-75% of container memory |
138+
139+
#### Docker memory limits
140+
141+
When tuning memory parameters, set explicit memory limits on your container using `deploy.resources.limits.memory` in Compose or `--memory` with `docker run`. Without limits, PostgreSQL sees the host's total RAM and may allocate more than intended. For example, if your container should use 4GB maximum, set `shared_buffers` to approximately 1GB (25%).
142+
143+
### I/O settings
144+
145+
| Parameter | Description | Recommended starting value |
146+
|-----------|-------------|---------------------------|
147+
| `effective_io_concurrency` | Concurrent disk I/O operations | `200` for SSDs, `2` for HDDs |
148+
149+
### Timeout settings
150+
151+
| Parameter | Description | Default |
152+
|-----------|-------------|---------|
153+
| `statement_timeout` | Max time for any statement | `0` (disabled) |
154+
| `lock_timeout` | Max time to wait for a lock | `0` (disabled) |
155+
| `deadlock_timeout` | Time before checking for deadlock | `1s` |
156+
| `transaction_timeout` | Max time for a transaction | `0` (disabled) |
157+
158+
> [!NOTE]
159+
>
160+
> Setting `shared_buffers` too high in a container can exceed kernel shared memory limits. Use no more than 25-30% of the container's memory limit.
161+
162+
## Timezone and locale configuration
163+
164+
Proper localization ensures timestamps and sorting behave correctly for your application's users.
165+
166+
```yaml
167+
services:
168+
db:
169+
image: postgres:18
170+
volumes:
171+
- postgres_data:/var/lib/postgresql
172+
- /etc/localtime:/etc/localtime:ro
173+
- /etc/timezone:/etc/timezone:ro
174+
environment:
175+
POSTGRES_PASSWORD: mysecretpassword
176+
TZ: America/New_York
177+
178+
volumes:
179+
postgres_data:
180+
```
181+
182+
Alternatively, set the timezone using a PostgreSQL command-line parameter:
183+
184+
```yaml
185+
services:
186+
db:
187+
image: postgres:18
188+
command: ["postgres", "-c", "timezone=America/New_York"]
189+
environment:
190+
POSTGRES_PASSWORD: mysecretpassword
191+
```
192+
193+
### Setting the locale
194+
195+
Specify locale settings during database initialization using the `POSTGRES_INITDB_ARGS` environment variable:
196+
197+
```yaml
198+
services:
199+
db:
200+
image: postgres:18
201+
volumes:
202+
- postgres_data:/var/lib/postgresql
203+
environment:
204+
POSTGRES_PASSWORD: mysecretpassword
205+
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=en_US.UTF-8 --lc-ctype=en_US.UTF-8"
206+
207+
volumes:
208+
postgres_data:
209+
```
210+
211+
This affects collation (sorting) and character processing behavior. Changing this variable after database creation has no effect—it only applies during the first run when the data directory is initialized.
212+
213+
## Connecting to the database
214+
215+
You can interact with PostgreSQL running in a container even without `psql` installed on your host machine.
216+
217+
### Interactive shell
218+
219+
Open a `psql` session inside the container:
220+
221+
```console
222+
$ docker exec -it postgres-container psql -U postgres
223+
```
224+
225+
Connect to a specific database:
226+
227+
```console
228+
$ docker exec -it postgres-container psql -U postgres -d mydb
229+
```

0 commit comments

Comments
 (0)