Docker for Beginners
Tags: docker, webdev, devops, softwareengineering
Published: 2024-05-01 08:25:44

**What is Docker?**
Docker is an open-source software platform that enables developers to run applications on any machine. This removes the pain of setting up and configuring different machines for running the same application. Docker allows you to create, deploy, and manage virtualized environments on a common operating system (OS).

**Benefits of Using Docker**

- Same Environment Consistency: Docker ensures applications behave the same way on any machine (local and remote servers).

- Continuous Integration and Delivery (CI/CD): Containers are ideal for CI/CD workflows.

**Prerequisites for Learning Docker**

- Basic understanding of Linux commands

- File system concepts

- User groups and permissions

**How Docker Works**

- Docker runs containers.

- A container encapsulates all the code and environment needed to run an application.

- It includes the operating system, configuration, and application code.

**Difference Between Virtual Machines and Containers**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rx964fmqiuz517301ut8.png)

**Virtual Machine (VM):**

- A virtual machine gets its own full operating system, including a kernel (the core that controls low-level tasks).

- This approach is resource-intensive on the host machine running the VMs.

- Architectural layers: Server, Host OS, Hypervisor, VMs (App, Bins/Libs, Kernel)

**Container:**

- A container is not a full virtual machine.

- It shares the host(our PC) machine’s kernel but maintains isolation through a unique file system (a feature of Linux distributions).

- Docker uses this file system to create isolated environments.
Containers start up quickly and use fewer resources (disk space, memory) compared to VMs.

- Architectural layers: Server, Host OS, Container (App, Bins/Libs, Kernel)

**Image:**

- An image is a template for a running instance called a container.

- An image defines the OS, software, and application code, all bundled up in a single file called a Dockerfile.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6rexdw8tkhkpj0r7517m.png)

**Dockerfile:**

- A Dockerfile is a text file containing instructions to create an image.

- You can configure the operating system, install required software, copy project files, and more.

**Let’s Build Our First Image**
We’ll create a PHP file that prints “Welcome to code with rubab” when a user visits our website.

**Create an index.php file:**

```
<?php echo "Welcome to code with rubab"; ?>
```
Save this file as index.php in your project folder named code-with-rubab

Now we will create a file called “Dockerfile” inside our project folder to create an image. We will configure our environment to run our index.php file inside Dockerfile.

**Create a Dockerfile:**
Create a file named Dockerfile inside your project folder. This file will define how to build the image.

First, we need an operating system with PHP and Apache installed. Apache is a web server software. In our traditional way, we had to install the OS, apache, and php manually. But with docker, we have images already built that save tons of time. Our image will be built on top of that Apache build. There are lots of existing images for Apache and we can find those images on [the Docker hub](https://hub.docker.com/_/php). Here, we will use a Debian OS-based PHP.

code-with-rubab/Dockerfile

```
FROM php:8.2.0-apache
COPY . /var/www/html
EXPOSE 80
```

Explanation:

- FROM php:8.2.0-apache: This line specifies the base image we'll use. It's a pre-built image containing PHP and Apache.

- COPY . /var/www/html: This copies all files from the current directory (.) to the /var/www/html directory within the container. This is where Apache looks for web application files.

- EXPOSE 80: By default, the Docker container ignores all incoming requests. This line tells Docker that the container listens on port 80, the standard port for web traffic.

Note: When you copy files into the container using the COPY instruction, Docker marks all subsequent build steps as “dirty” and re-runs them.

**Docker Build Command:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yliglr4r5gl0vc189xum.png)

To build the image, navigate to the directory containing the Dockerfile in your terminal and run:

```
docker build -t code-with-rubab .
```
Explanation:

- -t: This option specifies a tag for the image. Here, we're naming the image ascode-with-rubab.

- .: The dot (.) refers to the current directory where the Dockerfile is located.

What Happens Behind the Command:

- The first time we run this command, it downloads all the layers of the base php:8.2.0-apache image. Then, it copies our project files into the image and creates a new image named code-with-rubab.

But you will get an error when you run this command

> ERROR: error during connect: this error may indicate that the docker daemon is not running

Solution: We need a docker engine. If you are a Windows user download from [here](https://docs.docker.com/desktop/install/windows-install/). For window users, we need to do some extra work to run this docker engine.

When you run docker engine on Windows, you will see this alert message

> Docker desktop is unbale to detect a hypervisor

To solve this issue we need to enable hypervisor. To do this, we need to enable Virtualization technology from BIOS settings, Install the Windows subsystem for Linux, and finally need to enable the hypervisor and Windows subsystem for Linux from Windows features on and off settings. [Check the steps from here](https://www.youtube.com/watch?v=qeaFtGtQvUw&list=PLLhwyo0tKUfv3DianBA7L_7VlyIWLYczw&index=17).

Now after installing and running the docker engine, we can build our project properly and a successful image build will look like below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b7hka75f7vsbw5fz4rtx.png)

To check the new image we can simply type this command

```
docker images
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jg17ob2s3x62l6lkghi.png)


**Docker Run command:**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ql0o53hfzp7ue86sisxy.png)


Now, we will create a container from the image we have just created.

```
docker run -p 80:80 code-with-rubab
```
Explanation:

- -p 80:80: This option maps port 80 on the host machine (our computer) to port 80 within the container. When a request reaches our computer’s port 80, Docker forwards it to the container’s port 80. The container’s EXPOSE line in the Dockerfile allows it to accept this request, and Apache handles it.

- code-with-rubab: This is the name of the image you want to run to create a container.

Now, if we hit a browser URL with localhost then we will see the “Welcome to code with rubab” message which means our application is running inside a Docker container, Yay!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydlx518b2d0zzscusyqv.png)


**Bonus:**
Now, If you try to change the message from the codebase and set a new welcome message “Welcome to Rubab, Rashed, and Rasel’s planet” then you will see the message is not reflected in the browser.

What happened?

The docker does not know what has been changed in our codebase as the code was already shipped with the docker image and until we rebuild and re-run our container we will not get the reflection of changes. This a very tedious work and we do these boring tasks.

To make docker look for changes we make in our codebase, we need to add volume in our docker run command. So, if we build our image now, docker will know where to check changes on our machine during the container’s run time. So, we will add volume now.

First, we to stop the running container with Ctrl+c.

Now, add the volume to our docker run command

```
Docker  run -p 80:80 -v <path-of-your-project-directory>/:/var/www/html/ code-with-rubab
```

Explanation:

- -v = v means volume
- <path-of-your-project-directory>/:/var/www/html = <path-of-your-project-directory>/ is our host’s project directory, in my case my local PC directory was “D:/docker/docker-beginner/” and “/var/www/html” is our container’s directory path.

So, the changes we make now will be reflected in the browser.
One more thing, After running the docker run command we are unable to interact with our current shell. So, to do this we will run the container in the background or detached mode. For this, we will use -d for detached mode.

```
Docker  run -d -p 80:80 -v <path-of-your-project-directory>/:/var/www/html/ code-with-rubab
```

Now, we will be able to use the current sell. Let’s see our running container by typing this command

```
docker ps // ps is short form of process which is a container
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8j87h501j0r0sq2uk2ny.png)


**More Docker Commands:**
I’ve listed down more commands to play with our current docker setup. There are lots of other docker commands we can google on the browser.

```
docker build --no-cache -t <image-name>. // force a complete rebuild
docker build --progress=plain -t <image-name> . // detailed build info

docker image prune // clean dangline images
docker image rm <image-name>

docker ps -a // all running/stopped
docker stop container-id // stop a container
docker container prune // clean stopped container

// To interact with container using sh (shell command). 
// Example:we can check our index.php file in the container
docker exec -it container-id sh 
```
**Important Notes on Container:**
- The container’s lifetime is directly tied to its main process, one process per container. If the main process terminates, even if background tasks are running, the container will stop automatically without warning.

- Containers are lightweight, allowing you to run many containers simultaneously on a single machine.

But we need to run a complete project using MySQL, Laravel, redis, and phpmyadmin. What about if I have frontend react app and backend Laravel API projects? Don’t worry, this is just the first part of my Docker series. In my next Docker article, I will cover the whole process (Hint: Docker Compose).

Happy Learning!

----------------------------------------

Thank you for reading my article. You can join [code with rubab](https://www.facebook.com/groups/codewithrubab) for web development-related queries & discussions.

Also, you can find me on:

[Linkedin For Regular Posts](https://www.linkedin.com/in/imran-hossain-rubab/)

[My website](https://codewithrubab.com/)

[My Facebook Page](https://www.facebook.com/codewithrubab)

[My Youtube Channel](https://www.youtube.com/@codeWithRubab)