Sandbox is not supported on mobile, try on a computer
Docker is a powerful platform that simplifies the development process by allowing containerization of the applications. In simple words, Docker enables us to ship applications along with their dependencies (libraries, files etc).
In this hands-on exercise, we will learn fundamentals of Docker by performing basic operations, e.g.:
Pulling an image from Docker registry
Listing or Removing Images
Creating ,Removing and Running a container
Starting or Stopping a container
Listing containers and accessing container logs.
Building images from Dockerfiles and running in a container
Docker streamlines almost all phases of the development lifecycle, from development (i.e. allowing developers to work in standardised environments using local containers) to testing (i.e. running multiple instances to be tested by different tools/people in parallel) to finally deployment at scale (i.e. deployment on Kubernetes or AWS ECS or serverless).
Read on to learn more on Docker:
Docker Architecture
Docker's architecture is designed to provide a lightweight and efficient containerization platform. The above figure provides a helpful illustration of Docker's architecture, which consists of several key components:
1. Docker Client:
The Docker client is the primary interface through which users interact with Docker. It accepts commands from the user and communicates with the Docker daemon to execute those commands. The client can run on the same host as the daemon or on a remote machine, allowing users to manage Docker resources remotely
2. Docker Daemon:
The Docker daemon (dockerd) is the heart of the Docker engine. It is a long-running process that manages Docker objects, such as containers, images, networks, and volumes. The daemon handles container orchestration, image pull and push, and other essential tasks related to running containers
3. Docker Images:
Docker images are read-only templates that contain the application code, runtime, libraries, environment variables, and other dependencies needed to run an application. Images are the building blocks for containers and can be versioned for easy management and sharing.
4. Docker Containers:
Docker containers are isolated and lightweight runtime instances created from Docker images. Each container runs an application and its runtime environment, isolated from other containers and the host system. Containers provide consistent behaviour across different environments and enable efficient resource utilisation.
5. Docker Registries:
Docker registries are repositories that store Docker images. They can be public or private and serve as central repositories for sharing and distributing Docker images. Docker Hub is the default public registry, while users can set up their private registries for secure image management.
6. Docker Network:
Docker networking allows containers to communicate with each other and the host system. Docker provides various networking options, such as bridge, host, overlay, and custom networks, to facilitate communication between containers and the outside world.
7. Docker Volumes:
Docker volumes are used to persist and share data between containers and the host system. Volumes enable data storage separate from container instances, ensuring data durability even if the container is removed.
The architecture diagram visually represents how these components interact with each other to provide a robust containerization platform. The Docker client communicates with the Docker daemon, which, in turn, manages containers, images, networks, and volumes. Docker images are stored in registries, which can be accessed by the Docker daemon for image management. Containers are created from images and run in isolated environments, enabling seamless deployment and consistent behaviour across various environments.
Overall, Docker's architecture streamlines the process of developing, shipping, and running applications within containers, making it a popular choice for modern software development and deployment workflows.
Uses of Docker:
Application Isolation: Docker allows applications to run in isolated environments, preventing conflicts with other applications or system libraries.
Portability: Docker containers are highly portable, ensuring seamless deployment across various platforms and cloud environments.
Resource Efficiency: Containers share the host system's OS kernel, resulting in resource efficiency and lower overhead compared to traditional virtualization.
Version Control: Docker images allow version control for your applications, simplifying rollbacks and updates.
Rapid Scaling: Docker's lightweight nature makes it ideal for rapidly scaling applications, both horizontally and vertically.
Exercise Manual
Step 1: Welcome! Let's dive into the world of Docker. In this exercise, we will cover basics operations and commands of Docker. Are you ready to get started?
Step 2: Our sandbox environment already has Docker but you can install it on your machine by following the documentation link provided below.
Step 3: Let's pull the latest Ubuntu image from Docker Hub. Pull means bringing an image from remote Docker repository to our Docker setup. Open your terminal and run the following command.
Step 4: List all the images present on our local Docker setup. Give it a try in your terminal and see what images you've pulled so far!
Step 5: Docker image name is a combination of image name and tag. For example, `ubuntu:latest` is the image name and tag. If you don't specify a tag, Docker will pull the latest image by default. And, that is why we are seeing `ubuntu:latest` in the output.
Step 6: Let's try to pull tag 20.04 for Ubuntu image from Docker Hub.
Step 7: If we list all the images again, we'll see that we now have two Ubuntu images with different tags.
Step 8: When we don't need an image anymore, we can remove it from our local Docker setup. To remove an image, run the command `docker rmi <image_ID or name>`. Replace `<image_ID or name>` with the actual ID or name from the `docker images` output.
Step 9: Let's remove the Ubuntu image with tag 20.04. Run the command `docker rmi ubuntu:20.04` in your terminal.
Step 10: Now, let's move on to containers. Containers are running instances of Docker images. We'll cover how to run, list, remove containers, and access their logs.
Step 11: Let's run an Nginx container. We don't have nginx image present on local Docker setup so Docker will pull it from Docker Hub (provided it exists there). We will name the contyainer `my_nginx`, and map port 8000 of your system to port 80 of the container.
Step 12: Naming the container is optional. If you don't specify a name, Docker will assign a random name to the container. However, it makes it easier to manage and select containers if we give them meaningful names.
Step 13: The `-d` flag runs the container in detached mode. This means that the container will run in the background. If you want to run the container in the foreground, you can omit the `-d` flag.
Step 14: Check all the running containers. We should be able to see the Nginx container we just started.
Step 15: Click on 'localhost:8000' button to see the Nginx welcome page.
Step 16: To stop a running container, run the command `docker stop <container_ID or name>`. As our container has the name `my_nginx`, we'll run `docker stop my_nginx` in the terminal.
Step 17: To list all containers, including stopped ones, use `docker ps -a`. Give it a try, and you'll see the list of containers on your system!
Step 18: A stopped container can again started using `docker start <container_id_or_name>`. Lets start the Nginx container we just stopped. Run `docker start my_nginx` in your terminal.
Step 19: To view the logs of a container, run `docker logs <container_ID or name>`. Let's view the logs of the Nginx container we just started. Run `docker logs my_nginx` in your terminal.
Step 20: -f flag is used to follow the logs. This means that the logs will be streamed to the terminal. If you omit the `-f` flag, you'll only see the logs that have already been generated. We can stop the logs from being displayed by pressing `Ctrl + C`.
Step 21: To access the shell of a running container, use the command `docker exec -it <container_ID or name> bash`. This will open a bash shell inside the container. Let's try it out! Run `docker exec -it my_nginx bash` in your terminal.
Step 22: To exit the shell, run the `exit` command.
Step 23: We can remove the container using the command `docker rm <container_ID or name>`. Let's remove the Nginx container we just stopped. Run `docker rm -f my_nginx` in your terminal. -f flag is used to force remove the container and is required to remove a running container.
Step 24: Similarly, we can run a container in interactive mode using the `-it` flag. This will open a bash shell inside the container. Let's try it out! Run `docker run -it --name my_nginx -p 8000:80 nginx:latest` in your terminal.
Step 25: It works exactly the same. We can stop the container by pressing `Ctrl + C`.
Step 26: Now that we have a good understanding of working with containers, let's move on to building images from Dockerfiles.
Step 27: We will use already created Dockerfile and Flask app for this exercise. Clone the repository by running `git clone https://github.com/web3coda/docker-basics` in your terminal.
Step 27: The link to the repository is also provided below. You can use it outside of sandbox environment as well.
Step 28: Open VS Code by clicking on the button. We will use VS Code to check the Dockerfile and Flask app files.
Step 29: Check 'dockerfile-tutorial' folder inside the cloned 'docker-basics' repository. This is the folder we will use for this exercise.
Step 30: Open Dockerfile by clicking on the file name in the left sidebar. This is the Dockerfile we will use to build the image for our Flask app. It is well documented so you can understand what each line does.
Step 31: Also, check app.py and requirements.txt files. These files are used by the Dockerfile to build the image for our Flask app.
Step 32: Dockerfile will create image that we can use to package a Flask app.
Step 33: Open the terminal, switch to 'dockerfile-tutorial' folder, and run the comamnd to build the image. The `-t` flag is used to tag the image. The `.` at the end of the command is the build context. It tells Docker to look for the Dockerfile in the current directory.
Step 34: The image is named `my_flask_app` and tagged `latest`. It will take a few seconds to build the image.
Step 35: Once the image is ready, we will create a container from this.
Step 36: Click on 'localhost:8000' button to see the app default/home page. If you still see the Nginx welcome page, use left click menu and select 'reload frame' option.
Step 37: Congratulations! We have successfully completed Docker Basics lab!