mrkeyoor.com_
Wed 23 Sept 00:33 UTC
npmTestingupdated 22 Sept 2026

docker-compose review

docker-compose 1.4.2 lets Node code invoke the external Docker Compose CLI through promise-returning functions such as `upAll`, `down`, `exec`, `ps`, and `config`. It spawns `docker compose` by default, captures stdout, stderr, and the exit code, and can parse several command results. The package includes TypeScript declarations and also supports the retired standalone `docker-compose` executable. It is a process wrapper for test setup scripts, not a Docker engine, a Compose implementation, or a container test framework.

Verdict

docker-compose 1.4.2 installed in 0.7 seconds and occupied 2 MB in our sandbox, but every useful call still depends on a working host Docker setup. It fits a Node test runner that already owns a Compose project; use Testcontainers when the tests need readiness and lifecycle guarantees.

We installed it

Lab card: what happened when we installed docker-composeScreenshot of docker-compose documentation
Install✓ · 0.7s3 packages on disk · 2 MB
ImportESM import works · require() works · CommonJS package
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does docker-compose install cleanly?

Yes. In a fresh container with an empty cache, npm install docker-compose finished in 0.7s, leaving 3 packages and 2 MB on disk. npm audit reported no known vulnerabilities.

Can docker-compose run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does docker-compose work with both ESM and CommonJS?

Yes. Both import 'docker-compose' and require('docker-compose') worked in Node 22 in our run. The package is published as CommonJS.

Does docker-compose include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

docker-compose or testcontainers: which should you use?

testcontainers: Choose it when tests need wait strategies, mapped ports, isolated containers, and managed cleanup. docker-compose 1.4.2 installed in 0.7 seconds and occupied 2 MB in our sandbox, but every useful call still depends on a working host Docker setup.

When should you not use docker-compose?

Docker, its daemon, or the Compose plugin is absent. The README says Compose is required, and this npm package installs none of those system pieces.

API stability4/5Version 1.4.2 keeps a function-per-command interface and a shared result containing stdout, stderr, and exit status. Since 1.0, the default executable has been the Compose v2 plugin, while an option preserves standalone v1 calls. Most future risk sits outside the JavaScript API because forwarded flags, JSON formats, and command behavior follow Docker's separately released CLI.
Docs4/5The project site documents individual commands, common options, result types, progress callbacks, parsed `ps` output, and in-memory Compose objects. Its README puts the v2 default and the 500 ms teardown workaround in plain sight. Some wording has aged, including Node 6 and Node 8 test references, so the current declaration files and Docker CLI documentation remain necessary for edge cases.
Maintenance4/5GitHub records a push on August 9, 2026, 222 stars, 20 open issues and pull requests, and an unarchived repository. Version 1.4.2 carries current Compose schema, YAML, test, and documentation work. The stale README claims that the project is just getting started and discusses Node 6, which suggests code and reference pages receive more attention than introductory copy.
Ecosystem4/5npm counted 6,187,155 downloads for the week ending August 24, 2026. The wrapper understands common Compose operations and works from ordinary Node scripts with bundled types. It has little extension surface of its own, and actual compatibility depends on the installed Docker CLI, daemon, Compose files, registries, credential helpers, and host permissions.

Use it if

  • A Node integration-test runner already has a Compose file and needs programmatic setup and teardown.
  • You want typed wrappers around common Compose commands and parsed output from `ps`, `config`, `images`, `port`, or `version`.
  • Your script must feed a YAML string or a typed Compose object through stdin instead of creating a temporary file.
  • One codebase must address both the Compose v2 plugin and a configured standalone `docker-compose` binary.
Skip it if

Setup reality

We installed docker-compose 1.4.2 in a clean Node 22 Bookworm sandbox. npm finished in 0.7 seconds and left 3 packages occupying 2 MB. The package has 1 direct dependency, no peer dependencies, and 236 KB unpacked. npm audit reported 0 known vulnerabilities. CommonJS require() and ESM import both worked, and TypeScript declarations are included.

That successful install supplies only the JavaScript wrapper. The host still needs Docker, the Compose v2 plugin, a reachable daemon, registry credentials, and user permission for the Docker socket. Calls normally need the project cwd or explicit config files. Set executable.standalone only for an old docker-compose binary; the default process is docker compose.

The env option becomes the child's whole environment. Include ...process.env if Compose still needs PATH, DOCKER_HOST, or credential-helper settings. A nonzero CLI exit rejects with captured output and an exit code, so test cleanup belongs in finally. Adding --volumes to down deletes the project's named volumes.

run and exec force -T, and string commands are split at whitespace. Use an argument array when a path or value contains spaces. The 500 ms delay after stop and down is only a timing workaround. It does not check readiness or resource removal. Our browser build failed under esbuild, consistent with a Node-only child-process wrapper.

Patterns

Bring up the complete project start-all-services

import path from 'node:path';
import { upAll } from 'docker-compose';

await upAll({
  cwd: path.resolve('test/stack'),
  log: true,
});

`upAll` adds detached mode unless command options request attached or abort-on-exit behavior. Docker must already work for this user.

Start a service subset start-selected-services

import { upMany } from 'docker-compose';

await upMany(['postgres', 'redis'], {
  cwd: process.cwd(),
  commandOptions: ['--build'],
});

Compose can still start declared dependencies. Add `--no-deps` only when those dependencies are intentionally excluded.

Guarantee teardown after a test tear-down-in-tests

import { down, upAll } from 'docker-compose';

await upAll({ cwd: stackDir });
try {
  await runIntegrationSuite();
} finally {
  await down({ cwd: stackDir, commandOptions: ['--remove-orphans'] });
}

The promise includes a 500 ms delay for Compose v2 teardown, but callers should still verify resources when removal timing matters.

Delete disposable volumes remove-test-volumes

await compose.down({
  cwd: stackDir,
  commandOptions: ['--volumes', ['--timeout', '20']],
});

`--volumes` removes named project volumes. Do not use it against a developer environment whose data must survive.

Run a one-off test command run-one-off-command

const result = await compose.run(
  'app',
  ['npm', 'test', '--', '--runInBand'],
  { cwd: stackDir, commandOptions: ['--rm', '--no-deps'] }
);
console.log(result.out);

Arrays preserve argument boundaries. String commands are split on whitespace, and this method disables TTY allocation with `-T`.

Execute inside an existing service exec-in-running-service

const result = await compose.exec(
  'app',
  ['node', 'scripts/health check.js'],
  { cwd: stackDir }
);
console.log(result.exitCode, result.out);

The service must already be running. Passing the command as an array preserves filenames and values containing spaces.

Read structured container state inspect-service-state

const result = await compose.ps({
  cwd: stackDir,
  commandOptions: [['--format', 'json']],
});

for (const service of result.data.services) {
  console.log(service.name, service.state, service.ports);
}

`--format json` maps into defined state values. Default table output remains human-oriented text such as `Up 2 hours`.

Check and inspect configuration validate-compose-config

const validated = await compose.config({ cwd: stackDir });
const listed = await compose.configServices({ cwd: stackDir });

console.log(validated.data.config);
console.log(listed.data.services);

Both calls reject on a nonzero Compose exit. `config` parses YAML, while `configServices` returns the service-name list.

Supply Compose data from memory provide-compose-object

import { type ComposeSpecification, upAll } from 'docker-compose';

const compose: ComposeSpecification = {
  services: {
    cache: { image: 'redis:7-alpine', ports: ['0:6379'] },
  },
};

await upAll({ compose });

The wrapper serializes this object to YAML and pipes it to Compose. Pin image tags if repeatable tests matter.

Layer Compose files in order use-multiple-config-files

await compose.upAll({
  cwd: stackDir,
  config: ['compose.yml', 'compose.test.yml'],
});

Every path becomes a separate `-f` argument relative to `cwd`. An inline config string wins when both forms are present.

Observe a long-running build stream-command-output

await compose.buildAll({
  cwd: stackDir,
  parallel: true,
  callback: (chunk, source) => {
    process[source === 'stderr' ? 'stderr' : 'stdout'].write(chunk);
  },
});

The callback streams chunks, yet the wrapper also buffers full stdout and stderr until completion.

Extend the child environment safely preserve-child-environment

await compose.pullAll({
  cwd: stackDir,
  env: {
    ...process.env,
    COMPOSE_PROJECT_NAME: 'mrkeyoor-tests',
  },
});

The `env` object replaces the child's environment. Copy `process.env` if Compose needs PATH, Docker variables, or credential settings.

Alternatives

PackageRegistryPick it when
testcontainersnpmChoose it when tests need wait strategies, mapped ports, isolated containers, and managed cleanup.
dockerodenpmChoose it for direct Docker Engine API access without parsing Compose CLI behavior.
execanpmChoose it when a general subprocess API plus a few explicit Compose commands is easier to audit.

More testing guides

pytest · chai · jsdom · vitest · playwright · coverage · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.