Compare commits

..

3 Commits

Author SHA1 Message Date
42f8df2589 Docker SDK: Added Network doc ( not complated ) 2026-02-04 01:31:31 +03:30
RadinPirouz
90f5451ff8 Docker Lib : Added Container Doc 2026-01-25 15:34:35 +03:30
RadinPirouz
2e229ceadd Docker Lib: Added Images Doc 2026-01-25 15:25:49 +03:30
5 changed files with 712 additions and 0 deletions

View File

@@ -0,0 +1,360 @@
# Docker SDK for Python Working with Images
This document explains how to **manage Docker images** using the Docker SDK for Python. Instead of treating the SDK as a set of function calls, well approach images the same way Docker itself does: as immutable artifacts that are pulled, built, tagged, pushed, inspected, and eventually cleaned up.
All examples assume:
* Docker is installed and running
* The Python process has access to the Docker socket
---
## 1. Creating the Docker Client
```python
import docker
client = docker.DockerClient(base_url='unix://var/run/docker.sock')
ping_docker = client.ping()
```
### Explanation
* `DockerClient` establishes a connection to the Docker daemon.
* `ping()` verifies that Docker is reachable before doing any real work.
This is a common pattern in automation:
* Fail fast if Docker is unavailable
* Avoid partial execution later in the script
---
## 2. Pulling Images from a Registry
```python
def pull_image(name_image, tag_image):
image = client.images.pull(name_image, tag=tag_image)
print(image)
```
### What this does
* Downloads an image from a registry (Docker Hub or private registry).
* If the image already exists locally, Docker may reuse layers.
Parameters:
* `name_image`: repository name (e.g. `alpine`, `nginx`, `myrepo/app`)
* `tag_image`: specific version or variant (e.g. `3.20`, `latest`)
Returned value:
* An `Image` object representing the pulled image
Why this matters:
* Pulling explicitly avoids relying on implicit image downloads
* Makes automation predictable and repeatable
---
## 3. Building Images from a Dockerfile
### Basic build
```python
def build_image():
image, logs = client.images.build(
path=".",
tag="myapp:1.0"
)
for log in logs:
if "stream" in log:
print(log["stream"].strip())
```
### Explanation
* `path="."` tells Docker to use the current directory as the build context.
* Docker automatically looks for a file named `Dockerfile`.
* `tag="myapp:1.0"` assigns a name and version to the resulting image.
The build process returns:
* `image`: the final built image object
* `logs`: a stream of build output messages
Printing build logs is important because:
* Docker build failures are only visible in logs
* CI pipelines rely on this output for debugging
---
## 4. Advanced Build with Custom Dockerfile and Build Arguments
```python
def build_image_2():
image, logs = client.images.build(
path=".",
dockerfile="Dockerfile.prod",
tag="myapp:prod",
buildargs={
"APP_ENV": "production",
"VERSION": "1.0.0"
}
)
```
### Explanation
This version adds more control:
* `dockerfile="Dockerfile.prod"`
* Allows multiple Dockerfiles per project
* Common for dev vs prod builds
* `buildargs`
* Passed to `ARG` instructions inside the Dockerfile
* Enables parameterized builds without editing the Dockerfile
Typical DevOps use cases:
* Environment-specific builds
* Injecting version numbers
* Feature flags during build time
---
## 5. Tagging Images
```python
def tag_image():
image = client.images.get("myapp:1.0")
image.tag("myrepo/myapp", tag="latest")
```
### Explanation
* Docker images are immutable, but tags are not.
* This creates an additional reference to the same image ID.
Why tagging is important:
* One image can have multiple tags
* Tags represent lifecycle stages (`1.0`, `prod`, `latest`)
This is how promotion pipelines work:
* Build once
* Tag many times
* Push selectively
---
## 6. Removing Images
```python
def remove_image():
client.images.remove("myapp:1.0", force=True)
```
### Explanation
* Removes the image reference from the local Docker host.
* `force=True` removes the image even if it is in use by stopped containers.
Use with care:
* Running containers still prevent deletion
* Forced removal is destructive
---
## 7. Pushing Images to a Registry
```python
def push_image():
client.images.push(
repository="myrepo/myapp",
tag="latest"
)
```
### Explanation
* Uploads the image layers to a registry.
* Requires prior authentication (`client.login`).
Important notes:
* Only new or changed layers are pushed
* Tags determine what remote users pull
This step is usually automated in:
* CI/CD pipelines
* Release workflows
---
## 8. Cleaning Up Unused Images
```python
def prune_images():
result = client.images.prune()
print(result)
```
### Explanation
* Removes dangling images (untagged and unused).
* Helps reclaim disk space on build servers.
The result includes:
* Number of images removed
* Amount of disk space freed
This is essential for:
* CI runners
* Long-lived build machines
---
## 9. Inspecting Image Metadata
```python
def inspect_image():
alpine_image = client.images.get("alpine:3.20")
print(alpine_image.attrs)
print(alpine_image.attrs["Id"])
print(alpine_image.attrs["Size"])
print(alpine_image.attrs["Config"]["Env"])
print(alpine_image.attrs["Config"]["Cmd"])
```
### Explanation
* `attrs` exposes the raw Docker image inspection data.
* This is equivalent to `docker image inspect`.
Useful fields:
* `Id`: content-addressable image hash
* `Size`: image size in bytes
* `Config.Env`: environment variables baked into the image
* `Config.Cmd`: default command
This information is often used for:
* Debugging unexpected behavior
* Auditing images
* Validating build output
---
## 10. Listing Local Images
```python
def image_list():
images = client.images.list()
for item in images:
print(item.id, item.tags)
```
### Explanation
* Lists all images stored locally.
* Each image may have multiple tags or none.
This mirrors:
* `docker images`
---
## 11. Ensuring an Image Exists
```python
def ensure_image(name):
try:
client.images.get(name)
print(f"{name} exists")
except docker.errors.ImageNotFound:
print(f"Pulling {name}")
client.images.pull(name)
```
### Explanation
This is a very common DevOps pattern:
* Check if the image exists locally
* Pull it only if necessary
Benefits:
* Avoids unnecessary network calls
* Makes scripts idempotent
---
## 12. Important Exceptions to Know
When working with images, you must handle failures explicitly.
### `docker.errors.ImageNotFound`
* Raised when an image does not exist locally
* Common when calling `get()`
### `docker.errors.BuildError`
* Raised when an image build fails
* Usually due to Dockerfile errors or missing files
### `docker.errors.APIError`
* Raised for general Docker API failures
* Includes permission issues, daemon errors, and network problems
Catching these exceptions is critical for:
* Reliable automation
* Meaningful error reporting
* CI/CD stability
---
## 13. Summary
In this section, you learned how to:
* Pull images from registries
* Build images using Dockerfiles
* Use build arguments and multiple Dockerfiles
* Tag and push images
* Inspect and list images
* Clean up unused images
* Handle common Docker image errors
This image workflow is the backbone of:
* CI pipelines
* Release automation
* Platform engineering systems
---
## References
Official Docker SDK for Python documentation:
* [https://docker-py.readthedocs.io/](https://docker-py.readthedocs.io/)

View File

@@ -0,0 +1,284 @@
# Docker SDK for Python Working with Containers
This document explains how to **manage Docker containers** using the Docker SDK for Python. Containers are the runtime unit of Docker, so this section focuses on lifecycle management: listing, creating, running, starting, stopping, restarting, pausing, and inspecting logs.
The goal is to understand **how container state changes**, how the Python SDK maps to Docker CLI behavior, and how these operations are typically used in real DevOps automation.
---
## 1. Creating the Docker Client
```python
import docker
import time
client = docker.DockerClient(base_url='unix://var/run/docker.sock')
ping_docker = client.ping()
```
### Explanation
* Establishes a connection to the Docker daemon via the Unix socket.
* `ping()` is used as a sanity check before executing container operations.
In production-grade scripts, this check prevents:
* Silent failures
* Partial execution when Docker is down
---
## 2. Listing Running Containers
```python
def get_containers_list():
containers = client.containers.list()
for c in containers:
print(c.id, c.name, c.status)
```
### Explanation
* `containers.list()` returns **only running containers** by default.
* Each returned object represents a live container instance.
Common attributes:
* `id`: unique container identifier
* `name`: human-readable container name
* `status`: runtime state (running)
This is equivalent to:
* `docker ps`
---
## 3. Listing All Containers (Including Stopped)
```python
def get_all_containers_list():
containers = client.containers.list(all=True)
for c in containers:
print(c.id, c.name, c.status)
```
### Explanation
* `all=True` includes stopped, exited, and created containers.
* Useful for cleanup, auditing, and lifecycle reconciliation.
Equivalent CLI command:
* `docker ps -a`
---
## 4. Creating a Container (Without Starting It)
```python
def create_container():
container = client.containers.create(
image="nginx:latest",
name="my_nginx",
ports={"80/tcp": 8080},
detach=True
)
```
### Explanation
This creates a container in the **created** state.
Key parameters:
* `image`: base image for the container
* `name`: explicit container name
* `ports`: port mapping (container → host)
* `detach=True`: container runs in background when started
Important distinction:
* `create()` does **not** start the container
* This mirrors `docker create`
Use cases:
* Deferred startup
* Multi-step initialization
---
## 5. Running a Container (Create + Start)
```python
def run_container():
container = client.containers.run(
"nginx:latest",
name="nginx_run",
ports={"80/tcp": 8081},
detach=True
)
```
### Explanation
* `run()` is a convenience method.
* Internally performs `create()` followed by `start()`.
Equivalent CLI command:
* `docker run -d -p 8081:80 nginx:latest`
This is the most common approach for:
* Short-lived workloads
* Simple services
---
## 6. Managing Container Lifecycle
```python
def start_container():
container = client.containers.get("my_nginx")
container.start()
time.sleep(1000)
container.restart()
time.sleep(1000)
container.pause()
container.unpause()
time.sleep(1000)
container.stop(timeout=10)
```
### Explanation
This function demonstrates multiple lifecycle transitions.
#### `containers.get(name)`
* Retrieves an existing container by name or ID.
* Raises an exception if the container does not exist.
#### `start()`
* Transitions container from `created` or `stopped``running`.
#### `restart()`
* Stops and immediately starts the container.
* Often used after configuration changes.
#### `pause()` / `unpause()`
* Freezes container processes using cgroups.
* Network and filesystem state remain intact.
#### `stop(timeout=10)`
* Sends SIGTERM, then SIGKILL after timeout.
* Allows graceful shutdown.
The `sleep()` calls simulate:
* Long-running services
* Observing container behavior between states
---
## 7. Reading Container Logs
```python
def log_container():
container = client.containers.get("my_nginx")
logs = container.logs(tail=20)
print(logs.decode())
```
### Explanation
* Retrieves logs from the containers stdout/stderr.
* `tail=20` limits output to the last 20 lines.
Important details:
* Logs are returned as bytes
* Decoding is required for readable output
Equivalent CLI command:
* `docker logs --tail 20 my_nginx`
This is critical for:
* Debugging runtime issues
* Health checks
* Observability tooling
---
## 8. Conditional Execution Based on Docker Availability
```python
if ping_docker:
get_containers_list()
```
### Explanation
* Ensures container operations only run if Docker is reachable.
* Prevents unhandled API errors.
This pattern is common in:
* Entry-point scripts
* Health probes
* Automation jobs
---
## 9. Container States (Conceptual Model)
Understanding container states is essential:
* `created`: container exists but is not running
* `running`: container processes are active
* `paused`: execution is suspended
* `exited`: container stopped normally
* `dead`: container failed unexpectedly
Every method in this document transitions the container between these states.
---
## 10. Summary
In this section, you learned how to:
* List running and stopped containers
* Create containers separately from starting them
* Run containers in a single step
* Control container lifecycle states
* Read container logs
* Safely execute operations based on Docker availability
This container-level control is the foundation for:
* Service orchestration
* CI/CD job execution
* Debugging and recovery automation
---
## References
Official Docker SDK for Python documentation:
* [https://docker-py.readthedocs.io/](https://docker-py.readthedocs.io/)

View File

@@ -0,0 +1,68 @@
```python
import docker
import time
docker_client = docker.DockerClient(base_url="unix://var/run/docker.sock")
docker_client.ping()
print("All Networks:\n")
all_networks = docker_client.networks.list()
for network in all_networks:
print(network.name, network.id)
print("\nNetworks Named host and bridge:\n")
system_networks = docker_client.networks.list(names=["host", "bridge"])
for network in system_networks:
print(network.name, network.id)
print("\nNetwork With Custom ID:\n")
custom_id_networks = docker_client.networks.list(
ids=["29c9e588bb8e0db6445f2a2278a1c2f42e39dc163c0a404f744dc4139fe47d21"]
)
for network in custom_id_networks:
print(network.name, network.id)
print("\nNetwork With Custom ID (Including Attributes):\n")
custom_id_networks = docker_client.networks.list(
ids=["29c9e588bb8e0db6445f2a2278a1c2f42e39dc163c0a404f744dc4139fe47d21"]
)
for network in custom_id_networks:
print(network.name, network.id, network.attrs)
print("\nNetwork With Custom Filter:\n")
filtered_networks = docker_client.networks.list(
names=["gitea_default"],
filters={"driver": "bridge"}
)
for network in filtered_networks:
if network.attrs["Driver"]:
print(network.name, network.id)
print("\nNetwork With Custom Filter (Greedy):\n")
filtered_networks = docker_client.networks.list(
names=["gitea_default"],
filters={"driver": "bridge"},
greedy=True
)
for network in filtered_networks:
if network.attrs["Driver"]:
print(network.name, network.id, network.attrs)
```
```python
```