C# + DockerCompose - 在尝试连接之前等待 MS SQL 服务器 Docker 容器启动
C# + DockerCompose - Wait for MS SQL Server Docker container to be up before trying to connect
我正在尝试为我的微服务创建类似于 Spotify's approach 的集成测试。
我仍在研究如何启动和播种数据库。
目前我有一个 .NET Core 2.0 项目 FluentDocker v2.2.15 and DbUp 4.1.0.
我使用 FluentDocker 调用 DockerCompose 并启动我的服务,包括 SQL Server container
var hosts = new Hosts().Discover();
var dockerHost = hosts.FirstOrDefault(x => x.IsNative) ?? hosts.FirstOrDefault(x => x.Name == "default");
if (dockerHost == null)
{
return;
}
var composeFile = Args["composeFile"];
var result = dockerHost.Host.ComposeUp(composeFile: composeFile);
然后我使用 DbUp 运行 我的脚本并为数据库播种。
var connectionString = Args["connectionString"];
var scriptsPath = Args["scriptsPath"];
EnsureDatabase.For.SqlDatabase(connectionString);
var upgradeEngine = DeployChanges.To.SqlDatabase(connectionString).WithScriptsFromFileSystem(scriptsPath).Build();
var result = upgradeEngine.PerformUpgrade();
当我给 SQL 服务器足够的时间启动时,我可以 运行 成功,例如,在调试时。但是,如果我 运行 全速执行此操作,则 DbUp 会在尚未准备好时尝试连接到 SQL 服务器。
FluentDocker 有一个 WaitForPort
方法,但它似乎不适用于 DockerCompose API.
我想知道是否有办法在 运行 脚本之前等待 SQL 服务器的端口 1433 响应(不包括非确定性策略,例如 await Task.Delay
) 或者是否有其他库允许我进行这种控制。
谢谢
您可以在 FluentDocker v2 中使用 WaitForPort
、WaitForProcess
、WaitForHttp
或自定义 lambda Wait
函数.6.2.例如:
给定 docker-compose 文件:
version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
volumes:
db_data:
文件指定wordpress依赖db,因此先启动db,再实例化wordpress容器。但要确保在
wordpress 网络是 运行 的 using
子句,您需要使用 HTTP 来确定这一点。可以使用FluentAPI来实例化,这样等待服务启动。
var file = Path.Combine(Directory.GetCurrentDirectory(),
(TemplateString) "Resources/ComposeTests/WordPress/docker-compose.yml");
using (new Builder()
.UseContainer()
.UseCompose()
.FromFile(file)
.RemoveOrphans()
.Wait("wordpress", (service, cnt) => {
if (cnt > 60) throw new FluentDockerException("Failed to wait for wordpress service");
var res = HttpExtensions.DoRequest("http://localhost:8000/wp-admin/install.php").Result;
return (res.Code == HttpStatusCode.OK &&
res.Body.IndexOf("https://wordpress.org/", StringComparison.Ordinal) != -1) ? 0 : 500;
})
.Build().Start())
{
// Since we have waited - this shall now always work.
var installPage = await "http://localhost:8000/wp-admin/install.php".Wget();
Assert.IsTrue(installPage.IndexOf("https://wordpress.org/", StringComparison.Ordinal) != -1);
}
(上面的示例比较繁琐WaitForHttp
但是使用自定义lambda来说明这一点)。
通过这种方式,您甚至可以使用 db 连接 并在继续之前查询 table。
Return 大于零的值是等待下一次测试的时间。零及以下将成功结束等待。异常将终止等待(并失败)。
上面的例子使用了FluentAPI语法,但是你可以手动添加一个钩子到compose容器上,然后自己使用扩展。
干杯,
马里奥
我正在尝试为我的微服务创建类似于 Spotify's approach 的集成测试。
我仍在研究如何启动和播种数据库。 目前我有一个 .NET Core 2.0 项目 FluentDocker v2.2.15 and DbUp 4.1.0.
我使用 FluentDocker 调用 DockerCompose 并启动我的服务,包括 SQL Server container
var hosts = new Hosts().Discover();
var dockerHost = hosts.FirstOrDefault(x => x.IsNative) ?? hosts.FirstOrDefault(x => x.Name == "default");
if (dockerHost == null)
{
return;
}
var composeFile = Args["composeFile"];
var result = dockerHost.Host.ComposeUp(composeFile: composeFile);
然后我使用 DbUp 运行 我的脚本并为数据库播种。
var connectionString = Args["connectionString"];
var scriptsPath = Args["scriptsPath"];
EnsureDatabase.For.SqlDatabase(connectionString);
var upgradeEngine = DeployChanges.To.SqlDatabase(connectionString).WithScriptsFromFileSystem(scriptsPath).Build();
var result = upgradeEngine.PerformUpgrade();
当我给 SQL 服务器足够的时间启动时,我可以 运行 成功,例如,在调试时。但是,如果我 运行 全速执行此操作,则 DbUp 会在尚未准备好时尝试连接到 SQL 服务器。
FluentDocker 有一个 WaitForPort
方法,但它似乎不适用于 DockerCompose API.
我想知道是否有办法在 运行 脚本之前等待 SQL 服务器的端口 1433 响应(不包括非确定性策略,例如 await Task.Delay
) 或者是否有其他库允许我进行这种控制。
谢谢
您可以在 FluentDocker v2 中使用 WaitForPort
、WaitForProcess
、WaitForHttp
或自定义 lambda Wait
函数.6.2.例如:
给定 docker-compose 文件:
version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
volumes:
db_data:
文件指定wordpress依赖db,因此先启动db,再实例化wordpress容器。但要确保在
wordpress 网络是 运行 的 using
子句,您需要使用 HTTP 来确定这一点。可以使用FluentAPI来实例化,这样等待服务启动。
var file = Path.Combine(Directory.GetCurrentDirectory(),
(TemplateString) "Resources/ComposeTests/WordPress/docker-compose.yml");
using (new Builder()
.UseContainer()
.UseCompose()
.FromFile(file)
.RemoveOrphans()
.Wait("wordpress", (service, cnt) => {
if (cnt > 60) throw new FluentDockerException("Failed to wait for wordpress service");
var res = HttpExtensions.DoRequest("http://localhost:8000/wp-admin/install.php").Result;
return (res.Code == HttpStatusCode.OK &&
res.Body.IndexOf("https://wordpress.org/", StringComparison.Ordinal) != -1) ? 0 : 500;
})
.Build().Start())
{
// Since we have waited - this shall now always work.
var installPage = await "http://localhost:8000/wp-admin/install.php".Wget();
Assert.IsTrue(installPage.IndexOf("https://wordpress.org/", StringComparison.Ordinal) != -1);
}
(上面的示例比较繁琐WaitForHttp
但是使用自定义lambda来说明这一点)。
通过这种方式,您甚至可以使用 db 连接 并在继续之前查询 table。 Return 大于零的值是等待下一次测试的时间。零及以下将成功结束等待。异常将终止等待(并失败)。
上面的例子使用了FluentAPI语法,但是你可以手动添加一个钩子到compose容器上,然后自己使用扩展。
干杯, 马里奥