Compare commits

..

5 Commits

Author SHA1 Message Date
2b7ffd4dde Added OOP To Basic Python Doc 2026-01-30 01:44:41 +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
RadinPirouz
32615bf615 docker doc : updated setup doc 2026-01-24 00:13:06 +03:30
RadinPirouz
7de5efab3f Docker Lib doc : added structure of doc 2026-01-23 23:28:44 +03:30
10 changed files with 1199 additions and 0 deletions

281
Docs/Basic/05-oop.md Normal file
View File

@@ -0,0 +1,281 @@
# 05 Object-Oriented Programming (OOP) in Python
This document explains the basics of **Object-Oriented Programming (OOP)** in Python using simple examples.
We cover:
* Classes and objects
* Attributes and methods
* Class attributes vs instance attributes
* Inheritance
* Special (magic) methods
---
## 1. Basic Class, Attribute, and Method
### Code
```python
class test_class():
def __init__(self, input):
self.parm = input
print("Class Created")
def result(self):
print(f"param is : {self.parm}")
var = test_class('abbas')
var.result()
```
### Explanation
#### Class
* `test_class` is a **class**, which acts as a blueprint for creating objects.
#### `__init__` method (Constructor)
* `__init__` is a **special method** that runs automatically when a new object is created.
* `input` is a **parameter** passed when creating the object.
* `self.parm = input` creates an **instance attribute** called `parm`.
#### Attribute
* `parm` is an **attribute** (a variable that belongs to the object).
* It stores data specific to each object.
#### Method
* `result()` is a **method** (a function that belongs to the class).
* It uses `self.parm` to access the objects data.
#### Object Creation
```python
var = test_class('abbas')
```
* Creates an object named `var`.
* Calls `__init__` automatically.
#### Method Call
```python
var.result()
```
* Calls the `result` method on the object.
---
## 2. Class Attributes vs Instance Attributes
### Code
```python
class test_class():
test_value = 'abbas'
def __init__(self, input):
self.parm = input
print("Class Created")
def result(self):
print(f"param is : {self.parm}")
var = test_class('abbas')
var2 = test_class('mmd')
var.result()
var.test_value
var2.test_value = 'mmd'
var2.test_value
var.test_value
```
### Explanation
#### Class Attribute
```python
test_value = 'abbas'
```
* This is a **class attribute**.
* It belongs to the class itself.
* Shared by all objects unless overridden.
#### Instance Attribute
```python
self.parm = input
```
* This is an **instance attribute**.
* Each object has its own value.
#### Behavior Analysis
```python
var.test_value
```
* Accesses the class attribute → `'abbas'`
```python
var2.test_value = 'mmd'
```
* Creates a **new instance attribute** for `var2`.
* Does not change the class attribute.
```python
var2.test_value
```
* Returns `'mmd'` (instance attribute)
```python
var.test_value
```
* Still returns `'abbas'` (class attribute)
#### Key Rule
* Instance attributes override class attributes **only for that object**.
---
## 3. Inheritance
### Code
```python
class class_1():
def __init__(self):
print("Class 1 Created")
def hi(self):
print("Hi")
class class_2(class_1):
def __init__(self):
print("Class 2 Created")
self.hi()
b = class_2()
```
### Explanation
#### Parent Class
```python
class class_1():
```
* `class_1` is the **parent (base) class**.
#### Child Class
```python
class class_2(class_1):
```
* `class_2` **inherits** from `class_1`.
* It automatically has access to all public methods of `class_1`.
#### Method Usage
```python
self.hi()
```
* `hi()` is defined in `class_1`.
* Because of inheritance, `class_2` can call it.
#### Output Order
```text
Class 2 Created
Hi
```
#### Important Note
* `class_1.__init__()` is **not called automatically** here.
* To call it, you would need:
```python
super().__init__()
```
---
## 4. Special (Magic) Methods
### Code
```python
class class_1():
def __init__(self):
print("Class 1 Created")
def __len__(self):
return 1
def __str__(self):
return 'print command on class'
def __del__(self):
return 'on del value'
```
### Explanation
Special methods start and end with **double underscores (`__`)** and control built-in behavior.
#### `__init__`
* Runs when an object is created.
#### `__len__`
```python
len(object)
```
* Defines the behavior of `len()` on the object.
* Returns `1` in this example.
#### `__str__`
```python
print(object)
```
* Defines the string representation of the object.
* Used by `print()` and `str()`.
#### `__del__`
* Runs when the object is deleted or garbage-collected.
* Used rarely in modern Python.
* Return value is ignored.
---
## Summary
* **Class**: Blueprint for objects
* **Object**: Instance of a class
* **Attribute**: Data stored in an object
* **Method**: Function inside a class
* **Class Attribute**: Shared across all objects
* **Instance Attribute**: Unique per object
* **Inheritance**: Child class reuses parent class logic
* **Magic Methods**: Customize built-in Python behavior

View File

@@ -0,0 +1,274 @@
# Docker SDK for Python Setup and First Steps
This document introduces the **Docker SDK for Python (`docker` library)** and explains how to connect to the Docker Engine, inspect its status, and authenticate with a registry. The goal is not just to show code, but to clearly explain **what each part does, why it exists, and when you would use it**.
This guide assumes you already understand basic Docker concepts (images, containers, daemon) and are approaching this from a DevOps perspective.
---
## 1. Installing the Docker SDK for Python
Before Python can communicate with Docker, we need to install the official SDK.
```bash
pip install docker
```
### What this does
* Installs the **docker** Python package (often called *docker-py*).
* This package acts as a **client wrapper** around Dockers REST API.
* All interactions ultimately talk to the Docker daemon (`dockerd`) over a socket or TCP connection.
Important note:
* Installing the library alone is not enough.
* Docker **must already be installed and running** on the system.
---
## 2. Connecting to Docker Using Environment Configuration
The simplest and most common way to create a Docker client is by using environment-based configuration.
```python
import docker
client = docker.from_env()
version = client.version()
ping_docker = client.ping()
print(version, ping_docker)
```
### Step-by-step explanation
#### `import docker`
* Imports the Docker SDK.
* This module exposes high-level objects for interacting with Docker resources.
#### `docker.from_env()`
* Automatically creates a `DockerClient` instance.
* Reads Docker connection details from environment variables such as:
* `DOCKER_HOST`
* `DOCKER_TLS_VERIFY`
* `DOCKER_CERT_PATH`
* On Linux, this usually resolves to:
* `unix:///var/run/docker.sock`
This is why `from_env()` is preferred:
* Works across Linux, macOS, Windows, and CI systems
* Requires no hardcoded connection strings
#### `client.version()`
* Calls the Docker Engine `/version` API endpoint.
* Returns detailed metadata such as:
* Docker Engine version
* API version
* Go version
* OS and architecture
This is commonly used for:
* Debugging
* Compatibility checks
* Logging runtime environment details
#### `client.ping()`
* Sends a lightweight request to the Docker daemon.
* Returns `True` if Docker is reachable and responsive.
This is a **health check**, often used in:
* Startup validation
* Monitoring scripts
* CI/CD pipelines
---
## 3. What Does “from_env” Actually Mean?
Using `from_env()` tells the SDK:
> “Figure out how to connect to Docker using the same configuration the Docker CLI uses.”
Behind the scenes, it:
* Detects whether Docker is local or remote
* Determines socket vs TCP
* Applies TLS settings if required
### When should you use it?
* Local development
* Kubernetes nodes
* CI runners
* Most production automation
### When not to use it?
* When you need explicit control over connection parameters
* When connecting to a **remote Docker daemon** with custom networking
---
## 4. Creating a Docker Client Explicitly
Instead of relying on environment detection, you can create a client manually.
```python
import docker
client = docker.DockerClient(base_url='unix://var/run/docker.sock')
version = client.version()
ping_docker = client.ping()
print(version, ping_docker)
```
### Explanation
#### `docker.DockerClient(...)`
* Directly instantiates a Docker client object.
* Requires you to specify how to reach the Docker daemon.
#### `base_url='unix://var/run/docker.sock'`
* Points to the Unix socket used by Docker on Linux systems.
* This socket is owned by root and the `docker` group.
Important implications:
* Your Python process must have permission to access the socket
* Usually means running as root or a user in the `docker` group
### When this approach is useful
* Controlled environments
* Educational examples
* Explicit infrastructure scripts
### Why it is less common
* Not portable across OSes
* Hardcodes infrastructure assumptions
---
## 5. Inspecting Docker and Authenticating
Once connected, the client can retrieve detailed system information and authenticate with registries.
```python
import docker
client = docker.DockerClient(base_url='unix://var/run/docker.sock')
version = client.version()
ping_docker = client.ping()
information = client.info()
client.login(
username='user',
password='password',
registry='registry_link'
)
print(information, ping_docker)
```
### `client.info()`
* Calls the Docker `/info` endpoint.
* Returns a comprehensive snapshot of the Docker host, including:
* Number of containers (running/stopped)
* Number of images
* Storage driver
* Cgroup and kernel features
* Security options (AppArmor, seccomp)
This is extremely valuable for:
* Capacity planning
* Debugging runtime issues
* Auditing host configuration
### `client.login(...)`
* Authenticates Docker with a container registry.
* Stores credentials in Dockers credential store.
Parameters:
* `username`: registry account username
* `password`: registry password or access token
* `registry`: registry URL (e.g. Docker Hub or private registry)
Common use cases:
* Pulling private images
* Pushing images in CI/CD pipelines
* Automating registry interactions
Security note:
* Avoid hardcoding credentials in source code
* Prefer environment variables or secret managers
---
## 6. High-Level vs Low-Level API (Important Concept)
What you are using here is the **high-level Docker client**.
Characteristics:
* Pythonic object model
* Resource-oriented (containers, images, networks)
* Easier to read and maintain
The SDK also exposes a **low-level API**:
* Direct access to Docker REST endpoints
* More control, less abstraction
As a DevOps engineer, you will typically:
* Use high-level API for automation
* Drop to low-level API for advanced edge cases
---
## 7. Summary
In this setup phase, you learned how to:
* Install the Docker SDK for Python
* Connect to Docker using environment-based configuration
* Explicitly define Docker connection settings
* Verify Docker availability
* Retrieve system-level Docker information
* Authenticate with container registries
This foundation is critical before moving on to:
* Managing containers
* Building images
* Working with volumes and networks
---
## References
Official Docker SDK for Python documentation:
* [https://docker-py.readthedocs.io/](https://docker-py.readthedocs.io/)

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

View File

View File

View File

View File