or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-testcontainers--mysql

MySQL module for Testcontainers that enables programmatic creation and management of ephemeral MySQL database containers for testing Node.js applications.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@testcontainers/mysql@11.9.x

To install, run

npx @tessl/cli install tessl/npm-testcontainers--mysql@11.9.0

index.mddocs/

Testcontainers MySQL

Testcontainers MySQL is a specialized module that provides a fluent API for programmatically creating and managing ephemeral MySQL database containers for testing Node.js applications. It extends the base Testcontainers library with MySQL-specific configuration and connection management capabilities.

Package Information

  • Package Name: @testcontainers/mysql
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @testcontainers/mysql

Core Imports

import { MySqlContainer, StartedMySqlContainer } from "@testcontainers/mysql";

For CommonJS:

const { MySqlContainer, StartedMySqlContainer } = require("@testcontainers/mysql");

Basic Usage

import { MySqlContainer } from "@testcontainers/mysql";
import { createConnection } from "mysql2/promise";

// Start a MySQL container with default settings
await using container = await new MySqlContainer("mysql:8.0").start();

// Connect using mysql2 client
const client = await createConnection({
  host: container.getHost(),
  port: container.getPort(),
  database: container.getDatabase(),
  user: container.getUsername(),
  password: container.getUserPassword(),
});

// Execute queries
const [rows] = await client.execute("SELECT 1 as result");
console.log(rows); // [{ result: 1 }]

await client.end();
// Container automatically disposed with 'await using'

Architecture

The module consists of two main classes:

  • MySqlContainer: Extends GenericContainer from testcontainers, providing MySQL-specific configuration methods in a fluent builder pattern
  • StartedMySqlContainer: Extends AbstractStartedContainer from testcontainers, representing a running container with access to MySQL-specific connection details and query execution

The module automatically configures MySQL environment variables, exposes port 3306, and provides convenient methods for obtaining connection details.

Capabilities

Container Configuration

Configure and start a MySQL container with custom settings.

class MySqlContainer extends GenericContainer {
  /**
   * Create a new MySQL container configuration
   * @param image - Docker image name (e.g., "mysql:8.0", "mysql:5.7")
   */
  constructor(image: string);

  /**
   * Set the MySQL database name to be created
   * @param database - Database name (default: "test")
   * @returns this for method chaining
   */
  withDatabase(database: string): this;

  /**
   * Set the MySQL username
   * @param username - Username for the MySQL user (default: "test")
   * @returns this for method chaining
   */
  withUsername(username: string): this;

  /**
   * Set the MySQL user password
   * @param userPassword - Password for the MySQL user (default: "test")
   * @returns this for method chaining
   */
  withUserPassword(userPassword: string): this;

  /**
   * Set the MySQL root password
   * @param rootPassword - Root user password (default: "test")
   * @returns this for method chaining
   */
  withRootPassword(rootPassword: string): this;

  /**
   * Start the MySQL container
   * @returns Promise resolving to a started container instance
   */
  start(): Promise<StartedMySqlContainer>;
}

Usage Examples:

// Custom database configuration
await using container = await new MySqlContainer("mysql:8.0")
  .withDatabase("myapp_test")
  .withUsername("app_user")
  .withUserPassword("secret123")
  .withRootPassword("rootsecret")
  .start();

// Use URI-based connection
const connectionUri = container.getConnectionUri();
// mysql://app_user:secret123@localhost:32768/myapp_test

Inherited Configuration Methods

MySqlContainer inherits extensive configuration capabilities from GenericContainer:

interface GenericContainer {
  /** Configure exposed ports */
  withExposedPorts(...ports: number[]): this;

  /** Set startup timeout in milliseconds (default for MySQL: 120000) */
  withStartupTimeout(startupTimeout: number): this;

  /** Set additional environment variables */
  withEnvironment(environment: Record<string, string>): this;

  /** Configure wait strategy before considering container ready */
  withWaitStrategy(waitStrategy: WaitStrategy): this;

  /** Set network mode */
  withNetworkMode(networkMode: string): this;

  /** Copy files to container before start */
  withCopyFilesToContainer(filesToCopy: FileToCopy[]): this;

  /** Set container command */
  withCommand(command: string[]): this;

  /** Set container entrypoint */
  withEntrypoint(entrypoint: string[]): this;

  /** Configure bind mounts */
  withBindMounts(bindMounts: BindMount[]): this;

  /** Configure tmpfs mounts */
  withTmpFs(tmpFs: TmpFs): this;

  /** Configure container health check */
  withHealthCheck(healthCheck: HealthCheck): this;

  /** Set log consumer for container output */
  withLogConsumer(consumer: (stream: Readable) => unknown): this;

  /** Set container user */
  withUser(user: string): this;

  /** Set working directory */
  withWorkingDir(workingDir: string): this;

  /** Enable privileged mode */
  withPrivilegedMode(): this;

  /** Set container labels */
  withLabels(labels: Labels): this;

  /** Set container name */
  withName(name: string): this;

  /** Enable container reuse across test runs */
  withReuse(): this;

  /** Enable automatic container removal after stop (default behavior) */
  withAutoRemove(): this;

  /** Set image pull policy */
  withPullPolicy(pullPolicy: ImagePullPolicy): this;
}

Connection Information Access

Retrieve connection details from a started MySQL container.

class StartedMySqlContainer extends AbstractStartedContainer {
  /**
   * Get the host port mapped to MySQL's internal port 3306
   * @returns The mapped port number
   */
  getPort(): number;

  /**
   * Get the database name
   * @returns Database name
   */
  getDatabase(): string;

  /**
   * Get the MySQL username
   * @returns Username
   */
  getUsername(): string;

  /**
   * Get the MySQL user password
   * @returns User password
   */
  getUserPassword(): string;

  /**
   * Get the MySQL root password
   * @returns Root password
   */
  getRootPassword(): string;

  /**
   * Generate a MySQL connection URI
   * @param isRoot - If true, use root credentials; if false, use user credentials (default: false)
   * @returns Connection URI in format mysql://user:password@host:port/database
   */
  getConnectionUri(isRoot?: boolean): string;
}

Usage Examples:

await using container = await new MySqlContainer("mysql:8.0")
  .withDatabase("testdb")
  .withUsername("testuser")
  .withUserPassword("testpass")
  .start();

// Individual connection details
const host = container.getHost();
const port = container.getPort();
const database = container.getDatabase();
const username = container.getUsername();
const password = container.getUserPassword();

// Full connection URI
const userUri = container.getConnectionUri(); // Uses user credentials
const rootUri = container.getConnectionUri(true); // Uses root credentials

Query Execution

Execute SQL queries directly within the container using the MySQL CLI.

class StartedMySqlContainer {
  /**
   * Execute a SQL query inside the container using MySQL CLI
   * @param query - SQL query to execute
   * @param additionalFlags - Optional additional CLI flags (default: [])
   * @param isRoot - If true, execute as root user; if false, use configured user (default: false)
   * @returns Promise resolving to query output as string
   * @throws Error if query execution fails (non-zero exit code)
   */
  executeQuery(
    query: string,
    additionalFlags?: string[],
    isRoot?: boolean
  ): Promise<string>;
}

Usage Examples:

await using container = await new MySqlContainer("mysql:8.0").start();

// Basic query execution
const result = await container.executeQuery("SELECT 1 as result");
// Output: "result\n1\n"

// Execute with additional CLI flags
const jsonResult = await container.executeQuery(
  "SELECT * FROM users",
  ["--json"]
);

// Execute as root user for admin operations
const adminResult = await container.executeQuery(
  "SHOW DATABASES",
  [],
  true
);

// Error handling
try {
  await container.executeQuery("INVALID SQL");
} catch (error) {
  console.error("Query failed:", error.message);
}

Container Lifecycle Management

Manage the container lifecycle with inherited methods from AbstractStartedContainer.

class StartedMySqlContainer {
  /**
   * Stop the container
   * @param options - Optional stop options
   * @returns Promise resolving to stopped container
   */
  stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;

  /**
   * Restart the container
   * @param options - Optional restart options
   * @returns Promise that resolves when restart completes
   */
  restart(options?: Partial<RestartOptions>): Promise<void>;

  /**
   * Get the container host address
   * @returns Host address (typically "localhost")
   */
  getHost(): string;

  /**
   * Get the container hostname
   * @returns Container hostname
   */
  getHostname(): string;

  /**
   * Get the container ID
   * @returns Docker container ID
   */
  getId(): string;

  /**
   * Get the container name
   * @returns Container name
   */
  getName(): string;

  /**
   * Get container labels
   * @returns Container labels object
   */
  getLabels(): Labels;

  /**
   * Async disposal for use with 'await using' syntax
   */
  [Symbol.asyncDispose](): Promise<void>;
}

Usage Examples:

// Manual lifecycle management
const container = await new MySqlContainer("mysql:8.0").start();

// Use the container
const client = await createConnection({
  host: container.getHost(),
  port: container.getPort(),
  database: container.getDatabase(),
  user: container.getUsername(),
  password: container.getUserPassword(),
});

// Restart the container
await container.restart();

// Manual cleanup
await container.stop();

// Automatic disposal (recommended)
await using container2 = await new MySqlContainer("mysql:8.0").start();
// Container automatically stopped when leaving scope

Network and Port Management

Access network-related information from a started container.

class StartedMySqlContainer {
  /**
   * Get the first mapped port
   * @returns First mapped port number
   */
  getFirstMappedPort(): number;

  /**
   * Get mapped port for a specific internal port
   * @param port - Internal container port or port with protocol (e.g., "3306/tcp")
   * @param protocol - Protocol ("tcp" or "udp"), defaults to "tcp"
   * @returns Mapped host port
   */
  getMappedPort(port: number, protocol?: string): number;
  getMappedPort(portWithProtocol: `${number}/${"tcp" | "udp"}`): number;

  /**
   * Get network names the container is connected to
   * @returns Array of network names
   */
  getNetworkNames(): string[];

  /**
   * Get network ID for a specific network name
   * @param networkName - Network name
   * @returns Network ID
   */
  getNetworkId(networkName: string): string;

  /**
   * Get container IP address in a specific network
   * @param networkName - Network name
   * @returns IP address in the specified network
   */
  getIpAddress(networkName: string): string;
}

File Operations

Copy files and directories to/from the running container.

class StartedMySqlContainer {
  /**
   * Copy files to the running container
   * @param filesToCopy - Array of file copy definitions
   * @returns Promise that resolves when copy completes
   */
  copyFilesToContainer(filesToCopy: FileToCopy[]): Promise<void>;

  /**
   * Copy directories to the running container
   * @param directoriesToCopy - Array of directory copy definitions
   * @returns Promise that resolves when copy completes
   */
  copyDirectoriesToContainer(directoriesToCopy: DirectoryToCopy[]): Promise<void>;

  /**
   * Copy content to the running container
   * @param contentsToCopy - Array of content copy definitions
   * @returns Promise that resolves when copy completes
   */
  copyContentToContainer(contentsToCopy: ContentToCopy[]): Promise<void>;

  /**
   * Copy tar archive to the container
   * @param tar - Readable stream containing tar archive
   * @param target - Target path in container (default: "/")
   * @returns Promise that resolves when copy completes
   */
  copyArchiveToContainer(tar: Readable, target?: string): Promise<void>;

  /**
   * Copy archive from the container
   * @param path - Path in container to copy from
   * @returns Promise resolving to readable stream of tar archive
   */
  copyArchiveFromContainer(path: string): Promise<NodeJS.ReadableStream>;
}

Command Execution and Logging

Execute commands and retrieve logs from the running container.

class StartedMySqlContainer {
  /**
   * Execute a command in the running container
   * @param command - Command as string or array of strings
   * @param opts - Optional execution options
   * @returns Promise resolving to execution result
   */
  exec(
    command: string | string[],
    opts?: Partial<ExecOptions>
  ): Promise<ExecResult>;

  /**
   * Get container logs
   * @param opts - Optional log options (since, tail)
   * @returns Promise resolving to readable stream of logs
   */
  logs(opts?: { since?: number; tail?: number }): Promise<Readable>;

  /**
   * Commit the container to a new image
   * @param options - Commit options
   * @returns Promise resolving to new image ID
   */
  commit(options: CommitOptions): Promise<string>;
}

Usage Examples:

await using container = await new MySqlContainer("mysql:8.0").start();

// Execute arbitrary commands
const result = await container.exec(["ls", "-la", "/var/lib/mysql"]);
console.log(result.output);

// Get container logs
const logStream = await container.logs({ tail: 100 });
logStream.on("data", (chunk) => console.log(chunk.toString()));

// Copy SQL initialization file
await container.copyFilesToContainer([
  {
    source: "/path/to/init.sql",
    target: "/docker-entrypoint-initdb.d/init.sql"
  }
]);

Types

From testcontainers Package

The following types are imported from the base testcontainers package and used in the API:

/** Options for stopping a container */
interface StopOptions {
  timeout?: number;
  remove?: boolean;
}

/** Options for restarting a container */
interface RestartOptions {
  timeout?: number;
}

/** Result of command execution */
interface ExecResult {
  output: string;
  exitCode: number;
}

/** Options for command execution */
interface ExecOptions {
  workingDir?: string;
  env?: Record<string, string>;
  user?: string;
  privileged?: boolean;
  cmd?: string[];
}

/** Options for committing a container to an image */
interface CommitOptions {
  reference?: string;
  comment?: string;
  author?: string;
  pause?: boolean;
  changes?: string[];
}

/** File to copy to container */
interface FileToCopy {
  source: string;
  target: string;
  mode?: number;
}

/** Directory to copy to container */
interface DirectoryToCopy {
  source: string;
  target: string;
  mode?: number;
}

/** Content to copy to container */
interface ContentToCopy {
  content: string | Buffer;
  target: string;
  mode?: number;
}

/** Container labels as key-value pairs */
type Labels = Record<string, string>;

/** Bind mount configuration */
interface BindMount {
  source: string;
  target: string;
  mode?: "rw" | "ro";
}

/** TmpFs mount configuration */
type TmpFs = Record<string, string>;

/** Health check configuration */
interface HealthCheck {
  test: string[];
  interval?: number;
  timeout?: number;
  retries?: number;
  startPeriod?: number;
}

/** Wait strategy interface */
interface WaitStrategy {
  waitUntilReady(container: StartedTestContainer): Promise<void>;
}

/** Image pull policy */
interface ImagePullPolicy {
  shouldPull(): boolean;
}

/** Stopped test container interface */
interface StoppedTestContainer {
  getId(): string;
  getName(): string;
}

Error Handling

The executeQuery method throws an error if the SQL query fails:

try {
  await container.executeQuery("SELECT * FROM nonexistent_table");
} catch (error) {
  // Error message includes exit code and query
  console.error(error.message);
  // "executeQuery failed with exit code 1 for query: SELECT * FROM nonexistent_table"
}

For connection errors with MySQL clients, use standard error handling for the respective client library (e.g., mysql2, mysql, etc.).