import { PostgreSqlContainer } from '@testcontainers/postgresql'; import type { StartedNetwork } from 'testcontainers'; import { createSilentLogConsumer } from '../helpers/utils'; import { TEST_CONTAINER_IMAGES } from '../test-containers'; import type { Service, ServiceResult } from './types'; const HOSTNAME = 'postgres'; export interface PostgresMeta { database: string; username: string; password: string; } export type PostgresResult = ServiceResult; export const postgres: Service = { description: 'PostgreSQL database', shouldStart: (ctx) => ctx.usePostgres, async start(network: StartedNetwork, projectName: string): Promise { const { consumer, throwWithLogs } = createSilentLogConsumer(); const builder = new PostgreSqlContainer(TEST_CONTAINER_IMAGES.postgres) .withNetwork(network) .withNetworkAliases(HOSTNAME) .withDatabase('n8n_db') .withUsername('n8n_user') .withPassword('test_password') .withStartupTimeout(60000) .withLabels({ 'com.docker.compose.project': projectName, 'com.docker.compose.service': HOSTNAME, }) .withName(`${projectName}-${HOSTNAME}`) .withAddedCapabilities('NET_ADMIN') // Allows us to drop IP tables and block traffic .withTmpFs({ '/var/lib/postgresql': 'rw' }) .withCommand([ 'postgres', '-c', 'fsync=off', '-c', 'synchronous_commit=off', '-c', 'full_page_writes=off', '-c', 'max_connections=200', ]) .withReuse() .withLogConsumer(consumer); try { const container = await builder.start(); return { container, meta: { database: container.getDatabase(), username: container.getUsername(), password: container.getPassword(), }, }; } catch (error: unknown) { return throwWithLogs(error); } }, env(result: PostgresResult, external?: boolean): Record { return { DB_TYPE: 'postgresdb', DB_POSTGRESDB_HOST: external ? result.container.getHost() : HOSTNAME, DB_POSTGRESDB_PORT: external ? String(result.container.getMappedPort(5432)) : '5432', DB_POSTGRESDB_DATABASE: result.meta.database, DB_POSTGRESDB_USER: result.meta.username, DB_POSTGRESDB_PASSWORD: result.meta.password, }; }, };