1 min read

Docker Container Manager

This guide demonstrates how to manage Docker containers using the official docker SDK for Python. It allows you to automate container lifecycle management (listing, running, stopping, removing) from a Python script.

Modules Used:

  • docker: The official Python library for the Docker Engine API.
  • argparse: To handle command-line arguments.

Prerequisites

  1. Docker Desktop (or Docker Engine) must be installed and running.
  2. The user running the script must have permission to access the Docker socket (on Linux, add user to docker group).

Installation

pip install docker

The Code

Save this as docker_manager.py.

import docker
import argparse
import sys

def get_client():
    try:
        # Connects to the Docker daemon using default socket or environment variables
        return docker.from_env()
    except docker.errors.DockerException as e:
        print(f"Error connecting to Docker: {e}")
        print("Ensure Docker is running.")
        return None

def list_containers(show_all=False):
    client = get_client()
    if not client: return

    containers = client.containers.list(all=show_all)
    if not containers:
        print("No containers found.")
        return

    print(f"{'ID':<12} {'Image':<25} {'Status':<10} {'Name'}")
    print("-" * 65)
    for c in containers:
        # Short ID
        cid = c.short_id
        # Image tags might be a list, take the first one or ID
        image = c.image.tags[0] if c.image.tags else c.image.id[:12]
        # Truncate image name if too long
        if len(image) > 23: image = image[:22] + "..."

        print(f"{cid:<12} {image:<25} {c.status:<10} {c.name}")

def run_container(image, name=None, detach=True, ports=None):
    client = get_client()
    if not client: return

    print(f"Pulling and running '{image}'...")
    try:
        # Parse ports if provided (e.g., ["8080:80"]) -> {80: 8080}
        # Note: docker-py expects {container_port: host_port}
        port_bindings = {}
        if ports:
            for p in ports:
                host, container = p.split(':')
                port_bindings[container] = host

        container = client.containers.run(
            image,
            name=name,
            detach=detach,
            ports=port_bindings
        )
        print(f"Container started: {container.name} ({container.short_id})")
    except docker.errors.ImageNotFound:
        print(f"Error: Image '{image}' not found locally or on registry.")
    except docker.errors.APIError as e:
        print(f"Docker API Error: {e}")

def stop_container(container_id):
    client = get_client()
    if not client: return

    try:
        container = client.containers.get(container_id)
        print(f"Stopping {container.name}...")
        container.stop()
        print("Stopped.")
    except docker.errors.NotFound:
        print(f"Error: Container '{container_id}' not found.")

def remove_container(container_id, force=False):
    client = get_client()
    if not client: return

    try:
        container = client.containers.get(container_id)
        print(f"Removing {container.name}...")
        container.remove(force=force)
        print("Removed.")
    except docker.errors.NotFound:
        print(f"Error: Container '{container_id}' not found.")
    except docker.errors.APIError as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Docker Container Manager")
    subparsers = parser.add_subparsers(dest="command", help="Command to run")

    # List
    list_parser = subparsers.add_parser("list", help="List containers")
    list_parser.add_argument("-a", "--all", action="store_true", help="Show all containers (default shows just running)")

    # Run
    run_parser = subparsers.add_parser("run", help="Run a container")
    run_parser.add_argument("image", help="Image name (e.g., nginx)")
    run_parser.add_argument("--name", help="Container name")
    run_parser.add_argument("-p", "--ports", action="append", help="Port mapping host:container (e.g., 8080:80)")

    # Stop
    stop_parser = subparsers.add_parser("stop", help="Stop a container")
    stop_parser.add_argument("id", help="Container ID or Name")

    # Remove
    rm_parser = subparsers.add_parser("rm", help="Remove a container")
    rm_parser.add_argument("id", help="Container ID or Name")
    rm_parser.add_argument("-f", "--force", action="store_true", help="Force removal (kill if running)")

    args = parser.parse_args()

    if args.command == "list":
        list_containers(args.all)
    elif args.command == "run":
        run_container(args.image, args.name, ports=args.ports)
    elif args.command == "stop":
        stop_container(args.id)
    elif args.command == "rm":
        remove_container(args.id, args.force)
    else:
        parser.print_help()

Usage

# Run an Nginx server on port 8080
python docker_manager.py run nginx --name my-web-server -p 8080:80

# List running containers
python docker_manager.py list

# Stop the container
python docker_manager.py stop my-web-server

# Remove the container
python docker_manager.py rm my-web-server

programming/python/python