Dockerode: Node.js Docker Remote API Client
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
-
connect ECONNREFUSED [host]:[port]
cause The Docker daemon is not running, or `dockerode` is configured to connect to an incorrect host, port, or socket path.fixVerify your Docker daemon is running (`sudo systemctl start docker` or `docker start`). Check your Dockerode connection configuration (e.g., `socketPath`, `host`, `port`, or the `DOCKER_HOST` environment variable) and ensure it matches your Docker setup. -
(HTTP code 404) no such container - No such container: [container_id_or_name]
cause Attempting to interact with a Docker container that does not exist or whose ID/name is incorrect for the connected Docker daemon.fixDouble-check the container ID or name you are using. Ensure the container exists on the Docker daemon you are connected to by listing all containers (`docker ps -a`). -
(HTTP code 400) bad parameter - API version is too old. Minimum is vX.Y, got vA.B
cause The Docker API version specified in dockerode's configuration (`version` option) is incompatible with the Docker daemon's API version.fixUpdate the `version` option in your `new Docker()` constructor to match your Docker daemon's API version (e.g., 'v1.41'). You can find your daemon's API version with `docker version --format '{{.Server.APIVersion}}'`. -
Cannot read properties of undefined (reading 'start')
cause An operation on a Docker entity (like `container.start()`) is being called on an `undefined` object. This typically happens when a preceding asynchronous operation (e.g., `docker.createContainer()`) failed or returned `null`/`undefined` without proper error handling.fixEnsure all asynchronous Dockerode operations are `await`ed or chained with `.then().catch()` appropriately. Always check that the resulting entity objects are valid before attempting subsequent operations on them to prevent `undefined` references.
Warnings
- breaking Major version 4.0.0 potentially introduces breaking changes due to significant dependency updates (e.g., `docker-modem`) and internal refactors. While specific API changes aren't detailed in the changelog, users upgrading from v3.x should thoroughly test their integrations. Changes might include updated types, refined method signatures, or altered default behaviors.
- breaking Version 4.0.2 included an important security update for the underlying `SSH2` dependency (via `docker-modem`) to address CVE-2023-48795. This is a critical security fix for users connecting to Docker daemons via SSH. Ensure you are on at least v4.0.2 or a higher patched version.
- gotcha Incorrect Docker API versioning can lead to unexpected errors or unsupported operations. Dockerode explicitly recommends specifying the API version for Docker versions >= v1.13. Failing to set the 'version' option or setting an incompatible version will result in API errors directly from the Docker daemon.
- gotcha Dockerode leverages Node.js streams extensively for operations like container logs, exec streams, and build streams. Improperly handling or not consuming these streams can lead to resource leaks, process hangs, or unexpected behavior due to unread data or unclosed connections. Always ensure streams are properly piped, consumed, or closed.
Install
-
npm install dockerode -
yarn add dockerode -
pnpm add dockerode
Imports
- Docker
import { Docker } from 'dockerode';import Docker from 'dockerode';
- Docker (CommonJS)
const Docker = require('dockerode'); - Container/Image types
import type { Container, Image, ImageInfo, ContainerInfo } from 'dockerode';
Quickstart
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();