Files
docker/readme.hints.md

4.7 KiB
Raw Permalink Blame History

Docker Module - Development Hints

OOP Refactoring - Clean Architecture (2025-11-24)

Architecture Changes

The module has been restructured to follow a clean OOP Facade pattern:

  • DockerHost is now the single entry point for all Docker operations
  • All resource classes extend abstract DockerResource base class
  • Static methods are prefixed with _ to indicate internal use
  • Public API is exclusively through DockerHost methods

Key Changes

1. Factory Pattern

  • All resource creation/retrieval goes through DockerHost:
    // Old (deprecated):
    const container = await DockerContainer.getContainers(dockerHost);
    const network = await DockerNetwork.createNetwork(dockerHost, descriptor);
    
    // New (clean API):
    const containers = await dockerHost.getContainers();
    const network = await dockerHost.createNetwork(descriptor);
    

2. Container Management Methods Added The DockerContainer class now has full CRUD and streaming operations:

Lifecycle:

  • container.start() - Start container
  • container.stop(options?) - Stop container
  • container.remove(options?) - Remove container
  • container.refresh() - Reload state

Information:

  • container.inspect() - Get detailed info
  • container.logs(options) - Get logs as string (one-shot)
  • container.stats(options) - Get stats

Streaming & Interactive:

  • container.streamLogs(options) - Stream logs continuously (follow mode)
  • container.attach(options) - Attach to main process (PID 1) with bidirectional stream
  • container.exec(command, options) - Execute commands in container interactively

Example - Stream Logs:

const container = await dockerHost.getContainerById('abc123');
const logStream = await container.streamLogs({ timestamps: true });

logStream.on('data', (chunk) => {
  console.log(chunk.toString());
});

Example - Attach to Container:

const { stream, close } = await container.attach({
  stdin: true,
  stdout: true,
  stderr: true
});

// Pipe to/from process
process.stdin.pipe(stream);
stream.pipe(process.stdout);

// Later: detach
await close();

Example - Execute Command:

const { stream, close } = await container.exec('ls -la /app', {
  tty: true
});

stream.on('data', (chunk) => {
  console.log(chunk.toString());
});

stream.on('end', async () => {
  await close();
});

3. DockerResource Base Class All resource classes now extend DockerResource:

  • Consistent dockerHost property (not dockerHostRef)
  • Required refresh() method
  • Standardized constructor pattern

4. ImageStore Encapsulation

  • dockerHost.imageStore is now private
  • Use dockerHost.storeImage(name, stream) instead
  • Use dockerHost.retrieveImage(name) instead

5. Creation Descriptors Support Both Primitives and Instances Interfaces now accept both strings and class instances:

// Both work:
await dockerHost.createService({
  image: 'nginx:latest',  // String
  networks: ['my-network'],  // String array
  secrets: ['my-secret']  // String array
});

await dockerHost.createService({
  image: imageInstance,  // DockerImage instance
  networks: [networkInstance],  // DockerNetwork array
  secrets: [secretInstance]  // DockerSecret array
});

Migration Guide

Replace all static method calls with dockerHost methods:

  • DockerContainer.getContainers(host)dockerHost.getContainers()
  • DockerImage.createFromRegistry(host, opts)dockerHost.createImageFromRegistry(opts)
  • DockerService.createService(host, desc)dockerHost.createService(desc)
  • dockerHost.imageStore.storeImage(...)dockerHost.storeImage(...)

smartrequest v5+ Migration (2025-11-17)

Breaking Change

smartrequest v5.0.0+ returns web ReadableStream objects (Web Streams API) instead of Node.js streams.

Solution Implemented

All streaming methods now convert web ReadableStreams to Node.js streams using:

plugins.smartstream.nodewebhelpers.convertWebReadableToNodeReadable(webStream)

Files Modified

  • ts/classes.host.ts:

    • requestStreaming() - Converts web stream to Node.js stream before returning
    • getEventObservable() - Works with converted Node.js stream
  • ts/classes.image.ts:

    • createFromTarStream() - Uses converted Node.js stream for event handling
    • exportToTarStream() - Uses converted Node.js stream for backpressure management

Testing

  • Build:  All 11 type errors resolved
  • Tests:  Node.js tests pass (DockerHost, DockerContainer, DockerImage, DockerImageStore)

Notes

  • The conversion maintains backward compatibility with existing code expecting Node.js stream methods (.on(), .emit(), .pause(), .resume())
  • smartstream's nodewebhelpers module provides bidirectional conversion utilities between web and Node.js streams