or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-configuration.mdcontainers.mdimages.mdindex.mdnetworks.mdswarm.mdvolumes.md

swarm.mddocs/

0

# Docker Swarm Operations

1

2

This document covers comprehensive Docker Swarm orchestration including swarm management, services, tasks, nodes, secrets, configs, and production deployment patterns.

3

4

## Swarm Initialization and Management

5

6

### Swarm Initialization

7

8

```java { .api }

9

import com.spotify.docker.client.DockerClient;

10

import com.spotify.docker.client.messages.swarm.*;

11

12

// Initialize new swarm cluster

13

SwarmInit swarmInit = SwarmInit.builder()

14

.listenAddr("0.0.0.0:2377")

15

.advertiseAddr("192.168.1.100:2377")

16

.build();

17

18

String nodeId = docker.initSwarm(swarmInit);

19

System.out.println("Swarm initialized. Node ID: " + nodeId);

20

```

21

22

### Advanced Swarm Initialization

23

24

```java { .api }

25

// Initialize swarm with custom specification

26

SwarmSpec swarmSpec = SwarmSpec.builder()

27

.name("production-swarm")

28

.labels(Map.of(

29

"environment", "production",

30

"datacenter", "us-east-1"

31

))

32

33

// Orchestration settings

34

.orchestration(OrchestrationConfig.builder()

35

.taskHistoryRetentionLimit(10)

36

.build())

37

38

// Raft consensus configuration

39

.raft(RaftConfig.builder()

40

.snapshotInterval(10000L)

41

.keepOldSnapshots(5L)

42

.logEntriesForSlowFollowers(500L)

43

.electionTick(10L)

44

.heartbeatTick(1L)

45

.build())

46

47

// Dispatcher configuration

48

.dispatcher(DispatcherConfig.builder()

49

.heartbeatPeriod(Duration.ofSeconds(5))

50

.build())

51

52

// Certificate authority configuration

53

.caConfig(CaConfig.builder()

54

.nodeCertExpiry(Duration.ofDays(90))

55

.build())

56

57

// Encryption configuration

58

.encryptionConfig(EncryptionConfig.builder()

59

.autoLockManagers(true)

60

.build())

61

62

.build();

63

64

SwarmInit advancedInit = SwarmInit.builder()

65

.listenAddr("0.0.0.0:2377")

66

.advertiseAddr("192.168.1.100:2377")

67

.forceNewCluster(false)

68

.spec(swarmSpec)

69

.build();

70

71

String nodeId = docker.initSwarm(advancedInit);

72

```

73

74

### Swarm Inspection

75

76

```java { .api }

77

// Get swarm information

78

Swarm swarm = docker.inspectSwarm();

79

80

System.out.println("Swarm ID: " + swarm.id());

81

System.out.println("Created At: " + swarm.createdAt());

82

System.out.println("Updated At: " + swarm.updatedAt());

83

84

// Swarm specification

85

SwarmSpec spec = swarm.spec();

86

System.out.println("Swarm Name: " + spec.name());

87

System.out.println("Labels: " + spec.labels());

88

89

// Join tokens for workers and managers

90

JoinTokens joinTokens = swarm.joinTokens();

91

System.out.println("Worker Join Token: " + joinTokens.worker());

92

System.out.println("Manager Join Token: " + joinTokens.manager());

93

94

// Remote managers

95

List<RemoteManager> managers = swarm.remoteManagers();

96

for (RemoteManager manager : managers) {

97

System.out.println("Manager: " + manager.nodeId() + " @ " + manager.addr());

98

}

99

```

100

101

### Joining and Leaving Swarm

102

103

```java { .api }

104

// Join swarm as worker

105

SwarmJoin workerJoin = SwarmJoin.builder()

106

.listenAddr("0.0.0.0:2377")

107

.advertiseAddr("192.168.1.101:2377")

108

.remoteAddrs("192.168.1.100:2377")

109

.joinToken("worker-token-here")

110

.build();

111

112

docker.joinSwarm(workerJoin);

113

114

// Join swarm as manager

115

SwarmJoin managerJoin = SwarmJoin.builder()

116

.listenAddr("0.0.0.0:2377")

117

.advertiseAddr("192.168.1.102:2377")

118

.remoteAddrs("192.168.1.100:2377")

119

.joinToken("manager-token-here")

120

.build();

121

122

docker.joinSwarm(managerJoin);

123

124

// Leave swarm

125

docker.leaveSwarm();

126

127

// Force leave (for managers)

128

docker.leaveSwarm(true);

129

```

130

131

### Swarm Updates

132

133

```java { .api }

134

// Update swarm configuration

135

Swarm currentSwarm = docker.inspectSwarm();

136

Long version = currentSwarm.version().index();

137

138

SwarmSpec updatedSpec = currentSwarm.spec().toBuilder()

139

.name("updated-production-swarm")

140

.labels(Map.of(

141

"environment", "production",

142

"region", "us-east",

143

"updated", "true"

144

))

145

.build();

146

147

// Update swarm

148

docker.updateSwarm(version, updatedSpec);

149

150

// Update with token rotation

151

docker.updateSwarm(version, true, false, updatedSpec); // Rotate worker token

152

docker.updateSwarm(version, false, true, updatedSpec); // Rotate manager token

153

```

154

155

### Swarm Unlock

156

157

```java { .api }

158

// Get unlock key (for auto-lock enabled swarms)

159

UnlockKey unlockKey = docker.unlockKey();

160

System.out.println("Unlock Key: " + unlockKey.unlockKey());

161

162

// Unlock swarm

163

docker.unlock(unlockKey);

164

```

165

166

## Service Management

167

168

### Service Creation

169

170

```java { .api }

171

import com.spotify.docker.client.messages.swarm.*;

172

173

// Basic service creation

174

ServiceSpec serviceSpec = ServiceSpec.builder()

175

.name("web-service")

176

.taskTemplate(TaskSpec.builder()

177

.containerSpec(ContainerSpec.builder()

178

.image("nginx:latest")

179

.build())

180

.build())

181

.build();

182

183

ServiceCreateResponse response = docker.createService(serviceSpec);

184

System.out.println("Created service ID: " + response.id());

185

```

186

187

### Advanced Service Configuration

188

189

```java { .api }

190

// Comprehensive service configuration

191

ServiceSpec advancedService = ServiceSpec.builder()

192

.name("production-api")

193

.labels(Map.of(

194

"environment", "production",

195

"tier", "backend",

196

"version", "1.0.0"

197

))

198

199

// Task template

200

.taskTemplate(TaskSpec.builder()

201

.containerSpec(ContainerSpec.builder()

202

.image("myapp:latest")

203

.hostname("api-server")

204

.env("ENV=production", "PORT=8080")

205

.args("--config", "/app/config.yml")

206

.user("appuser")

207

.dir("/app")

208

209

// Resource limits

210

.resources(ResourceRequirements.builder()

211

.limits(Resources.builder()

212

.memoryBytes(512L * 1024 * 1024) // 512MB

213

.nanoCpus(500_000_000L) // 0.5 CPU

214

.build())

215

.reservations(Resources.builder()

216

.memoryBytes(256L * 1024 * 1024) // 256MB reserved

217

.nanoCpus(250_000_000L) // 0.25 CPU reserved

218

.build())

219

.build())

220

221

// Health check

222

.healthcheck(HealthConfig.builder()

223

.test("CMD curl -f http://localhost:8080/health || exit 1")

224

.interval(Duration.ofSeconds(30))

225

.timeout(Duration.ofSeconds(10))

226

.retries(3)

227

.startPeriod(Duration.ofSeconds(60))

228

.build())

229

230

// Secrets and configs

231

.secrets(SecretBind.builder()

232

.secretId("app-secret-id")

233

.secretName("database-password")

234

.file(SecretFile.builder()

235

.name("db-password")

236

.uid(1000L)

237

.gid(1000L)

238

.mode(0400L)

239

.build())

240

.build())

241

242

.configs(ConfigBind.builder()

243

.configId("app-config-id")

244

.configName("application-config")

245

.file(ConfigFile.builder()

246

.name("app-config.yml")

247

.uid(1000L)

248

.gid(1000L)

249

.mode(0644L)

250

.build())

251

.build())

252

253

.build())

254

255

// Placement constraints

256

.placement(Placement.builder()

257

.constraints("node.role==worker", "engine.labels.type==compute")

258

.preferences(PlacementPreference.builder()

259

.spread(SpreadDescriptor.builder()

260

.spreadDescriptor("node.labels.zone")

261

.build())

262

.build())

263

.maxReplicas(2L) // Max replicas per node

264

.build())

265

266

// Restart policy

267

.restartPolicy(RestartPolicy.builder()

268

.condition("on-failure")

269

.delay(Duration.ofSeconds(5))

270

.maxAttempts(3L)

271

.window(Duration.ofSeconds(120))

272

.build())

273

274

// Networks

275

.networks(NetworkAttachmentConfig.builder()

276

.target("production-network")

277

.aliases("api", "backend")

278

.build())

279

280

.build())

281

282

// Service mode (replicated vs global)

283

.mode(ServiceMode.builder()

284

.replicated(ReplicatedService.builder()

285

.replicas(3L)

286

.build())

287

.build())

288

289

// Update configuration

290

.updateConfig(UpdateConfig.builder()

291

.parallelism(1L)

292

.delay(Duration.ofSeconds(10))

293

.failureAction("rollback")

294

.monitor(Duration.ofSeconds(60))

295

.maxFailureRatio(0.1f)

296

.order("start-first")

297

.build())

298

299

// Rollback configuration

300

.rollbackConfig(UpdateConfig.builder()

301

.parallelism(1L)

302

.delay(Duration.ofSeconds(5))

303

.failureAction("pause")

304

.monitor(Duration.ofSeconds(30))

305

.maxFailureRatio(0.0f)

306

.build())

307

308

// Endpoint specification (for published ports)

309

.endpointSpec(EndpointSpec.builder()

310

.mode("vip")

311

.ports(PortConfig.builder()

312

.name("http")

313

.protocol("tcp")

314

.targetPort(8080L)

315

.publishedPort(80L)

316

.publishMode("ingress")

317

.build())

318

.build())

319

320

.build();

321

322

ServiceCreateResponse response = docker.createService(advancedService);

323

```

324

325

### Service with Authentication

326

327

```java { .api }

328

// Create service that requires registry authentication

329

RegistryAuth auth = RegistryAuth.builder()

330

.username("myuser")

331

.password("mypass")

332

.serverAddress("https://my-registry.com")

333

.build();

334

335

ServiceSpec serviceSpec = ServiceSpec.builder()

336

.name("private-service")

337

.taskTemplate(TaskSpec.builder()

338

.containerSpec(ContainerSpec.builder()

339

.image("my-registry.com/myapp:latest")

340

.build())

341

.build())

342

.build();

343

344

ServiceCreateResponse response = docker.createService(serviceSpec, auth);

345

```

346

347

### Service Inspection and Updates

348

349

```java { .api }

350

// Inspect service

351

Service service = docker.inspectService("service-name-or-id");

352

353

System.out.println("Service ID: " + service.id());

354

System.out.println("Version: " + service.version().index());

355

System.out.println("Created: " + service.createdAt());

356

System.out.println("Updated: " + service.updatedAt());

357

358

// Service endpoint

359

Endpoint endpoint = service.endpoint();

360

if (endpoint != null) {

361

System.out.println("Endpoint Mode: " + endpoint.spec().mode());

362

for (PortConfig port : endpoint.spec().ports()) {

363

System.out.println("Port: " + port.publishedPort() + " -> " + port.targetPort());

364

}

365

366

// Virtual IPs

367

for (EndpointVirtualIp vip : endpoint.virtualIps()) {

368

System.out.println("VIP: " + vip.addr() + " (Network: " + vip.networkId() + ")");

369

}

370

}

371

372

// Update service

373

ServiceSpec updatedSpec = service.spec().toBuilder()

374

.taskTemplate(service.spec().taskTemplate().toBuilder()

375

.containerSpec(service.spec().taskTemplate().containerSpec().toBuilder()

376

.image("myapp:v2.0")

377

.env("VERSION=2.0", "UPDATED=true")

378

.build())

379

.build())

380

.build();

381

382

docker.updateService(service.id(), service.version().index(), updatedSpec);

383

```

384

385

### Service Listing and Filtering

386

387

```java { .api }

388

// List all services

389

List<Service> allServices = docker.listServices();

390

391

// List with criteria

392

Service.Criteria criteria = Service.Criteria.builder()

393

.serviceName("web-service")

394

.serviceId("service-id")

395

.serviceLabel("environment", "production")

396

.build();

397

398

List<Service> filteredServices = docker.listServices(criteria);

399

400

for (Service service : filteredServices) {

401

System.out.println("Service: " + service.spec().name());

402

System.out.println("Replicas: " + service.spec().mode().replicated().replicas());

403

System.out.println("Image: " + service.spec().taskTemplate().containerSpec().image());

404

}

405

```

406

407

### Service Removal

408

409

```java { .api }

410

// Remove service

411

docker.removeService("service-name-or-id");

412

413

// Safe service removal with scaling down first

414

public void safeRemoveService(DockerClient docker, String serviceId)

415

throws DockerException, InterruptedException {

416

417

try {

418

// First scale service to 0

419

Service service = docker.inspectService(serviceId);

420

ServiceSpec scaledSpec = service.spec().toBuilder()

421

.mode(ServiceMode.builder()

422

.replicated(ReplicatedService.builder()

423

.replicas(0L)

424

.build())

425

.build())

426

.build();

427

428

docker.updateService(serviceId, service.version().index(), scaledSpec);

429

System.out.println("Scaled service to 0 replicas");

430

431

// Wait for tasks to stop

432

Thread.sleep(10000);

433

434

// Remove service

435

docker.removeService(serviceId);

436

System.out.println("Removed service: " + serviceId);

437

438

} catch (DockerException e) {

439

System.err.println("Error removing service: " + e.getMessage());

440

}

441

}

442

```

443

444

### Service Logs

445

446

```java { .api }

447

// Get service logs

448

try (LogStream logs = docker.serviceLogs("service-name",

449

DockerClient.LogsParam.stdout(),

450

DockerClient.LogsParam.stderr(),

451

DockerClient.LogsParam.follow(),

452

DockerClient.LogsParam.timestamps(true))) {

453

454

logs.forEachRemaining(logMessage -> {

455

System.out.println("Service Log: " + logMessage.content().toStringUtf8());

456

});

457

}

458

```

459

460

## Task Management

461

462

### Task Listing and Inspection

463

464

```java { .api }

465

// List all tasks

466

List<Task> allTasks = docker.listTasks();

467

468

// List with criteria

469

Task.Criteria taskCriteria = Task.Criteria.builder()

470

.serviceName("web-service")

471

.nodeId("node-id")

472

.taskName("web-service.1")

473

.taskState("running")

474

.build();

475

476

List<Task> filteredTasks = docker.listTasks(taskCriteria);

477

478

for (Task task : filteredTasks) {

479

System.out.println("Task ID: " + task.id());

480

System.out.println("Service ID: " + task.serviceId());

481

System.out.println("Node ID: " + task.nodeId());

482

System.out.println("Slot: " + task.slot());

483

484

TaskStatus status = task.status();

485

System.out.println("State: " + status.state());

486

System.out.println("Message: " + status.message());

487

488

if (status.containerStatus() != null) {

489

System.out.println("Container ID: " + status.containerStatus().containerId());

490

System.out.println("PID: " + status.containerStatus().pid());

491

}

492

}

493

```

494

495

### Task Inspection

496

497

```java { .api }

498

// Inspect specific task

499

Task task = docker.inspectTask("task-id");

500

501

System.out.println("Task Details:");

502

System.out.println(" ID: " + task.id());

503

System.out.println(" Version: " + task.version().index());

504

System.out.println(" Created: " + task.createdAt());

505

System.out.println(" Updated: " + task.updatedAt());

506

System.out.println(" Service: " + task.serviceId());

507

System.out.println(" Node: " + task.nodeId());

508

System.out.println(" Slot: " + task.slot());

509

510

// Task specification

511

TaskSpec spec = task.spec();

512

ContainerSpec containerSpec = spec.containerSpec();

513

System.out.println(" Image: " + containerSpec.image());

514

System.out.println(" Command: " + containerSpec.command());

515

System.out.println(" Args: " + containerSpec.args());

516

517

// Task status and history

518

TaskStatus status = task.status();

519

System.out.println(" Current State: " + status.state());

520

System.out.println(" Message: " + status.message());

521

System.out.println(" Timestamp: " + status.timestamp());

522

523

// Container status (if running)

524

if (status.containerStatus() != null) {

525

ContainerStatus containerStatus = status.containerStatus();

526

System.out.println(" Container ID: " + containerStatus.containerId());

527

System.out.println(" PID: " + containerStatus.pid());

528

System.out.println(" Exit Code: " + containerStatus.exitCode());

529

}

530

```

531

532

## Node Management

533

534

### Node Listing and Inspection

535

536

```java { .api }

537

// List all nodes

538

List<Node> allNodes = docker.listNodes();

539

540

// List with criteria

541

Node.Criteria nodeCriteria = Node.Criteria.builder()

542

.nodeName("worker-1")

543

.nodeRole("worker")

544

.membershipAccepted()

545

.build();

546

547

List<Node> filteredNodes = docker.listNodes(nodeCriteria);

548

549

for (Node node : filteredNodes) {

550

System.out.println("Node ID: " + node.id());

551

System.out.println("Hostname: " + node.description().hostname());

552

System.out.println("Role: " + node.spec().role());

553

System.out.println("Availability: " + node.spec().availability());

554

System.out.println("State: " + node.status().state());

555

System.out.println("Address: " + node.status().addr());

556

557

// Manager status (if applicable)

558

ManagerStatus managerStatus = node.managerStatus();

559

if (managerStatus != null) {

560

System.out.println("Leader: " + managerStatus.leader());

561

System.out.println("Reachability: " + managerStatus.reachability());

562

System.out.println("Address: " + managerStatus.addr());

563

}

564

565

// Node resources

566

NodeDescription desc = node.description();

567

Resources resources = desc.resources();

568

System.out.println("Memory: " + resources.memoryBytes() + " bytes");

569

System.out.println("CPUs: " + resources.nanoCpus() / 1_000_000_000.0);

570

}

571

```

572

573

### Node Inspection

574

575

```java { .api }

576

// Inspect specific node (returns NodeInfo which is alias for Node)

577

NodeInfo nodeInfo = docker.inspectNode("node-id-or-hostname");

578

579

System.out.println("Node Information:");

580

System.out.println(" ID: " + nodeInfo.id());

581

System.out.println(" Version: " + nodeInfo.version().index());

582

System.out.println(" Created: " + nodeInfo.createdAt());

583

System.out.println(" Updated: " + nodeInfo.updatedAt());

584

585

// Node specification

586

NodeSpec spec = nodeInfo.spec();

587

System.out.println(" Name: " + spec.name());

588

System.out.println(" Labels: " + spec.labels());

589

System.out.println(" Role: " + spec.role());

590

System.out.println(" Availability: " + spec.availability());

591

592

// Node description (hardware/software info)

593

NodeDescription desc = nodeInfo.description();

594

System.out.println(" Hostname: " + desc.hostname());

595

Platform platform = desc.platform();

596

System.out.println(" Architecture: " + platform.architecture());

597

System.out.println(" OS: " + platform.os());

598

599

// Engine info

600

EngineDescription engine = desc.engine();

601

System.out.println(" Engine Version: " + engine.engineVersion());

602

System.out.println(" Plugins: " + engine.plugins());

603

System.out.println(" Labels: " + engine.labels());

604

605

// TLS info

606

TlsInfo tlsInfo = desc.tlsInfo();

607

System.out.println(" Certificate Subject: " + tlsInfo.certIssuerSubject());

608

System.out.println(" Certificate Issuer: " + tlsInfo.certIssuerPublicKey());

609

```

610

611

### Node Updates

612

613

```java { .api }

614

// Update node configuration

615

Node node = docker.listNodes().get(0); // Get first node

616

Long version = node.version().index();

617

618

NodeSpec updatedSpec = node.spec().toBuilder()

619

.availability("drain") // Drain node for maintenance

620

.labels(Map.of(

621

"maintenance", "true",

622

"type", "compute",

623

"zone", "us-east-1a"

624

))

625

.build();

626

627

docker.updateNode(node.id(), version, updatedSpec);

628

629

// Common node operations

630

public void drainNode(DockerClient docker, String nodeId)

631

throws DockerException, InterruptedException {

632

633

Node node = docker.inspectNode(nodeId);

634

NodeSpec drainSpec = node.spec().toBuilder()

635

.availability("drain")

636

.build();

637

638

docker.updateNode(nodeId, node.version().index(), drainSpec);

639

System.out.println("Node " + nodeId + " drained");

640

}

641

642

public void activateNode(DockerClient docker, String nodeId)

643

throws DockerException, InterruptedException {

644

645

Node node = docker.inspectNode(nodeId);

646

NodeSpec activeSpec = node.spec().toBuilder()

647

.availability("active")

648

.build();

649

650

docker.updateNode(nodeId, node.version().index(), activeSpec);

651

System.out.println("Node " + nodeId + " activated");

652

}

653

```

654

655

### Node Removal

656

657

```java { .api }

658

// Remove node from swarm

659

docker.deleteNode("node-id");

660

661

// Force remove (even if node is manager)

662

docker.deleteNode("node-id", true);

663

664

// Safe node removal process

665

public void safeRemoveNode(DockerClient docker, String nodeId)

666

throws DockerException, InterruptedException {

667

668

try {

669

// First drain the node

670

drainNode(docker, nodeId);

671

672

// Wait for tasks to migrate

673

System.out.println("Waiting for tasks to migrate...");

674

Thread.sleep(30000);

675

676

// Verify no tasks are running on the node

677

List<Task> nodeTasks = docker.listTasks(

678

Task.Criteria.builder()

679

.nodeId(nodeId)

680

.taskState("running")

681

.build()

682

);

683

684

if (!nodeTasks.isEmpty()) {

685

System.out.println("Warning: " + nodeTasks.size() + " tasks still running on node");

686

}

687

688

// Remove node

689

docker.deleteNode(nodeId);

690

System.out.println("Node " + nodeId + " removed successfully");

691

692

} catch (DockerException e) {

693

System.err.println("Error removing node: " + e.getMessage());

694

}

695

}

696

```

697

698

## Secrets Management

699

700

### Secret Creation

701

702

```java { .api }

703

import com.spotify.docker.client.messages.swarm.*;

704

import java.util.Base64;

705

706

// Create secret from string data

707

String secretData = "my-secret-password";

708

String encodedData = Base64.getEncoder().encodeToString(secretData.getBytes());

709

710

SecretSpec secretSpec = SecretSpec.builder()

711

.name("database-password")

712

.data(encodedData)

713

.labels(Map.of(

714

"environment", "production",

715

"type", "password"

716

))

717

.build();

718

719

SecretCreateResponse response = docker.createSecret(secretSpec);

720

System.out.println("Created secret ID: " + response.id());

721

```

722

723

### Advanced Secret Configuration

724

725

```java { .api }

726

// Create secret with external driver

727

SecretSpec externalSecret = SecretSpec.builder()

728

.name("external-secret")

729

.labels(Map.of("provider", "vault"))

730

.driver(Driver.builder()

731

.name("vault")

732

.options(Map.of(

733

"path", "secret/myapp/db",

734

"key", "password"

735

))

736

.build())

737

.build();

738

739

// Create secret from file

740

byte[] fileContent = Files.readAllBytes(Paths.get("/path/to/secret/file"));

741

String fileData = Base64.getEncoder().encodeToString(fileContent);

742

743

SecretSpec fileSecret = SecretSpec.builder()

744

.name("ssl-certificate")

745

.data(fileData)

746

.labels(Map.of("type", "certificate"))

747

.build();

748

749

docker.createSecret(externalSecret);

750

docker.createSecret(fileSecret);

751

```

752

753

### Secret Listing and Inspection

754

755

```java { .api }

756

// List all secrets

757

List<Secret> secrets = docker.listSecrets();

758

759

for (Secret secret : secrets) {

760

System.out.println("Secret ID: " + secret.id());

761

System.out.println("Name: " + secret.spec().name());

762

System.out.println("Created: " + secret.createdAt());

763

System.out.println("Updated: " + secret.updatedAt());

764

System.out.println("Labels: " + secret.spec().labels());

765

766

// Driver information

767

Driver driver = secret.spec().driver();

768

if (driver != null) {

769

System.out.println("Driver: " + driver.name());

770

System.out.println("Driver Options: " + driver.options());

771

}

772

}

773

774

// Inspect specific secret

775

Secret secret = docker.inspectSecret("secret-name-or-id");

776

System.out.println("Secret Details:");

777

System.out.println(" ID: " + secret.id());

778

System.out.println(" Version: " + secret.version().index());

779

System.out.println(" Name: " + secret.spec().name());

780

// Note: Secret data is not returned for security reasons

781

```

782

783

### Using Secrets in Services

784

785

```java { .api }

786

// Service with secret bindings

787

ServiceSpec serviceWithSecrets = ServiceSpec.builder()

788

.name("secure-web-service")

789

.taskTemplate(TaskSpec.builder()

790

.containerSpec(ContainerSpec.builder()

791

.image("nginx:latest")

792

793

// Bind secrets as files

794

.secrets(

795

SecretBind.builder()

796

.secretId("database-password-id")

797

.secretName("database-password")

798

.file(SecretFile.builder()

799

.name("db_password")

800

.uid(33L) // www-data user

801

.gid(33L) // www-data group

802

.mode(0400L) // Read-only for owner

803

.build())

804

.build(),

805

806

SecretBind.builder()

807

.secretId("ssl-cert-id")

808

.secretName("ssl-certificate")

809

.file(SecretFile.builder()

810

.name("server.crt")

811

.uid(0L) // root

812

.gid(0L) // root

813

.mode(0444L) // Read-only for all

814

.build())

815

.build()

816

)

817

818

.build())

819

.build())

820

.build();

821

822

docker.createService(serviceWithSecrets);

823

```

824

825

### Secret Removal

826

827

```java { .api }

828

// Remove secret

829

docker.deleteSecret("secret-name-or-id");

830

831

// Safe secret removal (check usage first)

832

public void safeRemoveSecret(DockerClient docker, String secretId)

833

throws DockerException, InterruptedException {

834

835

try {

836

// Check which services use this secret

837

List<Service> services = docker.listServices();

838

List<String> usingServices = new ArrayList<>();

839

840

for (Service service : services) {

841

TaskSpec taskSpec = service.spec().taskTemplate();

842

if (taskSpec.containerSpec().secrets() != null) {

843

for (SecretBind secret : taskSpec.containerSpec().secrets()) {

844

if (secretId.equals(secret.secretId()) || secretId.equals(secret.secretName())) {

845

usingServices.add(service.spec().name());

846

break;

847

}

848

}

849

}

850

}

851

852

if (usingServices.isEmpty()) {

853

docker.deleteSecret(secretId);

854

System.out.println("Removed secret: " + secretId);

855

} else {

856

System.out.println("Secret is in use by services: " + usingServices);

857

}

858

859

} catch (DockerException e) {

860

System.err.println("Error removing secret: " + e.getMessage());

861

}

862

}

863

```

864

865

## Configs Management

866

867

### Config Creation

868

869

```java { .api }

870

import com.spotify.docker.client.messages.swarm.*;

871

872

// Create config from string data

873

String configData = "server {\n listen 80;\n server_name example.com;\n}";

874

String encodedConfig = Base64.getEncoder().encodeToString(configData.getBytes());

875

876

ConfigSpec configSpec = ConfigSpec.builder()

877

.name("nginx-config")

878

.data(encodedConfig)

879

.labels(Map.of(

880

"application", "nginx",

881

"version", "1.0"

882

))

883

.build();

884

885

ConfigCreateResponse response = docker.createConfig(configSpec);

886

System.out.println("Created config ID: " + response.id());

887

```

888

889

### Advanced Config Management

890

891

```java { .api }

892

// Create config from template file

893

String templateData = """

894

upstream backend {

895

server ${BACKEND_HOST}:${BACKEND_PORT};

896

}

897

898

server {

899

listen 80;

900

location / {

901

proxy_pass http://backend;

902

}

903

}

904

""";

905

906

ConfigSpec templateConfig = ConfigSpec.builder()

907

.name("nginx-template")

908

.data(Base64.getEncoder().encodeToString(templateData.getBytes()))

909

.labels(Map.of(

910

"type", "template",

911

"service", "nginx"

912

))

913

.build();

914

915

docker.createConfig(templateConfig);

916

```

917

918

### Config Listing and Inspection

919

920

```java { .api }

921

// List all configs

922

List<Config> configs = docker.listConfigs();

923

924

// List with criteria

925

Config.Criteria configCriteria = Config.Criteria.builder()

926

.configName("nginx-config")

927

.configLabel("application", "nginx")

928

.build();

929

930

List<Config> filteredConfigs = docker.listConfigs(configCriteria);

931

932

for (Config config : filteredConfigs) {

933

System.out.println("Config ID: " + config.id());

934

System.out.println("Name: " + config.spec().name());

935

System.out.println("Created: " + config.createdAt());

936

System.out.println("Labels: " + config.spec().labels());

937

}

938

939

// Inspect specific config

940

Config config = docker.inspectConfig("config-name-or-id");

941

System.out.println("Config Details:");

942

System.out.println(" ID: " + config.id());

943

System.out.println(" Version: " + config.version().index());

944

System.out.println(" Name: " + config.spec().name());

945

// Config data is available (unlike secrets)

946

String data = new String(Base64.getDecoder().decode(config.spec().data()));

947

System.out.println(" Data: " + data);

948

```

949

950

### Using Configs in Services

951

952

```java { .api }

953

// Service with config bindings

954

ServiceSpec serviceWithConfigs = ServiceSpec.builder()

955

.name("configured-nginx")

956

.taskTemplate(TaskSpec.builder()

957

.containerSpec(ContainerSpec.builder()

958

.image("nginx:latest")

959

960

// Bind configs as files

961

.configs(

962

ConfigBind.builder()

963

.configId("nginx-config-id")

964

.configName("nginx-config")

965

.file(ConfigFile.builder()

966

.name("nginx.conf")

967

.uid(0L)

968

.gid(0L)

969

.mode(0644L)

970

.build())

971

.build(),

972

973

ConfigBind.builder()

974

.configId("ssl-config-id")

975

.configName("ssl-config")

976

.file(ConfigFile.builder()

977

.name("ssl.conf")

978

.uid(33L) // www-data

979

.gid(33L)

980

.mode(0644L)

981

.build())

982

.build()

983

)

984

985

.build())

986

.build())

987

.build();

988

989

docker.createService(serviceWithConfigs);

990

```

991

992

### Config Updates

993

994

```java { .api }

995

// Update config (creates new version)

996

Config existingConfig = docker.inspectConfig("nginx-config");

997

String newConfigData = "server {\n listen 443 ssl;\n server_name example.com;\n}";

998

999

ConfigSpec updatedSpec = existingConfig.spec().toBuilder()

1000

.data(Base64.getEncoder().encodeToString(newConfigData.getBytes()))

1001

.labels(Map.of(

1002

"application", "nginx",

1003

"version", "2.0",

1004

"ssl", "enabled"

1005

))

1006

.build();

1007

1008

docker.updateConfig(existingConfig.id(), existingConfig.version().index(), updatedSpec);

1009

```

1010

1011

### Config Removal

1012

1013

```java { .api }

1014

// Remove config

1015

docker.deleteConfig("config-name-or-id");

1016

1017

// Bulk config cleanup

1018

public void cleanupOldConfigs(DockerClient docker, String namePrefix)

1019

throws DockerException, InterruptedException {

1020

1021

List<Config> configs = docker.listConfigs();

1022

1023

for (Config config : configs) {

1024

String configName = config.spec().name();

1025

if (configName.startsWith(namePrefix)) {

1026

1027

// Check if config is in use

1028

boolean inUse = isConfigInUse(docker, config.id());

1029

1030

if (!inUse) {

1031

try {

1032

docker.deleteConfig(config.id());

1033

System.out.println("Removed unused config: " + configName);

1034

} catch (DockerException e) {

1035

System.err.println("Failed to remove config " + configName + ": " + e.getMessage());

1036

}

1037

} else {

1038

System.out.println("Config in use, skipping: " + configName);

1039

}

1040

}

1041

}

1042

}

1043

1044

private boolean isConfigInUse(DockerClient docker, String configId)

1045

throws DockerException, InterruptedException {

1046

1047

List<Service> services = docker.listServices();

1048

for (Service service : services) {

1049

TaskSpec taskSpec = service.spec().taskTemplate();

1050

if (taskSpec.containerSpec().configs() != null) {

1051

for (ConfigBind config : taskSpec.containerSpec().configs()) {

1052

if (configId.equals(config.configId()) || configId.equals(config.configName())) {

1053

return true;

1054

}

1055

}

1056

}

1057

}

1058

return false;

1059

}

1060

```

1061

1062

## Complete Swarm Deployment Example

1063

1064

```java { .api }

1065

public class SwarmDeploymentExample {

1066

1067

public void deployCompleteApplication(DockerClient docker)

1068

throws DockerException, InterruptedException {

1069

1070

System.out.println("Deploying complete multi-service application to swarm...");

1071

1072

// 1. Initialize swarm if needed

1073

try {

1074

docker.inspectSwarm();

1075

System.out.println("Swarm already initialized");

1076

} catch (DockerException e) {

1077

initializeSwarm(docker);

1078

}

1079

1080

// 2. Create application network

1081

createApplicationNetwork(docker);

1082

1083

// 3. Create secrets and configs

1084

createSecretsAndConfigs(docker);

1085

1086

// 4. Deploy database service

1087

deployDatabaseService(docker);

1088

1089

// 5. Deploy application service

1090

deployApplicationService(docker);

1091

1092

// 6. Deploy load balancer

1093

deployLoadBalancer(docker);

1094

1095

// 7. Monitor deployment

1096

monitorDeployment(docker);

1097

1098

System.out.println("Application deployment completed");

1099

}

1100

1101

private void initializeSwarm(DockerClient docker)

1102

throws DockerException, InterruptedException {

1103

1104

SwarmInit init = SwarmInit.builder()

1105

.listenAddr("0.0.0.0:2377")

1106

.build();

1107

1108

String nodeId = docker.initSwarm(init);

1109

System.out.println("Initialized swarm with node: " + nodeId);

1110

}

1111

1112

private void createApplicationNetwork(DockerClient docker)

1113

throws DockerException, InterruptedException {

1114

1115

NetworkConfig networkConfig = NetworkConfig.builder()

1116

.name("app-network")

1117

.driver("overlay")

1118

.attachable(true)

1119

.labels(Map.of("purpose", "application"))

1120

.build();

1121

1122

try {

1123

docker.createNetwork(networkConfig);

1124

System.out.println("Created application network");

1125

} catch (DockerException e) {

1126

System.out.println("Network already exists");

1127

}

1128

}

1129

1130

private void createSecretsAndConfigs(DockerClient docker)

1131

throws DockerException, InterruptedException {

1132

1133

// Database password secret

1134

SecretSpec dbSecret = SecretSpec.builder()

1135

.name("db-password")

1136

.data(Base64.getEncoder().encodeToString("secure-password".getBytes()))

1137

.build();

1138

1139

// Application config

1140

String appConfig = """

1141

database:

1142

host: postgres

1143

port: 5432

1144

name: myapp

1145

server:

1146

port: 8080

1147

""";

1148

1149

ConfigSpec appConfigSpec = ConfigSpec.builder()

1150

.name("app-config")

1151

.data(Base64.getEncoder().encodeToString(appConfig.getBytes()))

1152

.build();

1153

1154

try {

1155

docker.createSecret(dbSecret);

1156

docker.createConfig(appConfigSpec);

1157

System.out.println("Created secrets and configs");

1158

} catch (DockerException e) {

1159

System.out.println("Secrets/configs already exist");

1160

}

1161

}

1162

1163

private void deployDatabaseService(DockerClient docker)

1164

throws DockerException, InterruptedException {

1165

1166

ServiceSpec dbService = ServiceSpec.builder()

1167

.name("postgres")

1168

.taskTemplate(TaskSpec.builder()

1169

.containerSpec(ContainerSpec.builder()

1170

.image("postgres:13")

1171

.env("POSTGRES_DB=myapp", "POSTGRES_USER=app")

1172

.secrets(SecretBind.builder()

1173

.secretName("db-password")

1174

.file(SecretFile.builder()

1175

.name("postgres_password")

1176

.uid(999L) // postgres user

1177

.gid(999L)

1178

.mode(0400L)

1179

.build())

1180

.build())

1181

.mounts(Mount.builder()

1182

.type("volume")

1183

.source("postgres-data")

1184

.target("/var/lib/postgresql/data")

1185

.build())

1186

.build())

1187

.networks(NetworkAttachmentConfig.builder()

1188

.target("app-network")

1189

.aliases("database")

1190

.build())

1191

.placement(Placement.builder()

1192

.constraints("node.role==manager") // Database on manager for persistence

1193

.build())

1194

.build())

1195

.mode(ServiceMode.builder()

1196

.replicated(ReplicatedService.builder()

1197

.replicas(1L)

1198

.build())

1199

.build())

1200

.build();

1201

1202

docker.createService(dbService);

1203

System.out.println("Deployed database service");

1204

}

1205

1206

private void deployApplicationService(DockerClient docker)

1207

throws DockerException, InterruptedException {

1208

1209

ServiceSpec appService = ServiceSpec.builder()

1210

.name("webapp")

1211

.taskTemplate(TaskSpec.builder()

1212

.containerSpec(ContainerSpec.builder()

1213

.image("myapp:latest")

1214

.configs(ConfigBind.builder()

1215

.configName("app-config")

1216

.file(ConfigFile.builder()

1217

.name("config.yml")

1218

.uid(1000L)

1219

.gid(1000L)

1220

.mode(0644L)

1221

.build())

1222

.build())

1223

.secrets(SecretBind.builder()

1224

.secretName("db-password")

1225

.file(SecretFile.builder()

1226

.name("db_password")

1227

.uid(1000L)

1228

.gid(1000L)

1229

.mode(0400L)

1230

.build())

1231

.build())

1232

.healthcheck(HealthConfig.builder()

1233

.test("CMD curl -f http://localhost:8080/health")

1234

.interval(Duration.ofSeconds(30))

1235

.timeout(Duration.ofSeconds(10))

1236

.retries(3)

1237

.build())

1238

.build())

1239

.networks(NetworkAttachmentConfig.builder()

1240

.target("app-network")

1241

.aliases("backend")

1242

.build())

1243

.placement(Placement.builder()

1244

.constraints("node.role==worker")

1245

.build())

1246

.resources(ResourceRequirements.builder()

1247

.limits(Resources.builder()

1248

.memoryBytes(512L * 1024 * 1024)

1249

.nanoCpus(500_000_000L)

1250

.build())

1251

.build())

1252

.build())

1253

.mode(ServiceMode.builder()

1254

.replicated(ReplicatedService.builder()

1255

.replicas(3L)

1256

.build())

1257

.build())

1258

.updateConfig(UpdateConfig.builder()

1259

.parallelism(1L)

1260

.delay(Duration.ofSeconds(10))

1261

.failureAction("rollback")

1262

.build())

1263

.build();

1264

1265

docker.createService(appService);

1266

System.out.println("Deployed application service");

1267

}

1268

1269

private void deployLoadBalancer(DockerClient docker)

1270

throws DockerException, InterruptedException {

1271

1272

ServiceSpec lbService = ServiceSpec.builder()

1273

.name("nginx-lb")

1274

.taskTemplate(TaskSpec.builder()

1275

.containerSpec(ContainerSpec.builder()

1276

.image("nginx:latest")

1277

.build())

1278

.networks(NetworkAttachmentConfig.builder()

1279

.target("app-network")

1280

.build())

1281

.build())

1282

.mode(ServiceMode.builder()

1283

.replicated(ReplicatedService.builder()

1284

.replicas(2L)

1285

.build())

1286

.build())

1287

.endpointSpec(EndpointSpec.builder()

1288

.ports(PortConfig.builder()

1289

.targetPort(80L)

1290

.publishedPort(80L)

1291

.protocol("tcp")

1292

.publishMode("ingress")

1293

.build())

1294

.build())

1295

.build();

1296

1297

docker.createService(lbService);

1298

System.out.println("Deployed load balancer service");

1299

}

1300

1301

private void monitorDeployment(DockerClient docker)

1302

throws DockerException, InterruptedException {

1303

1304

System.out.println("Monitoring deployment status...");

1305

1306

String[] services = {"postgres", "webapp", "nginx-lb"};

1307

1308

for (int i = 0; i < 30; i++) { // Wait up to 5 minutes

1309

boolean allReady = true;

1310

1311

for (String serviceName : services) {

1312

Service service = docker.inspectService(serviceName);

1313

1314

List<Task> tasks = docker.listTasks(Task.Criteria.builder()

1315

.serviceName(serviceName)

1316

.taskState("running")

1317

.build());

1318

1319

Long replicas = service.spec().mode().replicated().replicas();

1320

1321

System.out.printf("Service %s: %d/%d replicas running%n",

1322

serviceName, tasks.size(), replicas);

1323

1324

if (tasks.size() < replicas) {

1325

allReady = false;

1326

}

1327

}

1328

1329

if (allReady) {

1330

System.out.println("All services are ready!");

1331

return;

1332

}

1333

1334

Thread.sleep(10000); // Wait 10 seconds

1335

}

1336

1337

System.out.println("Deployment monitoring timeout");

1338

}

1339

}

1340

```

1341

1342

This comprehensive Docker Swarm system provides full orchestration capabilities with service management, security through secrets and configs, node management, and production deployment patterns for scalable containerized applications.