0
# Compose Project Management
1
2
Complete Docker Compose project lifecycle management including service discovery, startup orchestration, health checking, and configuration extraction.
3
4
## Capabilities
5
6
### ComposeProject
7
8
Core class that wraps Docker Compose functionality and manages the complete lifecycle of compose-based services including startup, health checking, and shutdown.
9
10
```java { .api }
11
/**
12
* A wrapper around compose that starts and stops services defined in a set of compose files
13
*/
14
public class ComposeProject {
15
16
/**
17
* Constructor for ComposeProject with full configuration
18
* @param dockerClient Docker client for container operations
19
* @param composeFiles Compose files to manage
20
* @param executable Compose executable name (docker or podman)
21
* @param project Project name for compose services
22
* @param startupTimeout Maximum time to wait for service startup
23
* @param stopTimeout Maximum time to wait for service shutdown
24
* @param stopContainers Whether to stop containers on shutdown
25
* @param ryukEnabled Whether to enable Ryuk for cleanup
26
* @param followContainerLogs Whether to follow container logs
27
* @param removeVolumes Whether to remove volumes on shutdown
28
* @param removeImages Image removal strategy
29
* @param build Whether to build images before starting
30
* @param options Additional compose command options
31
* @param profiles Compose profiles to activate
32
* @param scalingPreferences Service scaling configuration
33
* @param env Environment variables
34
*/
35
public ComposeProject(
36
DockerClient dockerClient,
37
ComposeFiles composeFiles,
38
String executable,
39
String project,
40
Duration startupTimeout,
41
Duration stopTimeout,
42
boolean stopContainers,
43
boolean ryukEnabled,
44
boolean followContainerLogs,
45
boolean removeVolumes,
46
String removeImages,
47
Boolean build,
48
List<String> options,
49
List<String> profiles,
50
Map<String, Integer> scalingPreferences,
51
Map<String, String> env);
52
53
/**
54
* Gets the project name
55
* @return Project name
56
*/
57
public String getProject();
58
59
/**
60
* Starts all services defined in the compose files
61
*/
62
public synchronized void start();
63
64
/**
65
* Waits until all services are ready according to their wait strategies
66
* @param waitOn Executor for parallel waiting, null for default
67
*/
68
public void waitUntilServicesReady(Executor waitOn);
69
70
/**
71
* Combines start and wait operations
72
* @param waitOn Executor for parallel waiting
73
*/
74
public void startAndWaitUntilServicesReady(Executor waitOn);
75
76
/**
77
* Stops all services and cleans up resources
78
*/
79
public synchronized void stop();
80
81
/**
82
* Discovers running service instances
83
* @param checkForRequiredServices Whether to validate required services are running
84
*/
85
public synchronized void discoverServiceInstances(boolean checkForRequiredServices);
86
87
/**
88
* Runs a compose command with environment variables
89
* @param cmd Command to execute
90
* @param env Environment variables
91
*/
92
public void runWithCompose(String cmd, Map<String, String> env);
93
94
/**
95
* Gets list of running service instances
96
* @return List of service wait strategy targets
97
*/
98
public List<ComposeServiceWaitStrategyTarget> getServices();
99
100
/**
101
* Gets environment variable configuration from services
102
* @return Map of environment variable names to values
103
*/
104
public Map<String, String> getEnvVarConfig();
105
106
/**
107
* Gets exposed port configuration from services
108
* @return Map of configuration keys to port values
109
*/
110
public Map<String, String> getExposedPortConfig();
111
112
/**
113
* Gets list of Docker networks created by compose
114
* @return List of networks
115
*/
116
public List<Network> getNetworks();
117
118
/**
119
* Gets the default network ID for service communication
120
* @return Default network ID or fallback name
121
*/
122
public String getDefaultNetworkId();
123
}
124
```
125
126
**Usage Examples:**
127
128
```java
129
import io.quarkus.devservices.deployment.compose.*;
130
import java.time.Duration;
131
import java.util.concurrent.Executors;
132
133
// Create and start a compose project
134
List<File> composeFiles = List.of(new File("docker-compose.yml"));
135
ComposeFiles files = new ComposeFiles(composeFiles);
136
137
ComposeProject project = new ComposeProject.Builder(files, "docker")
138
.withProject("my-dev-services")
139
.withStartupTimeout(Duration.ofMinutes(2))
140
.withStopContainers(true)
141
.withRyukEnabled(true)
142
.withFollowContainerLogs(true)
143
.withEnv(Map.of("POSTGRES_PASSWORD", "secret"))
144
.build();
145
146
// Start services and wait for readiness
147
project.start();
148
project.waitUntilServicesReady(Executors.newCachedThreadPool());
149
150
// Get service information
151
String projectName = project.getProject();
152
List<ComposeServiceWaitStrategyTarget> services = project.getServices();
153
Map<String, String> envConfig = project.getEnvVarConfig();
154
Map<String, String> portConfig = project.getExposedPortConfig();
155
156
// Use configuration
157
String dbUrl = portConfig.get("DATABASE_URL");
158
String dbUser = envConfig.get("DB_USER");
159
160
// Cleanup when done
161
project.stop();
162
```
163
164
### ComposeProject.Builder
165
166
Fluent builder pattern for creating ComposeProject instances with extensive configuration options.
167
168
```java { .api }
169
/**
170
* Builder for ComposeProject with fluent configuration
171
*/
172
public static class Builder {
173
174
/**
175
* Creates a new builder with required parameters
176
* @param files Compose files to manage
177
* @param executable Compose executable name
178
*/
179
public Builder(ComposeFiles files, String executable);
180
181
/**
182
* Sets the docker client to use
183
* @param dockerClient Docker client instance
184
* @return This builder
185
*/
186
public Builder withDockerClient(DockerClient dockerClient);
187
188
/**
189
* Sets the project name
190
* @param project Project name for compose services
191
* @return This builder
192
*/
193
public Builder withProject(String project);
194
195
/**
196
* Sets whether to stop containers on shutdown
197
* @param stopContainers Stop containers flag
198
* @return This builder
199
*/
200
public Builder withStopContainers(boolean stopContainers);
201
202
/**
203
* Sets whether to enable Ryuk for cleanup
204
* @param ryukEnabled Ryuk enabled flag
205
* @return This builder
206
*/
207
public Builder withRyukEnabled(boolean ryukEnabled);
208
209
/**
210
* Sets the startup timeout
211
* @param duration Maximum startup time
212
* @return This builder
213
*/
214
public Builder withStartupTimeout(Duration duration);
215
216
/**
217
* Sets the stop timeout
218
* @param duration Maximum stop time
219
* @return This builder
220
*/
221
public Builder withStopTimeout(Duration duration);
222
223
/**
224
* Sets whether to build images before starting
225
* @param build Build images flag
226
* @return This builder
227
*/
228
public Builder withBuild(Boolean build);
229
230
/**
231
* Sets environment variables
232
* @param envVariables Environment variable map
233
* @return This builder
234
*/
235
public Builder withEnv(Map<String, String> envVariables);
236
237
/**
238
* Sets compose command options
239
* @param options List of command options
240
* @return This builder
241
*/
242
public Builder withOptions(List<String> options);
243
244
/**
245
* Sets compose profiles to activate
246
* @param profiles List of profile names
247
* @return This builder
248
*/
249
public Builder withProfiles(List<String> profiles);
250
251
/**
252
* Sets service scaling preferences
253
* @param scalingPreferences Map of service name to replica count
254
* @return This builder
255
*/
256
public Builder withScalingPreferences(Map<String, Integer> scalingPreferences);
257
258
/**
259
* Sets whether to follow container logs
260
* @param followContainerLogs Follow logs flag
261
* @return This builder
262
*/
263
public Builder withFollowContainerLogs(boolean followContainerLogs);
264
265
/**
266
* Sets image removal strategy
267
* @param removeImages Image removal option
268
* @return This builder
269
*/
270
public Builder withRemoveImages(String removeImages);
271
272
/**
273
* Sets whether to remove volumes on shutdown
274
* @param removeVolumes Remove volumes flag
275
* @return This builder
276
*/
277
public Builder withRemoveVolumes(boolean removeVolumes);
278
279
/**
280
* Builds the ComposeProject instance
281
* @return Configured ComposeProject
282
*/
283
public ComposeProject build();
284
}
285
```
286
287
**Usage Examples:**
288
289
```java
290
// Minimal configuration
291
ComposeProject minimal = new ComposeProject.Builder(composeFiles, "docker")
292
.withProject("my-project")
293
.build();
294
295
// Full configuration with all options
296
ComposeProject full = new ComposeProject.Builder(composeFiles, "podman")
297
.withProject("full-config-project")
298
.withStartupTimeout(Duration.ofMinutes(5))
299
.withStopTimeout(Duration.ofSeconds(30))
300
.withStopContainers(true)
301
.withRyukEnabled(false)
302
.withBuild(true)
303
.withFollowContainerLogs(true)
304
.withRemoveVolumes(true)
305
.withRemoveImages("all")
306
.withEnv(Map.of(
307
"POSTGRES_DB", "testdb",
308
"POSTGRES_USER", "test",
309
"POSTGRES_PASSWORD", "secret"
310
))
311
.withProfiles(List.of("development", "testing"))
312
.withOptions(List.of("--compatibility", "--verbose"))
313
.withScalingPreferences(Map.of("web", 2, "worker", 3))
314
.build();
315
316
// Configure for testing environment
317
ComposeProject testing = new ComposeProject.Builder(composeFiles, "docker")
318
.withProject("test-services")
319
.withStartupTimeout(Duration.ofMinutes(1))
320
.withRyukEnabled(true)
321
.withBuild(false)
322
.withProfiles(List.of("test"))
323
.build();
324
```
325
326
### ComposeRunner
327
328
Executes Docker Compose commands with proper environment setup and error handling, providing a fluent interface for running arbitrary compose operations.
329
330
```java { .api }
331
/**
332
* A class that runs compose commands with proper environment setup
333
*/
334
public class ComposeRunner {
335
336
/**
337
* Creates a new compose runner
338
* @param composeExecutable Executable name (docker, podman, etc.)
339
* @param composeFiles List of compose files
340
* @param projectName Project name for compose
341
*/
342
public ComposeRunner(String composeExecutable, List<File> composeFiles, String projectName);
343
344
/**
345
* Sets the compose command to run
346
* @param cmd Command string with arguments
347
* @return This runner
348
*/
349
public ComposeRunner withCommand(String cmd);
350
351
/**
352
* Sets environment variables for the command
353
* @param env Environment variable map
354
* @return This runner
355
*/
356
public ComposeRunner withEnv(Map<String, String> env);
357
358
/**
359
* Sets compose profiles to use
360
* @param profiles List of profile names
361
* @return This runner
362
*/
363
public ComposeRunner withProfiles(List<String> profiles);
364
365
/**
366
* Sets additional compose options
367
* @param options List of command-line options
368
* @return This runner
369
*/
370
public ComposeRunner withOptions(List<String> options);
371
372
/**
373
* Executes the compose command
374
* @throws RuntimeException If command fails or compose not found
375
*/
376
public void run();
377
378
/**
379
* Executes the compose command and returns output
380
* @return Command output as string
381
* @throws RuntimeException If command fails or compose not found
382
*/
383
public String runAndGetOutput();
384
385
/**
386
* Checks if the compose executable is available
387
* @param executable Executable name to check
388
* @return true if executable is found in PATH
389
*/
390
public static boolean isComposeAvailable(String executable);
391
}
392
```
393
394
**Usage Examples:**
395
396
```java
397
// Basic compose command execution
398
ComposeRunner runner = new ComposeRunner("docker", composeFiles, "my-project");
399
runner.withCommand("up -d")
400
.withEnv(Map.of("POSTGRES_PASSWORD", "secret"))
401
.run();
402
403
// Running with profiles and custom environment
404
new ComposeRunner("podman", composeFiles, "dev-project")
405
.withCommand("up --build")
406
.withProfiles(List.of("development", "debug"))
407
.withEnv(Map.of(
408
"API_KEY", "dev-key",
409
"LOG_LEVEL", "debug",
410
"REDIS_PASSWORD", "redis-secret"
411
))
412
.run();
413
414
// Getting command output for inspection
415
String status = new ComposeRunner("docker", composeFiles, "status-check")
416
.withCommand("ps --format json")
417
.runAndGetOutput();
418
System.out.println("Service status: " + status);
419
420
// Using additional options with command
421
new ComposeRunner("docker", composeFiles, "advanced-project")
422
.withCommand("up")
423
.withOptions(List.of("--compatibility", "--abort-on-container-exit"))
424
.withEnv(Map.of("COMPOSE_HTTP_TIMEOUT", "120"))
425
.run();
426
427
// Check if compose is available before running
428
if (ComposeRunner.isComposeAvailable("docker")) {
429
new ComposeRunner("docker", composeFiles, "my-project")
430
.withCommand("up -d")
431
.run();
432
} else if (ComposeRunner.isComposeAvailable("podman")) {
433
new ComposeRunner("podman", composeFiles, "my-project")
434
.withCommand("up -d")
435
.run();
436
} else {
437
throw new RuntimeException("No compatible compose executable found");
438
}
439
440
// Stopping services with cleanup
441
new ComposeRunner("docker", composeFiles, "test-project")
442
.withCommand("down -v --rmi all")
443
.run();
444
```
445
446
## Constants
447
448
```java { .api }
449
// Default network name
450
public static final String DEFAULT_NETWORK_NAME = "default";
451
452
// Environment variable names used by ComposeRunner
453
private static final String DOCKER_HOST_ENV = "DOCKER_HOST";
454
private static final String DOCKER_CERT_PATH_ENV = "DOCKER_CERT_PATH";
455
private static final String DOCKER_TLS_VERIFY_ENV = "DOCKER_TLS_VERIFY";
456
private static final String PROJECT_NAME_ENV = "COMPOSE_PROJECT_NAME";
457
private static final String COMPOSE_FILE_ENV = "COMPOSE_FILE";
458
private static final String COMPOSE_PROFILES_ENV = "COMPOSE_PROFILES";
459
```