Lab 1: Docker Fundamentals
Introduction
In this lab, you will learn the basics of Docker including how to pull images, run containers, understand the difference between docker run and docker exec, and use Docker Compose with Dockerfile and docker-compose.yml.
Prerequisites
- Docker installed on your system
- Basic Linux command line knowledge
Part 1: Installing Docker
On Ubuntu/Debian
# Update package index
sudo apt-get update
# Install prerequisites
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# Add your user to docker group (to run without sudo)
sudo usermod -aG docker $USER
Verify Installation
docker --version
docker run hello-world
Part 2: Pulling Docker Images
Docker images are templates used to create containers. You can pull images from Docker Hub.
Pull an Image
# Pull the latest Ubuntu image
docker pull ubuntu:22.04
# Pull a specific ROS2 image
docker pull ros:humble
# List downloaded images
docker images
Understanding Image Tags
ubuntu:22.04- Ubuntu version 22.04ros:humble- ROS2 Humble distributionimage:latest- Latest version (default if no tag specified)
Part 3: Running Docker Containers
Basic Run Command
# Run a container interactively
docker run -it ubuntu:22.04 /bin/bash
# Run a container in the background (detached)
docker run -d --name my_container ubuntu:22.04 sleep infinity
# Run with port mapping
docker run -d -p 8080:80 nginx
# Run with volume mounting
docker run -it -v /host/path:/container/path ubuntu:22.04 /bin/bash
Common Run Options
| Option | Description |
|---|---|
-it | Interactive mode with terminal |
-d | Detached mode (background) |
--name | Assign a name to container |
-p | Port mapping (host:container) |
-v | Volume mounting (host:container) |
--rm | Remove container when it exits |
-e | Set environment variables |
List Running Containers
# List running containers
docker ps
# List all containers (including stopped)
docker ps -a
Part 4: Docker Run vs Docker Exec
Understanding the difference between docker run and docker exec is crucial.
Docker Run
docker run creates a NEW container from an image and starts it.
# Creates a new container each time
docker run -it ubuntu:22.04 /bin/bash
- Creates a new container instance
- Each run creates a separate container
- Changes are isolated to that container
Docker Exec
docker exec executes a command in an EXISTING running container.
# First, start a container in the background
docker run -d --name my_ubuntu ubuntu:22.04 sleep infinity
# Then exec into the running container
docker exec -it my_ubuntu /bin/bash
- Connects to an already running container
- Multiple exec sessions share the same container
- Changes persist within that container session
Comparison Table
| Aspect | docker run | docker exec |
|---|---|---|
| Container | Creates NEW | Uses EXISTING |
| State | Fresh start | Continues state |
| Use case | Start new instance | Connect to running container |
| Syntax | docker run [options] image | docker exec [options] container command |
Practical Example
# Start a container
docker run -d --name webserver nginx
# Check if it's running
docker ps
# Execute commands inside the running container
docker exec webserver cat /etc/nginx/nginx.conf
docker exec -it webserver /bin/bash
# Stop the container
docker stop webserver
# Remove the container
docker rm webserver
Part 5: Docker Compose
Docker Compose allows you to define and run multi-container applications using a YAML file.
Install Docker Compose
# Install latest docker-compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Verify installation
docker-compose --version
Understanding Dockerfile
A Dockerfile defines how to build a Docker image.
# Dockerfile example
FROM ubuntu:22.04
# Set environment variables
ENV DEBIAN_FRONTEND=noninteractive
# Install packages
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /app
# Copy files from host to container
COPY . /app
# Run command when container starts
CMD ["python3", "app.py"]
Dockerfile Instructions
| Instruction | Description |
|---|---|
FROM | Base image to build from |
RUN | Execute commands during build |
COPY | Copy files from host to image |
WORKDIR | Set working directory |
ENV | Set environment variables |
EXPOSE | Declare ports |
CMD | Default command when container runs |
ENTRYPOINT | Configure container as executable |
Understanding docker-compose.yml
A docker-compose.yml file defines services, networks, and volumes.
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- ./app:/app
environment:
- DEBUG=true
depends_on:
- db
db:
image: postgres:13
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=secret
volumes:
db_data:
Docker Compose Commands
# Build images
docker-compose build
# Start services
docker-compose up
# Start in detached mode
docker-compose up -d
# Stop services
docker-compose down
# View logs
docker-compose logs
# Execute command in a service
docker-compose exec web /bin/bash
# Start specific profile
docker-compose --profile myprofile up -d
Part 6: Practical Exercise
Exercise 1: Create a Simple Container
- Pull the Python image:
docker pull python:3.10 - Run an interactive Python container:
docker run -it --name python_test python:3.10 python - Try some Python commands, then exit with
exit()
Exercise 2: Build Custom Image
- Create a project directory:
mkdir ~/docker_test && cd ~/docker_test - Create a simple Python app:
echo 'print("Hello from Docker!")' > app.py - Create a Dockerfile:
cat > Dockerfile << 'EOF' FROM python:3.10-slim WORKDIR /app COPY app.py . CMD ["python", "app.py"] EOF - Build and run:
docker build -t my-python-app . docker run my-python-app
Exercise 3: Use Docker Compose
- Create docker-compose.yml:
cat > docker-compose.yml << 'EOF' version: '3.8' services: app: build: . volumes: - ./app.py:/app/app.py EOF - Run with Docker Compose:
docker-compose up
Summary
In this lab, you learned:
- How to install Docker
- How to pull Docker images from Docker Hub
- How to run Docker containers with various options
- The difference between
docker run(creates new container) anddocker exec(connects to existing container) - How to create Dockerfiles to build custom images
- How to use docker-compose.yml to define multi-container applications
- Essential Docker Compose commands
Next Steps
Proceed to Lab 2 to learn how to run ROS2 in Docker containers on Mini Pupper.