Get started with Testcontainers for Swift in 5 minutes.
Add to your Package.swift:
dependencies: [
.package(url: "https://github.com/dragosv/testcontainers-swift.git", from: "0.1.0")
]Or in Xcode:
- File → Add Packages
- Enter:
https://github.com/dragosv/testcontainers-swift.git - Select version and add to project
- Docker installed and running
- Swift 6.1 or later
- macOS, Linux, iOS, tvOS, or watchOS
import Testcontainers
// Create a PostgreSQL container
let postgres = try await PostgresContainer()
.withDatabase("mydb")
.withUsername("user")
.withPassword("password")
.start()
// Use the connection string
let connectionString = try postgres.getConnectionString()
print("Connected to: \(connectionString)")
// Clean up
try await postgres.stop()let container = try await ContainerBuilder("nginx:latest")
.withName("my-web-server")
.withPortBinding(80, assignRandomHostPort: true)
.withWaitStrategy(Wait.tcp(port: 80, timeout: 30))
.buildAsync()
try await container.start()
let port = try container.getMappedPort(80)
print("Nginx running on port: \(port)")
try await container.stop()import XCTest
import Testcontainers
class DatabaseTests: XCTestCase {
var db: PostgresContainerReference?
override func setUp() async throws {
try await super.setUp()
db = try await PostgresContainer()
.withDatabase("testdb")
.start()
}
override func tearDown() async throws {
try await db?.stop()
try await super.tearDown()
}
func testDatabase() throws {
let connectionString = try db?.getConnectionString()
XCTAssertNotNil(connectionString)
}
}let postgres = try await PostgresContainer(version: "15")
.withDatabase("testdb")
.start()
let url = try postgres.getConnectionString()let mysql = try await MySqlContainer(version: "8.0")
.withDatabase("testdb")
.start()
let url = try mysql.getConnectionString()let redis = try await RedisContainer(version: "7")
.start()
let url = try redis.getRedisURL()let mongo = try await MongoDbContainer(version: "6.0")
.start()
let url = try mongo.getConnectionString()let container = try await builder.buildAsync()
try await container.start()
defer { Task { try? await container.stop() } }
// Use container...let container = try await ContainerBuilder("postgres:15")
.withWaitStrategy(
Wait.all(
Wait.tcp(port: 5432),
Wait.log(message: "database system is ready")
)
)
.buildAsync()let builder = ContainerBuilder("postgres:15")
.withEnvironment([
"POSTGRES_DB": "testdb",
"POSTGRES_USER": "testuser",
"POSTGRES_PASSWORD": "testpass"
])let network = try await NetworkBuilder("app-network").build()
let db = try await ContainerBuilder("postgres:15")
.withNetwork(network)
.withNetworkAliases(["database"])
.buildAsync()
let app = try await ContainerBuilder("myapp:1.0")
.withNetwork(network)
.buildAsync()
// Now "app" can reach database at hostname "database"Issue: TestcontainersError.dockerNotAvailable
Solution: Ensure Docker is installed and running:
docker psSolution: Use random port assignment:
.withPortBinding(8080, assignRandomHostPort: true)Solution: Check the logs:
let logs = try await container.getLogs()
print(logs)Solution: Increase timeout or change strategy:
.withWaitStrategy(Wait.tcp(port: 5432, timeout: 120))- Read ARCHITECTURE.md for design details
- Check Examples for more use cases
- See Tests for integration patterns
- Visit Contributing to contribute
- Open an issue on GitHub
- Check existing issues and discussions
- Ask on Stack Overflow with
testcontainerstag - Join the Testcontainers Slack