How to Configure Testcontainers to Run on Podman
Testcontainers is a popular Java library that simplifies integration testing by providing lightweight, disposable containers for databases, message brokers, and other services. Traditionally, Testcontainers relies on Docker to manage these containers. However, many developers are adopting Podman as a Docker alternative because of its daemonless architecture, rootless containers, and compatibility with Docker CLI commands. Configuring Testcontainers to work with Podman requires some additional setup. This article provides a guide on how to do just that.
1. What Is Podman and Why Use It with Testcontainers?
Podman is a container engine that runs without a central daemon, making it more secure and lightweight compared to Docker. It supports running containers in both root and rootless modes and implements much of Docker’s command-line interface, allowing developers to use familiar commands. Importantly for Testcontainers, Podman can provide a Docker-compatible API socket, enabling Testcontainers to communicate with it just as it would with a Docker daemon.
2. Prerequisites
- Before configuring Testcontainers to work with Podman, ensure that Podman is installed on your system, which can be confirmed by running the
podman --versioncommand. - Podman socket is enabled: Testcontainers communicates with Podman through a Docker-compatible API socket.
- Java and Maven/Gradle are set up: Testcontainers is a Java library, so a working Java environment is necessary.
3. Enabling the Podman Docker-Compatible Socket
Testcontainers communicates with a container engine via a Docker API socket. With Podman, this socket must be explicitly enabled:
On Linux, start the Podman service and enable its socket:
systemctl --user enable --now podman.socket
Verify the socket is running:
ls -la /run/user/$UID/podman/podman.sock
This socket file implements a Docker-compatible API that Testcontainers can communicate with.
On macOS, Podman runs containers inside a lightweight virtual machine rather than directly on the host. Before Testcontainers can interact with Podman, this virtual machine must be created and its internal Docker-compatible socket exposed to the host system.
Start by initializing a Podman machine, which will serve as the environment where containers are executed
podman machine init
Once initialized, start the virtual machine:
podman machine start
After the machine is running, verify its connectivity and inspect the available Podman connections:
podman system connection list
The output information provides two critical details: the SSH port used to connect to the Podman machine and the path to the internal podman.sock file. With these values, the socket can be forwarded to the host.
Alternatively, you can directly inspect the Podman machine to determine the path of the Docker-compatible socket. After ensuring the Podman machine is running:
podman machine start
podman machine inspect --format '{{.ConnectionInfo.PodmanSocket.Path}}'
This command outputs the exact location of the podman.sock file inside the Podman virtual machine, which can then be used when exposing the socket to the host for Testcontainers integration.
4. Configuring Testcontainers for Podman
Setting Environment Variables
Testcontainers discovers the container runtime configuration through environment variables. To point Testcontainers at Podman’s socket, set the DOCKER_HOST environment variable to the Podman socket path. For example:
Linux:
export DOCKER_HOST=unix://${XDG_RUNTIME_DIR}/podman/podman.sock
export TESTCONTAINERS_RYUK_DISABLED=true
macOS (using forwarded socket):
export DOCKER_HOST=unix://$(podman machine inspect --format '{{.ConnectionInfo.PodmanSocket.Path}}')
export TESTCONTAINERS_RYUK_DISABLED=true
The TESTCONTAINERS_RYUK_DISABLED flag is often necessary because the Ryuk container cleanup component used by Testcontainers for Docker does not always work with Podman, especially in rootless setups5. Writing Tests with Testcontainers and Podman
Once Testcontainers is configured to communicate with Podman through a Docker-compatible socket, writing tests is identical to a standard Docker-based setup. The container lifecycle, port mappings, and connection details are handled transparently by Testcontainers.
Singleton PostgreSQL Container
When using Podman, especially with Ryuk disabled, it is common to manage container lifecycles explicitly. A singleton container pattern ensures the database starts only once and is reused across multiple test classes.
public class PostgreSQLTestContainer {
private static final PostgreSQLContainer<?> INSTANCE
= new PostgreSQLContainer<>("postgres:15-alpine")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
static {
INSTANCE.start();
Runtime.getRuntime().addShutdownHook(new Thread(INSTANCE::stop));
}
public static PostgreSQLContainer<?> getInstance() {
return INSTANCE;
}
}
Integration Test Using the Container
The test below connects to the PostgreSQL container, creates a table, inserts data, and verifies the result.
class PostgreSQLIntegrationTest {
private final PostgreSQLContainer<?> postgres = PostgreSQLTestContainer.getInstance();
@Test
void shouldInsertAndQueryData() throws Exception {
try (Connection connection = DriverManager.getConnection(
postgres.getJdbcUrl(),
postgres.getUsername(),
postgres.getPassword()
)) {
Statement statement = connection.createStatement();
statement.execute("""
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
)
""");
statement.execute("INSERT INTO users (name) VALUES ('Benjamin')");
ResultSet resultSet
= statement.executeQuery("SELECT COUNT(*) FROM users");
resultSet.next();
int count = resultSet.getInt(1);
assertEquals(1, count);
}
}
}
From the test’s perspective, there is no difference between Docker and Podman. Testcontainers communicates with the container runtime through the configured socket, and Podman responds using a Docker-compatible API. As long as the DOCKER_HOST environment variable points to the Podman socket and Ryuk is disabled when required, Testcontainers manages containers normally.
6. Conclusion
In this article, we explored how to configure Testcontainers to work with Podman by exposing a Docker-compatible Podman socket and directing Testcontainers to use it. We covered the concepts behind Podman’s execution model, walked through platform-specific setup steps, and demonstrated how to write and manage integration tests using Testcontainers with Podman. This approach allows us to continue using familiar testing tools while benefiting from a daemonless, secure container runtime in both local development and CI environments.
This article explained how to configure Testcontainers to work with Podman in Java projects.







