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