Docker Hands-On Lab #
This lab provides practical exercises to reinforce the Docker concepts covered in the lecture. These hands-on activities will help you build confidence in using Docker for development and deployment scenarios.
Prerequisites #
- Docker Engine installed on your system
- Basic command line familiarity
- Text editor of your choice
Exercise 1: Getting Started with Docker #
1.1 Verify Docker Installation #
Ensure Docker is properly installed on your system:
docker --version
docker info
1.2 Running Your First Container #
Let’s run an interactive container using the official Ubuntu image:
docker run -it --rm ubuntu bash
Inside the container, try some commands:
ls
cat /etc/os-release
apt update
Type exit
to leave the container.
Exercise 2: Building Custom Images #
2.1 Create a Simple Python Web Application #
Create a directory for your project:
mkdir docker-lab
cd docker-lab
Create a file named app.py
:
from http.server import BaseHTTPRequestHandler, HTTPServer
import socket
import json
class WebServer(BaseHTTPRequestHandler):
def _set_response(self, content_type="text/plain"):
self.send_response(200)
self.send_header('Content-type', content_type)
self.end_headers()
def do_GET(self):
if self.path == '/':
# Serve the main page as plain text
self._set_response("text/plain")
hostname = socket.gethostname()
response = f"""
Hello from Docker!
This page is being served from a Docker container.
Container hostname: {hostname}
"""
self.wfile.write(response.encode('utf-8'))
elif self.path == '/api/info':
# Serve JSON API response
self._set_response("application/json")
data = {
"hostname": socket.gethostname(),
"python_version": socket.python_version(),
"container": True
}
self.wfile.write(json.dumps(data).encode('utf-8'))
else:
self._set_response()
self.wfile.write(b"404 - Not Found")
def run(server_class=HTTPServer, handler_class=WebServer, port=3000):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print(f"Starting server on port {port}...")
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
print("Server stopped.")
if __name__ == '__main__':
run()
2.2 Create a Dockerfile #
Create a file named Dockerfile
:
# Use Python as the base image
FROM python:3.9-slim
# Set working directory
WORKDIR /app
# Copy application file
COPY app.py .
# Expose the port the app runs on
EXPOSE 3000
# Command to run the application
CMD ["python", "app.py"]
2.3 Build and Run Your Image #
Build your Docker image:
docker build -t my-python-app .
Run the container:
docker run -d -p 3000:3000 --name web-app my-python-app
Test your application:
# Using curl for plain text response
curl http://localhost:3000
# Using curl for JSON API
curl http://localhost:3000/api/info
2.4 Explore Your Container #
Check the running containers:
docker ps
View container logs:
docker logs web-app
Execute commands in the running container:
docker exec -it web-app bash
Stop and remove your container:
docker stop web-app
docker rm web-app
Exercise 3: Advanced Docker Concepts #
3.1 Docker Networks #
Create a custom bridge network:
docker network create mynetwork
Run containers on the network:
docker run -d --name container1 --network mynetwork alpine sleep infinity
docker run -d --name container2 --network mynetwork alpine sleep infinity
Test container communication:
docker exec container1 ping -c 3 container2
List networks and inspect:
docker network ls
docker network inspect mynetwork
Clean up:
docker stop container1 container2
docker rm container1 container2
docker network rm mynetwork
3.2 Docker Volumes #
Create a named volume:
docker volume create mydata
Run a container with the volume:
docker run -d --name vol-test -v mydata:/data alpine sh -c "while true; do date >> /data/dates.txt; sleep 10; done"
Inspect the volume data:
docker exec vol-test cat /data/dates.txt
Use a different container to access the same volume:
docker run --rm -v mydata:/data alpine cat /data/dates.txt
Clean up:
docker stop vol-test
docker rm vol-test
docker volume rm mydata
Conclusion #
This lab has covered:
- Running containers with Docker
- Building custom Docker images
- Using Docker networks and volumes
Continue experimenting with Docker and explore other advanced topics like multi-stage builds, container orchestration with Kubernetes, and CI/CD integration.
Challenge Exercise #
Python API with Persistent Data #
Create a multi-container application with these components:
- A Python Flask API server that stores data in a persistent volume
- Connect containers using a custom Docker network
- Configure the containers to start automatically when Docker starts
Here’s a starter for your Flask API (app.py
):
from flask import Flask, request, jsonify
import os
import json
import socket
app = Flask(__name__)
DATA_FILE = '/data/items.json'
# Create data directory if it doesn't exist
os.makedirs(os.path.dirname(DATA_FILE), exist_ok=True)
# Initialize with empty data if file doesn't exist
if not os.path.exists(DATA_FILE):
with open(DATA_FILE, 'w') as f:
json.dump([], f)
@app.route('/items', methods=['GET'])
def get_items():
with open(DATA_FILE, 'r') as f:
return jsonify(json.load(f))
@app.route('/items', methods=['POST'])
def add_item():
new_item = request.json
with open(DATA_FILE, 'r') as f:
items = json.load(f)
items.append(new_item)
with open(DATA_FILE, 'w') as f:
json.dump(items, f)
return jsonify({"status": "success", "message": "Item added"})
@app.route('/info', methods=['GET'])
def get_info():
return jsonify({
"hostname": socket.gethostname(),
"items_count": len(json.load(open(DATA_FILE, 'r'))),
"container": True
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)