Week 5 - Lab 2: Docker and
Orchestration
Module: Operating Systems 3 (Virtualisation & Cloud Technologies)
Topic: Docker Engine, Networking, Compose, and Portainer
Estimated Time: 90 Minutes
Instructor: KT Nshimba
Lab Overview
In Lab 1, you learnt about System Containers (LXC). Now, we switch to Application Containers (Docker), which are designed to package single processes.
This comprehensive lab covers the entire Docker lifecycle: 1. Fundamentals: Installing Docker and running your first container. 2. Networking: Connecting containers manually. 3. Orchestration: Using Docker Compose to define a full stack (WordPress + MySQL) as code. 4. Management: Installing Portainer to manage it all via a GUI.
Prerequisites: - The Ubuntu Server VM from Week 2 (or a fresh VM). - Internet access.
Part 1: Docker Fundamentals
We will start by interacting with the Docker Engine directly via CLI.
Step 1: Install Docker
- Log in to your Ubuntu VM.
- Install Docker and the Compose plugin:
bash sudo apt update sudo apt install -y docker.io docker-compose-plugin - Add your user to the docker group (optional):
bash sudo usermod -aG docker $USER # Log out and back in required!
Step 2: The "Hello World" of Web Servers
-
Run the Container:
bash docker run -d --name my-web -p 8080:80 nginx-d: Detached mode.-p 8080:80: Forwards port 8080 on VM to port 80 in container.
-
Verify:
- Open your browser to
http://<VM-IP>:8080. - You should see "Welcome to nginx!".
- Open your browser to
-
Clean Up:
bash docker rm -f my-web
Part 2: Docker Networking (The Hard Way)
-
Create a Network:
bash docker network create lab-net -
Launch Containers:
bash docker run -d --name alpine1 --network lab-net alpine sleep 3600 docker run -d --name alpine2 --network lab-net alpine sleep 3600 -
Test DNS Resolution: Docker allows pinging by name.
bash docker exec -it alpine1 ping -c 3 alpine2- Result:
alpine2should resolve to an IP.
- Result:
-
Clean Up:
bash docker rm -f alpine1 alpine2 docker network rm lab-net
Part 3: Orchestration with Docker Compose
Running individual commands is error-prone. Docker Compose defines infrastructure in YAML.
Step 1: Create Workspace
- Run the following commands:
bash mkdir ~/my-wordpress cd ~/my-wordpress nano docker-compose.yaml
Step 2: Define the Stack
Paste the following configuration into the file:
version: '3.8'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data:
Step 3: Deploy
Run the stack in detached mode:
docker compose up -d
Step 4: Verify
- Visit
http://<VM-IP>:8000. You should see the WordPress Setup screen.
Part 4: Management with Portainer
Step 1: Deploy Portainer
Run the following long command to launch the Portainer container:
docker run -d -p 9000:9000 -p 9443:9443 --name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
Step 2: Access the GUI
- Go to
https://<VM-IP>:9443in your browser. - Accept the Self-Signed Certificate Warning.
- Create an admin user and password.
- Select Get Started.
Step 3: Explore
- Click Containers to see your WordPress stack running visually.
- Try creating a new container using the "Add Container" button!
Lab Checkpoint
Practical Skills Checklist
- Installed Docker Engine
- Deployed a container via CLI
- Created a custom network
- Wrote
docker-compose.yaml - Deployed Portainer
Reflection
- Networking: Why is
docker composeeasier than manual networking? - Persistence: Where is the MySQL data stored? (Hint:
db_datavolume).