start static method
Future<DockerProcess>
start({
- required String image,
- required String name,
- String? dockerExecutable,
- String? dockerCommand,
- List<
String> ? dockerArgs, - String? network,
- String? hostname,
- Map<
String, String> ? environment, - List<
String> ? ports, - List<
String> ? imageArgs, - bool sudo = false,
- bool verbose = false,
- bool? cleanup,
- FutureOr<
bool> readySignal(- String line
- Duration? timeout,
Starts a docker container.
Implementation
static Future<DockerProcess> start({
required String image,
required String name,
String? dockerExecutable,
String? dockerCommand,
List<String>? dockerArgs,
String? network,
String? hostname,
Map<String, String>? environment,
List<String>? ports,
List<String>? imageArgs,
bool sudo = false,
bool verbose = false,
bool? cleanup,
FutureOr<bool> Function(String line)? readySignal,
Duration? timeout,
}) async {
dockerExecutable ??= 'docker';
cleanup ??= false;
var command = dockerExecutable;
final args = <String>[];
final lines = <String>[];
if (sudo) {
args.add(command);
command = 'sudo';
}
dockerCommand ??= readySignal == null ? 'start' : 'run';
args.add(dockerCommand);
if (cleanup) {
args.add('--rm');
}
args.addAll(<String>[
'--name',
name,
]);
if (network != null) {
args.add('--net');
args.add(network);
}
if (hostname != null) {
args.add('-h');
args.add(hostname);
}
ports?.forEach((p) {
args.add('-p');
args.add(p);
});
environment?.forEach((k, v) {
args.add('-e');
args.add('$k=$v');
});
if (dockerArgs != null && dockerArgs.isNotEmpty) {
args.addAll(dockerArgs);
}
args.add(image);
if (imageArgs != null) {
args.addAll(imageArgs);
}
_logger.info({
'starting': {'name': name, 'command': command, 'args': args},
});
if (readySignal != null) {
final process = await Process.start(command, args);
final c = Completer<void>();
final timer = Timer(timeout ?? const Duration(minutes: 1), () {
if (c.isCompleted) return;
stderr.writeAll(lines, '\n');
c.completeError('timeout');
});
StreamSubscription<void>? subs1;
StreamSubscription<void>? subs2;
StreamSubscription<void> subs(Stream<List<int>> stream) {
return stream
.transform(utf8.decoder)
.transform(LineSplitter())
.listen((String line) async {
if (verbose) {
stdout.writeln(line);
}
lines.add(line);
if (await readySignal(line)) {
await subs1?.cancel();
subs1 = null;
await subs2?.cancel();
subs2 = null;
if (c.isCompleted) return;
c.complete();
}
});
}
subs1 = subs(process.stdout);
subs2 = subs(process.stderr);
final dp = DockerProcess._(dockerExecutable, name);
try {
await c.future;
} catch (_) {
await dp.kill();
rethrow;
} finally {
timer.cancel();
}
return dp;
} else {
final pr = await Process.run(command, args);
if (pr.exitCode != 0) {
stderr.writeAll(lines, '\n');
throw Exception(
'exitCode: ${pr.exitCode}\n\n'
'stdout: ${pr.stdout}\n\n'
'stderr: ${pr.stderr}',
);
}
return DockerProcess._(dockerExecutable, name);
}
}