Dockerode: Node.js Docker Remote API Client

4.0.10 · active · verified Tue Apr 21

Dockerode is a comprehensive Node.js module designed for programmatically interacting with the Docker Remote API. It provides a robust, feature-rich interface for managing Docker containers, images, networks, and other Docker entities, aiming to implement all features exposed by the Docker Remote API. Key differentiators include its strong emphasis on native Node.js streams for operations like logs and execs, allowing for flexible stream manipulation and demultiplexing. It treats Docker entities (containers, images, execs) as distinct objects, and offers both callback and Promise-based interfaces, catering to various asynchronous programming styles. The package maintains a steady release cadence with frequent patch updates for dependencies and minor bug fixes, with the current stable version being 4.0.10. It is built to be highly testable and closely track changes in the official Docker API, acting as a direct wrapper that passes options to Docker and returns its responses largely unchanged.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates a full container lifecycle: pulling an image, creating, starting, attaching to logs, waiting for exit, and removing a Docker container using the Promise-based API.

import Docker from 'dockerode';
import process from 'process';
import stream from 'stream';

const docker = new Docker({
  socketPath: process.env.DOCKER_SOCKET_PATH || '/var/run/docker.sock', // Default for Linux
  host: process.env.DOCKER_HOST || undefined, // e.g., 'http://192.168.1.10'
  port: process.env.DOCKER_PORT || undefined, // e.g., 2375
  version: 'v1.41' // It's recommended to specify your Docker daemon's API version
});

async function runDockerLifecycleExample() {
  let auxContainer: Docker.Container | undefined;
  const imageName = 'ubuntu:latest';

  try {
    console.log(`Checking if image '${imageName}' exists...`);
    const images = await docker.listImages({ filters: { reference: [imageName] } });
    if (images.length === 0) {
      console.log(`Image '${imageName}' not found locally. Pulling...`);
      await docker.pull(imageName, {});
      console.log(`Image '${imageName}' pulled.`);
    }

    console.log('Creating a new Ubuntu container...');
    auxContainer = await docker.createContainer({
      Image: imageName,
      AttachStdin: false,
      AttachStdout: true,
      AttachStderr: true,
      Tty: true,
      Cmd: ['/bin/bash', '-c', 'echo "Hello from Dockerode inside container!"; sleep 3; echo "Exiting."; exit 0;'],
      OpenStdin: false,
      StdinOnce: false
    });
    console.log(`Container created with ID: ${auxContainer.id}`);

    console.log('Starting container...');
    await auxContainer.start();
    console.log('Container started. Attaching to logs...');

    const logStream = await auxContainer.logs({ follow: true, stdout: true, stderr: true });
    const outputStream = new stream.PassThrough();
    logStream.pipe(outputStream);
    outputStream.on('data', (chunk) => console.log(`[LOG]: ${chunk.toString('utf8').trim()}`));
    outputStream.on('end', () => console.log('Log stream ended.'));

    console.log('Waiting for container to exit...');
    const exitResult = await auxContainer.wait();
    console.log(`Container exited with status code: ${exitResult.StatusCode}`);

    console.log('Removing container...');
    await auxContainer.remove();
    console.log('Container removed successfully.');

  } catch (err) {
    console.error('An error occurred during Docker operation:', err);
    if (auxContainer) {
      try {
        console.error('Attempting to force-remove container due to error...');
        await auxContainer.remove({ force: true });
        console.error('Container force-removed.');
      } catch (removeErr) {
        console.error('Failed to force-remove container:', removeErr);
      }
    }
    process.exit(1);
  }
}

runDockerLifecycleExample();

view raw JSON →