docker
testcontainers
postgresql.conf
configuration
containers

How do you include postgresql.conf on docker container when using org.testcontainers

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

When using Testcontainers with PostgreSQL, you usually do not "edit the container image" just to change a few database settings. The common pattern is to copy a config file into the container or pass PostgreSQL -c options at startup. The right choice depends on whether you need a full custom postgresql.conf or only a handful of parameter overrides.

The Smallest Solution: Pass -c Settings

If you only need a few configuration changes, the cleanest approach is often to override the server command instead of shipping a whole config file.

java
1import org.testcontainers.containers.PostgreSQLContainer;
2
3PostgreSQLContainer<?> postgres =
4    new PostgreSQLContainer<>("postgres:16")
5        .withCommand(
6            "postgres",
7            "-c", "shared_buffers=128MB",
8            "-c", "fsync=off",
9            "-c", "log_statement=all"
10        );
11
12postgres.start();

This is usually enough for test-specific tuning and keeps the setup obvious in the test code itself.

Copy a Custom postgresql.conf into the Container

If you really need a full config file, copy it into the container and tell PostgreSQL to use it.

java
1import org.testcontainers.containers.PostgreSQLContainer;
2import org.testcontainers.utility.MountableFile;
3
4PostgreSQLContainer<?> postgres =
5    new PostgreSQLContainer<>("postgres:16")
6        .withCopyFileToContainer(
7            MountableFile.forClasspathResource("postgresql.conf"),
8            "/etc/postgresql/postgresql.conf"
9        )
10        .withCommand(
11            "postgres",
12            "-c", "config_file=/etc/postgresql/postgresql.conf"
13        );
14
15postgres.start();

This approach works because PostgreSQL accepts config_file=... as a startup parameter. Testcontainers just needs to make sure the file exists in the container before startup.

Put the File on the Test Classpath

The MountableFile.forClasspathResource(...) call means the config file should usually live under your test resources, for example:

text
src/test/resources/postgresql.conf

That keeps the file versioned with the tests and avoids hard-coded local filesystem paths that break on CI machines.

A minimal postgresql.conf for test use might be:

conf
1listen_addresses = '*'
2shared_buffers = 128MB
3fsync = off
4log_statement = 'all'

In practice, keep the file as small as possible. It is easier to review and less likely to drift from the container image defaults in surprising ways.

Prefer Overrides When the Goal Is Only a Few Knobs

Using a full custom config file is powerful, but it is also heavier. It can make tests more fragile because you are now responsible for more of the server startup environment.

Use a full file when:

  • you need many settings
  • you want to keep the config under version control as one artifact
  • the settings are easier to reason about as a single PostgreSQL config file

Use withCommand(... "-c" ...) when:

  • you only need a few parameters
  • you want the test setup to stay local and explicit
  • you do not want to maintain a parallel config file

Verify That the Settings Took Effect

Do not assume the copied file or startup flags worked. Check from SQL:

java
1try (var connection = java.sql.DriverManager.getConnection(
2        postgres.getJdbcUrl(),
3        postgres.getUsername(),
4        postgres.getPassword());
5     var statement = connection.createStatement();
6     var rs = statement.executeQuery("show log_statement")) {
7
8    if (rs.next()) {
9        System.out.println(rs.getString(1));
10    }
11}

That makes configuration mistakes visible during test setup instead of leaving you guessing whether PostgreSQL read the intended file.

Keep in Mind What the Image Already Does

The official PostgreSQL container has its own initialization behavior around the data directory and startup entrypoint. That means copying a config file into one path does nothing unless PostgreSQL is actually told to use that file. Simply putting postgresql.conf somewhere in the container is not enough.

That is the core mistake in many broken Testcontainers examples: the file exists, but the server is still starting with its default config location.

Common Pitfalls

  • Copying postgresql.conf into the container without telling PostgreSQL to use it.
  • Using local filesystem paths in tests instead of classpath resources.
  • Replacing the whole config file when a few -c overrides would be simpler.
  • Assuming the config took effect without checking with SHOW queries.
  • Making the test config too different from the intended production behavior and then drawing the wrong conclusions from test results.

Summary

  • For a few settings, withCommand("postgres", "-c", "...") is usually the easiest solution.
  • For a full custom postgresql.conf, copy the file into the container and point PostgreSQL at it with config_file=....
  • Store the config under test resources so it works locally and in CI.
  • Verify the active settings from SQL instead of assuming startup did what you expected.
  • Keep the customization as small as possible to reduce test fragility.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.