Self-hosted service
docker/docker-py avatar
docker/docker-py

docker-py: the Docker SDK for Python, from install to first container

A Python library for the Docker Engine API

7,223 stars1,729 forksPythonApache-2.0

At a glance

What is it?
docker-py is the official Python client for the Docker Engine API. It installs with pip, talks to the daemon over the socket or DOCKER_HOST, and exposes containers, images and Swarms as Python objects.
Who is it for?
Adopt docker-py when a Python process needs to drive the Docker Engine API directly: starting containers, pulling images, streaming logs or managing Swarms. Do not adopt it as a replacement for the docker CLI in shell scripts, and do not expect it to manage Compose projects, because the README and the package metadata describe only the Engine API surface.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • docker/docker-py7,223 ★ · +10
Star history
Repository2026-09-232026-11-14
docker/docker-py7.2k7.2k

10 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

What docker-py is for, and who ends up using it

The README states the scope in one line: it lets you do anything the docker command does, but from within Python apps, running containers, managing containers and managing Swarms. That framing matters. docker-py is not a wrapper around the CLI binary and it is not a Compose implementation. It is a client for the Docker Engine API, which means every call maps to an HTTP endpoint on the daemon.

The audience is therefore narrower than "Python developers who use Docker". It is for people writing code that must decide at runtime what containers exist. A test harness that starts a database container per suite, a CI helper that pulls an image and inspects its labels, a control plane that lists containers across a host and reads their logs: these are the shapes that fit. If you only ever type docker run by hand, the library adds a dependency without removing any work.

How the client talks to the daemon

The entry point is docker.from_env(), which connects using the default socket or the configuration in your environment. That single function hides the transport decision: on a Unix host it resolves to the local socket, and environment variables such as DOCKER_HOST redirect it elsewhere. The README does not enumerate the variables it reads, so treat the environment as the configuration surface and check the documentation site before assuming a variable is honoured.

Above the transport sits an object model. client.containers, client.images and the Swarm namespace are collections that return typed objects. A Container exposes attrs, which is the raw inspection dictionary, alongside methods like logs() and stop(). Container.logs(stream=True) returns an iterator rather than a string, so log tailing becomes a normal Python loop. The dependency list in pyproject.toml is deliberately small: requests, urllib3, and pywin32 on Windows. Everything else is optional. SSH connections need paramiko through the ssh extra, and WebSocket attach needs websocket-client through the websockets extra, though the metadata notes that docker-py hijacks the TCP connection by default and only uses WebSockets when attach_socket(container, ws=True) is called.

Installing docker-py and running your first container

The README gives one install command and notes that the old docker[tls] extra is no longer required, since TLS support is always present and the extra is now a no-op kept for backwards compatibility.

bash
pip install docker

The package requires Python 3.8 or newer according to pyproject.toml. Once installed, the shortest working program connects to the local daemon and runs a command in a container, returning its output as a string.

python
import docker
client = docker.from_env()
result = client.containers.run("ubuntu:latest", "echo hello world")
print(result)

The README shows the return value as 'hello world\n'. Two details are easy to miss. First, containers.run without detach blocks until the container exits, so a long-running process will hang your program. Second, the daemon must already be reachable; from_env() does not start one.

For a background container, pass detach=True, which returns a Container object instead of output.

python
container = client.containers.run("bfirsh/reticulate-splines", detach=True)
for line in container.logs(stream=True):
    print(line.strip())
container.stop()

The README example calls strip() on each line before printing. Image management follows the same collection pattern: client.images.pull("nginx") returns an Image, and client.images.list() returns the local set.

Where docker-py is the wrong tool

The library covers the Engine API and stops there. Multi-service orchestration described in a Compose file is outside what the README claims, so a team that wants to bring up a Compose project from Python will need another mechanism and should not expect docker-py to fill the gap.

Version skew is the second boundary. The Engine API is versioned, and the Makefile pins TEST_API_VERSION to 1.45 and TEST_ENGINE_VERSION to 26.1 for the project's own integration runs. That tells you the maintainers test against a specific pairing, not against every daemon in the field. A client that is newer than the daemon it reaches can fail on endpoints the daemon does not implement. The README does not document rollback behaviour or a compatibility matrix, so pinning both the library version and the daemon version is the safe posture.

Finally, consider whether the CLI is simply better for the job. Shell scripts that already parse docker output gain nothing from a Python dependency, and short-lived automation where the process starts one container will spend more lines on client setup than on the actual work.

How docker-py differs from docker compose

The practical alternative people weigh is not another Python client but Compose. Compose takes a declarative YAML file describing services, networks and volumes and reconciles the daemon toward that description. docker-py takes imperative calls: you write the sequence, you decide when to pull, when to start, when to stop, and you handle the failure of each step yourself.

The difference shows up in idempotency. Re-running a Compose file converges on the same set of services. Re-running a docker-py script that calls containers.run creates another container unless your code checks first, for example by looking the container up with client.containers.get() and handling the not-found case. If your problem is "describe a stack and keep it running", Compose is the shorter path. If your problem is "react to what is currently on this host", the imperative client is the one that fits.

Maintenance, releases and the Apache-2.0 licence

The repository is not archived, and the last push was on 2026-10-28. Release cadence is uneven rather than steady: 7.0.0 shipped on 2023-12-08, 7.1.0 on 2024-05-23, and 7.2.0 on 2026-07-09. Anyone pinning a version should read the changelog between those tags rather than assume small version bumps carry small changes, since a major bump signals a breaking change by convention.

Upgrade cost is mostly a function of your daemon. Because the library speaks the Engine API, a client upgrade can change which API version it requests, and that is where breakage tends to appear. The project's own test setup pins an API version and an engine version, which is a reasonable template for consumers: pin the library, pin the daemon, and test the pair together.

The licence is Apache-2.0, declared both in the repository LICENSE file and in pyproject.toml. That is a permissive licence with an explicit patent grant, and it is compatible with commercial use. This is a description of what the repository declares, not legal advice; route the actual review to whoever handles licensing at your organisation. The maintainer field lists Docker Inc. with the email [email protected], so the project is vendor-published rather than community-governed.

Editorial conclusion

Adopt docker-py when a Python process needs to drive the Docker Engine API directly: starting containers, pulling images, streaming logs or managing Swarms. Do not adopt it as a replacement for the docker CLI in shell scripts, and do not expect it to manage Compose projects, because the README and the package metadata describe only the Engine API surface. Before committing, verify that the client version negotiates against the API version of your daemon, and check whether your connection needs the ssh extra, since the default install does not include paramiko.

Frequently asked questions

Can I use Docker with Python?

Yes. docker-py is a Python library for the Docker Engine API, and the README describes it as letting you do anything the docker command does from within Python apps, including running and managing containers and managing Swarms.

How to install Docker in Python?

The README gives a single command, pip install docker, which pulls the latest stable version from PyPI. The older docker[tls] extra is no longer required because TLS support is always present, and the extra remains only as a no-op for backwards compatibility.

What is docker-py?

It is a Python library for the Docker Engine API, published as the docker package on PyPI and licensed under Apache-2.0. It connects to the daemon through docker.from_env() and exposes containers, images and Swarms as Python objects.

Official sources

  1. docker/docker-py on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/docker-docker-py.svg)](https://hysenlabs.com/projects/docker-docker-py)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/docker-docker-py.svg)](https://hysenlabs.com/projects/docker-docker-py)

Was this useful?