Testcontainers module for creating throwaway MySQL database containers for integration testing
This document covers the creation and configuration of MySQL containers including Docker image selection, database credentials, and MySQL server configuration overrides.
Constructor Options:
MySQLContainer(String dockerImageName) - String-based image nameMySQLContainer(DockerImageName dockerImageName) - Type-safe image name (recommended)Configuration Methods (Fluent Interface, Return SELF):
withDatabaseName(String databaseName) - Set database name (default: "test")withUsername(String username) - Set username (default: "test")withPassword(String password) - Set password (default: "test")withConfigurationOverride(String configPath) - Mount custom my.cnf files from classpath directoryGetter Methods:
getDatabaseName(): String - Returns configured database namegetUsername(): String - Returns configured usernamegetPassword(): String - Returns configured passwordConstraints:
start()Create a new MySQL container instance with a specified Docker image.
/**
* Creates a MySQL container with the specified Docker image name string.
* The image name should follow Docker image naming conventions (e.g., "mysql:8.0" or "mysql:5.7.34").
*
* @param dockerImageName the Docker image name as a string (e.g., "mysql:8.0", "mysql:5.7.34")
* @throws IllegalArgumentException if dockerImageName is null or empty
*/
MySQLContainer(String dockerImageName);
/**
* Creates a MySQL container with the specified DockerImageName object.
* This is the recommended constructor as it provides type safety and validation.
*
* @param dockerImageName the Docker image name as a DockerImageName object
* @throws IllegalArgumentException if dockerImageName is null
*/
MySQLContainer(DockerImageName dockerImageName);Usage Example:
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
// Using string image name
MySQLContainer<?> mysql1 = new MySQLContainer<>("mysql:8.0");
// Using DockerImageName (recommended)
MySQLContainer<?> mysql2 = new MySQLContainer<>(DockerImageName.parse("mysql:8.0.36"));Image Selection Guidelines:
Common Image Tags:
mysql:8.0 - Latest MySQL 8.0 (recommended)mysql:8.0.36 - Specific MySQL 8.0 patch versionmysql:5.7 - Latest MySQL 5.7mysql:5.7.34 - Specific MySQL 5.7 patch versionSet the name of the database to be created when the container starts.
/**
* Sets the name of the database to be created in the MySQL container.
* This database will be automatically created when the container starts.
* The database name cannot be changed after container creation.
*
* @param databaseName the database name (must be valid MySQL identifier)
* @return self for method chaining (SELF extends MySQLContainer<SELF>)
* @throws IllegalArgumentException if databaseName is null or empty
*/
SELF withDatabaseName(String databaseName);
/**
* Gets the configured database name.
* Returns the default value "test" if not explicitly set.
*
* @return the database name (default: "test")
*/
String getDatabaseName();Usage Example:
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("myapp_test");
mysql.start();
String dbName = mysql.getDatabaseName(); // "myapp_test"Important Notes:
Valid Database Names:
"testdb", "myapp_test", "integration_test_db""test db" (spaces), "test-db" (hyphens), "SELECT" (reserved keyword)Set the username for database connections.
/**
* Sets the username for database connections.
* If set to "root", special behavior applies for password handling.
* The username cannot be changed after container creation.
*
* @param username the database username (must be valid MySQL identifier)
* @return self for method chaining (SELF extends MySQLContainer<SELF>)
* @throws IllegalArgumentException if username is null or empty
*/
SELF withUsername(String username);
/**
* Gets the configured username.
* Returns the default value "test" if not explicitly set.
*
* @return the username (default: "test")
*/
String getUsername();Usage Example:
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withUsername("myuser");
mysql.start();
String user = mysql.getUsername(); // "myuser"Important Notes:
MYSQL_ROOT_HOST to allow root login from any host (typically set to "%")ContainerLaunchExceptionRoot User Special Case:
// Root user with empty password requires MYSQL_ROOT_HOST
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withUsername("root")
.withPassword("")
.withEnv("MYSQL_ROOT_HOST", "%"); // Required for root with empty passwordSet the password for database connections.
/**
* Sets the password for database connections.
* The password applies to both the configured user and the root user.
* The password cannot be changed after container creation.
*
* @param password the database password (can be empty string for root user only)
* @return self for method chaining (SELF extends MySQLContainer<SELF>)
* @throws IllegalArgumentException if password is null
*/
SELF withPassword(String password);
/**
* Gets the configured password.
* Returns the default value "test" if not explicitly set.
*
* @return the password (default: "test")
*/
String getPassword();Usage Example:
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withUsername("myuser")
.withPassword("mypassword");
mysql.start();
String pwd = mysql.getPassword(); // "mypassword"Password Behavior:
MYSQL_ROOT_HOST environment variable is set)ContainerLaunchException at startupError Scenario: Empty Password with Non-Root User
// This will throw ContainerLaunchException
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withUsername("testuser")
.withPassword(""); // Empty password not allowed for non-root user
mysql.start(); // Throws ContainerLaunchExceptionSolution:
// Use root user with MYSQL_ROOT_HOST
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withUsername("root")
.withPassword("")
.withEnv("MYSQL_ROOT_HOST", "%");Mount custom MySQL configuration files (my.cnf) to override server settings.
/**
* Mounts custom MySQL configuration files from a classpath directory.
* All .cnf files in the specified directory will be mapped to /etc/mysql/conf.d
* in the container, allowing MySQL server settings to be overridden.
* Configuration is applied at container startup and cannot be changed without restart.
*
* @param configPath path to a directory on the classpath containing .cnf files
* @return self for method chaining (SELF extends MySQLContainer<SELF>)
* @throws IllegalArgumentException if configPath is null or empty
* @throws ContainerLaunchException if configPath does not exist on classpath or contains no .cnf files
*/
SELF withConfigurationOverride(String configPath);Usage Example:
// Assumes somepath/mysql_conf_override is a directory on the classpath
// containing .cnf files (e.g., custom.cnf)
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withConfigurationOverride("somepath/mysql_conf_override");
mysql.start();Configuration Override Details:
src/test/resources/).cnf files in that directory will be mounted into the container/etc/mysql/conf.d/ within the containerExample my.cnf override file:
[mysqld]
innodb_max_undo_log_size=20000000
max_connections=500
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
innodb_buffer_pool_size=1GCommon Configuration Overrides:
max_connections - Maximum concurrent connectionsinnodb_buffer_pool_size - InnoDB buffer pool sizecharacter-set-server - Server character set (e.g., "utf8mb4")collation-server - Server collationinnodb_log_file_size - InnoDB log file sizemax_allowed_packet - Maximum packet sizewait_timeout - Connection timeoutinteractive_timeout - Interactive session timeoutimport org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
try (MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0.36"))
.withDatabaseName("integration_test_db")
.withUsername("testuser")
.withPassword("testpass123")
.withConfigurationOverride("mysql-config")) {
mysql.start();
// Container is ready with custom configuration
String jdbcUrl = mysql.getJdbcUrl();
// jdbc:mysql://localhost:xxxxx/integration_test_db?useSSL=false&allowPublicKeyRetrieval=true
}import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
// Using root user with empty password
try (MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withDatabaseName("testdb")
.withUsername("root")
.withPassword("")
.withEnv("MYSQL_ROOT_HOST", "%")) { // Required for root with empty password
mysql.start();
// Container is ready for root access with no password
}Root User Notes:
MYSQL_ROOT_HOST environment variable when using empty passwordMYSQL_ROOT_HOST to "%" to allow root login from any hostContainerLaunchException: Empty password with non-root user
// This will throw ContainerLaunchException
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withUsername("testuser")
.withPassword(""); // Empty password not allowed for non-root user
mysql.start(); // Throws ContainerLaunchExceptionSolution:
// Use root user with MYSQL_ROOT_HOST
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withUsername("root")
.withPassword("")
.withEnv("MYSQL_ROOT_HOST", "%");ContainerLaunchException: Invalid configuration override path
// This will throw ContainerLaunchException if path doesn't exist
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withConfigurationOverride("nonexistent/path");
mysql.start(); // Throws ContainerLaunchExceptionSolution:
// Ensure path exists on classpath and contains .cnf files
// Place files in src/test/resources/mysql-config/
MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
.withConfigurationOverride("mysql-config"); // Valid classpath pathIllegalArgumentException: Null or empty parameters
// These will throw IllegalArgumentException
new MySQLContainer<>((String) null);
new MySQLContainer<>((DockerImageName) null);
mysql.withDatabaseName(null);
mysql.withUsername("");start() to catch errors earlyInstall with Tessl CLI
npx tessl i tessl/maven-org-testcontainers--mysql