---
# System prepended metadata

title: 10. Docker Fundamentals

---

# 10. Docker Fundamentals

[toc]


### Topics

:::info
- [x] Introduction
- [x] VMs vs Containers
- [x] Installation
- [x] Docker Commands
- [x] Docker Hub
- [x] Dockerfile
- [x] Docker push (to docker hub)
- [x] Docker Compose
:::

### Introduction

#### Container Runtime
:::warning
- Docker
- rkt
- containerd
- podman
- cri-o
:::

#### Container Orchestration Engine
:::warning
**On-prem**
- Kubernetes / k8s
- Docker Swarm
- Apache Mesosphere
- Hashicorp Nomad
- Red hat Openshift

**Cloud Based**
- AWS ECS
- AWS EKS
- Azure AKS
- Google GKE
:::

### Understanding types of Virtualization

#### Hypervisor based Virtualization


![](https://hackmd.io/_uploads/HJ66wzXPn.png)

#### Container based Virtualization

![](https://hackmd.io/_uploads/rJYQOMmP3.png)

#### Containers vs Virtual Machines

![](https://hackmd.io/_uploads/BJDhuGmDn.png)

![](https://i.imgur.com/sEsQlS6.png)

*Source: https://www.atlassian.com/microservices/cloud-computing/containers-vs-vms*

#### Containers on Virtual Machines

![](https://hackmd.io/_uploads/HkrDKMXv2.png)

#### Containers on Physical Machines vs Containers on Virtual Machines

![](https://hackmd.io/_uploads/SkHItMQvn.png)


#### A comparison between Containers and Virtual Machines
:::warning
- **Virtual Machines**
    - hardware level virtualization
    - Need Hypervisor to create VMs
    - Multiple OSs can be hosted on a single Physical box such as Linux, Windows, MacOS etc.
    - boot/provision time in minutes
    - e.g. ESXi, HyperV, KVM etc.
- **Containers**
    - OS / Kernel level virtualization
    - Need Container Runtimes *(such as Docker)* to create Containers
    - Guest OS is tied up with Host OS libraries
    - boot/provision time in milliseconds
    - e.g. Docker, rkt, Podman, Containerd etc.
:::


### Docker Architecture

![](https://i.imgur.com/UxA84AH.png)


:::warning
- Docker host
- Docker Daemon
- Docker Client (e.g.--> Docker CLI or Docker API)
- Docker image (e.g --> Amazon AMI)
- Docker container (e.g. --> Amazon EC2 instances)
- Docker Registry
    - Public  --> [DockerHub](https://hub.docker.com/)
    - Private --> [Amazon ECR](https://aws.amazon.com/ecr/)
:::

### Installation and Configuration
#### Docker installation on Ubuntu 20.04
````yaml=
sudo apt install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install docker.io
docker --version

Run Docker command without Sudo (Optional): 
sudo usermod -aG docker $(whoami)

Validate docker installation:
docker run hello-world
````

#### Docker installation on CentOS 7.8.2
````yaml=
#!/bin/sh

## Update repo
sudo yum check-update

## Install pre-requisites
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

## Add docker repo
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

## Install Docker
sudo yum install docker

## Validate
sudo docker --version


Run Docker command without Sudo (Optional): 
sudo usermod -aG docker $(whoami)

Validate docker installation:
docker run hello-world
````

#### Installation via get.docker.com (Works on all major Linux distributions)
````yaml=
## Download the script from get.docker.com
curl -fsSL https://get.docker.com -o install-docker.sh

## Make the script executable
chmod +x install-docker.sh

## Run the script
sudo sh install-docker.sh
````

### Working with Docker Commands

#### Fundamental Commands
:::warning
Basic commands:
````
docker --version
docker info
````

Docker image operations:
````
list all local images:
docker image ls (old command --> docker images)

list images on dockerhub for a keyword:
docker search <keyword>

pull image from dockerhub:
docker pull <image-name:tag>

push local image to dockerhub:
docker push <image-name:tag>

rename a local image:
docker tag <current-image-name:tag> <new-image-name:tag>
````
:arrow_right: Please note that image-tag always defaults to *"latest"* unless specified otherwise.

Create Docker containers using docker run:
````
Syntax:
docker run -itd <image-name> <CMD>
Example:
docker run -itd ubuntu /bin/bash

docker run -it --> Root mode
docker run -itd --> detached
````

list all containers:
````
docker ps --> to see running containers
or
docker ps -a --> to see all containers
````

Port mapping / Forwarding:
````
Syntax:
docker run -p hostport:containerport imagename

Example:
docker run -p 8001:80 nginx
````
Container Operations:
````
docker attach <container_name>
docker start <container_name>
docker stop <container_name>

Execute commands on a container from host:
Syntax:
docker exec -it <container-id> <command-to-run-inside-container>

Example:
docker exec -it web1 which tree
````
Docker run [Additional Flags]
````
--name <user-defined-container-name>
--rm --> automatically remove container once stopped
-p port mapping
-v volume mapping
````

Cleanup:
````
docker rm <container-id>
docker container rm <container-id>
docker rmi <image-name>
docker image rm <image-name>
docker system prune --all
````

Create an image using Docker commit:
````
docker commit <container-id> <new-image-name>
````


Create an image using Dockerfile:
````
docker build -t sk-nginx -f /tmp/demofile .

Where:
-t <image-name> --> specify the new image name
-f </path/to/dockerfile> --> specify Dockerfile location, if not current directory.
````

:::

#### Docker full command list
````yaml
Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.
````

#### Docker Management Commands
````sh
Management Commands:
  builder     Manage builds
  buildx*     Docker Buildx (Docker Inc., v0.10.5)
  compose*    Docker Compose (Docker Inc., v2.18.1)
  container   Manage containers
  context     Manage contexts
  image       Manage images
  manifest    Manage Docker image manifests and manifest lists
  network     Manage networks
  plugin      Manage plugins
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes    

Swarm Commands:
  swarm       Manage Swarm
````

### Working with Docker Images

#### Image creation using Docker commit

##### Create a new container from an existing image
:::warning
docker run -it --name container-name ubuntu /bin/bash
:::

##### Make customizations inside the container
:::warning
##### install package 'tree'
    apt-get update
    apt-get install tree
##### creat a sample file in /tmp
    cd /tmp
    touch "test file for docker commit demo" >> commit.txt
##### created a user 'sk12k'
    useradd sk12k

##### Exit the container
    exit
    or
    ctrl+P+Q (on your keyboard)
:::


##### Commit the image from the container
:::warning
docker commit <container-id> <new-image-name>
:::
    
##### Validate
:::warning
- Create a container from the new-image
- verify the changes commited in earlier step
:::

##### Clean-up
:::warning
Stop all containers
    
    docker stop <container-id>

delete all containers and images

    docker system prune --all
    or
    docker image rm <image-name>
:::

#### Image creation using Dockerfile
    
##### Docker Workflow
![](https://i.imgur.com/n0JPzUE.png)

##### Dockerfile format
    
````
# comment
INSTRUCTION arguments
````

##### Most commonly used Dockerfile instructions
:::warning
FROM
LABEL
RUN
ADD
COPY
ENV
EXPOSE
USER
VOLUME
WORKDIR
CMD
ENTRYPOINT
:::

:arrow_right: For full list of Dockerfile instructions refer here --> https://docs.docker.com/engine/reference/builder/
    
    
#### Create an image using Dockerfile
:::warning
- Create a dedicated directory
````yaml=
mkdir docker-demo
cd docker-demo/
````
- Create Dockerfile
````yaml=
vi Dockerfile
````
*Sample Dockerfile content:*
````yaml=
FROM ubuntu
LABEL "maintainer"="sk12k@simplilearn.net"
RUN apt-get update
RUN apt-get install -y nginx tree
RUN useradd sk12k
ENV environment production
COPY index.nginx-debian.html /var/www/html
CMD nginx -g 'daemon off;'
````

Create another file in the same directory
````yaml=
vi index.nginx-debian.html
````
*Sample file content*
````
Welcome to Nginx from Simplilearn and Docker
````
- Build the image
````yaml=
docker build -t sk-nginx .
````
- Verify the image has been created

````yaml=
docker image ls
````

- Create a container from newly created image
````yaml=
docker run -idt -p 8001:80 --name=sk-web1 sk-nginx
````

- Verify that nginx is accessible from the newly created container
````yaml=
On Simplilearn Lab:
curl localhost:8001

On DigitalOcean:
Go to your browser:
<IPaddress>:8001
````
- Verify if tree package was installed
````    
docker exec -it <container-id> which tree
````
- Verify if sk12k user was created
````
docker exec -it <container-id> id <user-id>
````
- Verify if the file was created in /tmp directory with the right content
````    
docker exec -it <container-id> ls /tmp
and/or
docker exec -it <container-id> cat /tmp/<file-name>
````
:::
    
#### Push local image to Dockerhub
    
:::warning
- Make sure you have a profile on Dockerhub. If you don't have one go ahead and create one on https://hub.docker.com/
- Verify your Docker credentials by logging in to https://hub.docker.com/
- You need to make sure that image name is in the following format:
<profile-name/image-name>
For example if your user name for Docker hub is sk12k, your image name should be:
sk12k/image-name
    
*Change the image name using the following command:*
````yaml=
Syntax:
docker tag <current-image-name> <new-image-name>

Example:
docker tag sk-nginx sk12k/nginx-jan
````
- Verify that the image has been renamed:
````yaml=
docker image ls
````
:mag: *Please note that you would see both the old image name and new image name listed in the output.*

- Now login to dockerhub via command line
````yaml=
docker login
````
:mag: *Provide your Docker hub username and password when prompted*
    
- Once you have logged in successfully via Docker CLI, run the following command to push the image to Dockerhub:
````yaml=
Syntax:
docker push username/imagename
    
Example:
docker push sk12k/nginx-jan
````
- It will take a few seconds for the image to be uplaoded.
- Verify that your image has been successfully uploaded by logging in to hub.docker.com on a web browser and go to repositories

![](https://i.imgur.com/ZplZdGQ.png)
    
:::

:arrow_right: Please note that you need login credentials only for *"docker push"* and not for *"docker pull"*.

#### Class activity
:::warning
- Write a Dockerfile
- Build the image using Dockerfile
- Run a container to validate (You should be able to access the app using browser)
- push the image to dockerhub
- Remove your image from local cache and run it again from docker hub
:::
### Working with Multiple Containers using Docker-Compose

#### Docker Compose Overview
:::warning
- https://docs.docker.com/compose/
:::
#### Docker-Compose Installation
:::warning

- sudo curl -SL https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
- sudo chmod +x /usr/local/bin/docker-compose
- docker-compose --version
:::

:arrow_right: *For full installation steps take a look at https://docs.docker.com/compose/install/other/*

#### Docker compose installation script
    
````sh=
##########################################################
## Docker compose (V2) installation script
## Tested on Ubuntu 22.04
##########################################################
## docker-compose --> V1
## docker compose --> V2
##########################################################

echo "##########################################################"
echo "Update the apt package index and install packages to allow apt to use a repository over HTTPS"
echo "##########################################################"
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg

echo "##########################################################"
echo "Add Docker’s official GPG key"
echo "##########################################################"
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo "##########################################################"
echo "Use the following command to set up the repository"
echo "##########################################################"
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
echo "##########################################################"
echo "Update apt package index"
echo "##########################################################"
sudo apt-get update

echo "##########################################################"
echo "Install docker compose plugin"
echo "##########################################################"
sudo apt-get install docker-compose-plugin

echo "##########################################################"
echo "Validate compose installation"
echo "##########################################################"
docker compose version
````
#### Wordpress using Docker Compose
:::warning
- Create a project directory
````yaml=
mkdir my_wordpress
cd my_wordpress/
````
- Create a docker-compose.yaml file
````yaml=
services:
  db:
    # We use a mariadb image which supports both amd64 & arm64 architecture
    image: mariadb:10.6.4-focal
    # If you really want to use MySQL, uncomment the following line
    #image: mysql:8.0.27
    command: '--default-authentication-plugin=mysql_native_password'
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=somewordpress
      - MYSQL_DATABASE=wordpress
      - MYSQL_USER=wordpress
      - MYSQL_PASSWORD=wordpress
    expose:
      - 3306
      - 33060
  wordpress:
    image: wordpress:latest
    volumes:
      - wp_data:/var/www/html
    ports:
      - 80:80
    restart: always
    environment:
      - WORDPRESS_DB_HOST=db
      - WORDPRESS_DB_USER=wordpress
      - WORDPRESS_DB_PASSWORD=wordpress
      - WORDPRESS_DB_NAME=wordpress
volumes:
  db_data:
  wp_data:
````

- Build the project
````yaml=
docker-compose up -d
````
- Validation
````yaml=
http://localhost:80
or
http://<public-ipaddress:80>
````
- Shutdown and Cleanup
````yaml=
docker-compose down 
docker-compose down --volumes
````
:::

:arrow_right: *Wordpress using Docker Compose - Full documentation here --> https://github.com/docker/awesome-compose/tree/master/official-documentation-samples/wordpress/*    
:arrow_right: *All Docker Compose projects here --> https://github.com/docker/awesome-compose/blob/master/official-documentation-samples/README.md*

    
    
### Docker Ecosystem
:::warning
- Docker (runtime)--> Individual containers on one host
- Docker Compose  --> Multiple containers on one host
- Docker Stack    --> Multiple Containers on multiple hosts (using docker compose files)
- Docker Swarm    --> Full-fledged container orchestration capabilities

:::
### References
:::info
**Beginner**
- https://docs.docker.com/get-started/overview/
- https://www.docker.com/play-with-docker/
- https://docker-curriculum.com/

**Advanced**
- https://ecsworkshop.com/
- https://eksworkshop.com/
- [Containers on Azure](https://azure.microsoft.com/en-gb/products/category/containers)
- [Containers on AWS](https://aws.amazon.com/containers/)
- [Azure Container workshop](https://stoacawks.z6.web.core.windows.net/)

**Certification (DCA)**
- https://training.mirantis.com/certification/dca-certification-exam/
- https://github.com/Evalle/DCA
:::