Day 3 - Part 2 - Introduction to Containerization, Docker and Kubernetes#
Containerization#
A lightweight form of virtualization that packages an application and its dependencies into a single container. This ensures consistent behavior across environments.
Key Concepts#
Containers vs Virtual Machines#
Feature |
Virtual Machines (VMs) |
Containers |
|---|---|---|
OS |
Each VM runs its own OS |
Containers share the host OS kernel |
Size |
VMs are large and resource-intensive |
Containers are lightweight and fast |
Isolation |
Each VM is isolated from others |
Containers run in isolated environments |
Reproducibility |
VMs can be inconsistent across environments |
Containers are consistent across environments |
Portability |
VMs are less portable |
Containers can run anywhere |
Performance |
VMs have overhead due to full OS |
Containers have less overhead |
Deployment |
VMs require more resources for deployment |
Containers are easier to deploy |
Speed |
VMs take longer to start up |
Containers start almost instantly |
Resource Usage |
VMs consume more resources |
Containers use fewer resources |
Management |
VMs require complex management |
Containers are easier to manage |
Networking |
VMs have complex networking |
Containers have simpler networking |
Scalability |
VMs are harder to scale |
Containers are easier to scale |
Docker#
A platform to develop, ship and run applications in containers.
Key Concepts#
Docker Engine: Core service that creates and runs containers.
Docker CLI: Command-line tool to interact with Docker.
Dockerfile: Script defining how to build a Docker image.
Docker Image: Immutable snapshot created from a Dockerfile.
Docker Container: Runtime instance of an image.
Docker Hub: Public registry for sharing images.
Docker in Action#
Run your first Docker container using the Docker CLI:
docker run hello-world
This command pulls the
hello-worldimage from Docker Hub and runs it in a container. If you see a “Hello from Docker!” message, Docker is installed correctly.Create a Docker image. To do that, first create a file named
app.pywith the following content:print("Hello, Docker!")
Create a Dockerfile in the same directory with the following content:
FROM python:3.9-slim COPY app.py /app.py CMD ["python", "/app.py"]
Build the Docker image:
docker build -t hello-docker .
Run the Docker image:
docker run hello-docker
You can share a volume between the host and the container. To do that, run the following command:
docker run -v /path/on/host:/path/in/container hello-docker
You can also run a container in the background using the
-dflag:docker run -d hello-docker
To see the running containers, use the following command:
docker ps
To stop a running container, use the following command:
docker stop <container_id>
To remove a container, use the following command:
docker rm <container_id>
To remove an image, use the following command:
docker rmi <image_id>
To see the images, use the following command:
docker images
To see the logs of a container, use the following command:
docker logs <container_id>
Kubernetes#
A container orchestration platform that automates the deployment, scaling and management of containerized applications.
Scaling: Automatically scale up/down application instances based on demand.
Self-Healing: Automatically restarts containers that fail, replaces containers, and kills containers that don’t respond to health checks.
Service Discovery and Load Balancing: Exposes services and distributes traffic.
Automated Rollouts and Rollbacks: Gradually rolls out changes and reverts if something goes wrong.
Secret and Configuration Management: Manage sensitive data and application configuration separately from code.
Resource Efficiency: Efficiently packs containers onto nodes based on resource requirements and availability.
Key Concepts#
Pod: The smallest deployable unit in K8s; wraps one or more containers.
Node: A worker machine in the cluster (virtual or physical).
Cluster: A group of nodes managed by Kubernetes.
Deployment: Defines the desired state for pods and handles updates.
Service: An abstraction to expose pods to the network.
Ingress: Manages external access to services, usually via HTTP.
ConfigMap: Stores non-sensitive configuration data.
Secret: Stores sensitive data like passwords or keys.
Namespace: Provides a scope for names, allowing segregation of cluster resources.
Practical Exercise#
Create a simple app as follows:
app.pyfrom flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello from Docker!" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
Create a requirements file:
requirements.txtflaskCreate a Dockerfile:
DockerfileFROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY app.py . CMD ["python", "app.py"]
Build the Docker image:
docker build -t flask-app-image .
[!WARNING] If you are not using Linux, you may need to use
docker buildxto build the image. You can do this by running the following command:docker buildx build --platform linux/amd64 -t flask-app-image .
Run the Docker container:
docker run -d -p 8000:5000 flask-app-image
Access the app in your browser at
http://localhost:8000.Push the Docker image to a registry (e.g., Docker Hub):
docker tag flask-app-image albughdadim/flask-app-image docker push albughdadim/flask-app-image
Create a Kubernetes deployment file:
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-app-deployment
namespace: flask-app-ns
spec:
replicas: 2
selector:
matchLabels:
app: flask-app-deployment
template:
metadata:
labels:
app: flask-app-deployment
spec:
containers:
- name: flask-container
image: albughdadim/flask-app-image:latest
ports:
- containerPort: 5000
Create a Kubernetes service file:
service.yaml
apiVersion: v1
kind: Service
metadata:
name: flask-service
namespace: flask-app-ns
spec:
type: ClusterIP
selector:
app: flask-app-deployment
ports:
- protocol: TCP
port: 80
targetPort: 5000
Create an ingress file:
ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: flask-ingress
namespace: flask-app-ns
annotations:
cert-manager.io/cluster-issuer: ecmwf-meditwin-issuer
nginx.ingress.kubernetes.io/backend-protocol: HTTP
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "500m"
external-dns.alpha.kubernetes.io/hostname: moflask.internal.meditwin-project.eu
spec:
rules:
- host: moflask.internal.meditwin-project.eu
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: flask-service
port:
number: 80
tls:
- hosts:
- moflask.internal.meditwin-project.eu
secretName: flask-tls
Download the
kubeconfigfileSet the
KUBECONFIGenvironment variable to point to your kubeconfig file:export KUBECONFIG="/path/to/your/kubeconfig"
Check contexts to ensure you are connected to the correct cluster:
kubectl config get-contexts
If needed, switch to the desired context:
kubectl config use-context ecmwf-meditwin
Create a namespace for your application:
kubectl create namespace flask-app-ns
Apply the deployment, service and ingress files:
kubectl apply -f deployment.yaml kubectl apply -f service.yaml kubectl apply -f ingress.yaml