# 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

#### Container based Virtualization

#### Containers vs Virtual Machines


*Source: https://www.atlassian.com/microservices/cloud-computing/containers-vs-vms*
#### Containers on Virtual Machines

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

#### 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

:::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

##### 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

:::
: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
:::