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.04
  • ros:humble - ROS2 Humble distribution
  • image: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

  1. Pull the Python image:
    docker pull python:3.10
    
  2. Run an interactive Python container:
    docker run -it --name python_test python:3.10 python
    
  3. Try some Python commands, then exit with exit()

Exercise 2: Build Custom Image

  1. Create a project directory:
    mkdir ~/docker_test && cd ~/docker_test
    
  2. Create a simple Python app:
    echo 'print("Hello from Docker!")' > app.py
    
  3. Create a Dockerfile:
    cat > Dockerfile << 'EOF'
    FROM python:3.10-slim
    WORKDIR /app
    COPY app.py .
    CMD ["python", "app.py"]
    EOF
    
  4. Build and run:
    docker build -t my-python-app .
    docker run my-python-app
    

Exercise 3: Use Docker Compose

  1. Create docker-compose.yml:
    cat > docker-compose.yml << 'EOF'
    version: '3.8'
    services:
      app:
        build: .
        volumes:
          - ./app.py:/app/app.py
    EOF
    
  2. 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) and docker 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.

Reference