Creating your first Docker Container - A beginner's Guide
Tags: docker, python, containers
Published: 2023-03-05 08:57:45

Picture this, you built a cool homepage for a website and it is working exactly as you want on your machine. You share it with someone else to get their feedback, but it just won't work the same way. Believe it or not, this happens all the time in the software development world. Docker is a tool that helps you solve this.

### What is Docker?
Docker is a powerful tool for creating, deploying, and managing software applications in containers. A **container** is a lightweight, standalone, and executable package that includes everything needed to run the software, such as code, libraries, and dependencies. Think of it as a complete bundle with all the inner working hidden from the outer world. Docker can be used to create these containers which are independent of the host's environment, thus providing the same experience across systems.

###  How does this work?
Containers have their standalone filesystem thanks to the **images** they are built on. An Image is a building block of the container and hence houses everything that is required for the container to run - the code, the filesystem, dependencies.
Docker packages these all in one image which can then be used to create the containers.

In this tutorial, we will containerise a simple Python application. Note that the same process can be used to create containers of any size.

### Project Structure

Go ahead and create a new folder on your system. We will call this `docker-test`. Create a python file called `pydock.py`. Add the following sample code to the python file or feel free to use your own code.

```py
from faker import Faker
from tabulate import tabulate
fake = Faker()

# print 10 fake names and addresses
table = [['name','address']]
# generating the names and addresses
for _ in range(10):
    name = fake.name()
    address = fake.address()
    table.append([name,address])

# print in tabular format
print(tabulate(table,headers='firstrow',tablefmt='fancy_grid'))

```
This is a simple application that generates fake names and addresses in a tabular format. Notice that we are using external libraries - `faker` and `tabulate` for the same.

Now create a `.dockerignore` file in the root of the project. Use this to add the files that you want to ignore while creating an image. Your folder structure should look like this:
```
docker-test
-- pydock.py
-- .dockerignore
```

### Docker Setup
Go ahead and install **Docker Desktop** for your system from [here](https://docs.docker.com/get-docker/). While you are at it, create an account on [dockerhub](https://hub.docker.com/) as well. 

Once docker desktop is installed, you can open the application. This will automatically start a `docker daemon` in background. 

### Dockerfile - where the magic lives

Next, create a file called `Dockerfile` in the root of the project. This defines how the image will be created and what will be used to create the image. The project structure should now look like this:
```
docker-test
-- pydock.py
-- .dockerignore
-- Dockerfile
```
Edit the contents of the `Dockerfile` as follows:
```Dockerfile
FROM python:3.8-slim-buster

WORKDIR /app

COPY . .

RUN pip install Faker tabulate

CMD [ "python3","pydock.py"]
```

Let's go over the contents of this `Dockerfile` from top to bottom. 
- The `FROM` instruction specifies what kind of image we want to create. We can pull pre-built images from **DockerHub**, including full-scale Operating Systems. However in this case, we just need to build a python image so we are using `python:3.8-slim-buster`. You can choose any python image that are mentioned [here](https://hub.docker.com/_/python)
- The `WORKDIR` instruction specifies the working directory in the container's filesystem. Think of this as the path where your image will sit and run in the container. In this case it is `/app`.
- The `COPY` instruction lets you copy files from your machine to the image. The syntax is `COPY <source> <target>`, where `<source>` is the file path on your local machine and `<target>` is the file path on the container starting from the working directory. 
- `RUN` instruction is used to execute commands during the build process of a Docker image. Here we are using this to install our dependencies - `Faker` and `tabulate`. 
- The `CMD` instruction is used to specify the default command to be executed when a container is started from the image. Notice that `CMD` uses an array format to define the commands while `RUN` uses a simple string format

**IMPORTANT:** Docker images are a set of layers. Every instruction in a `Dockerfile` creates a layer. These layers are cached internally for faster image builds.

### Building a Docker image
Once you are done with the `Dockerfile`, we can move on to create your first Docker image. Open terminal in the root of your project. You can check if Docker is running using 
```
docker --version
```

To build an image, run the following:
```
docker build  -t <username>/<image-name>:<tag> .
```

You can call the image whatever you want, but the following conventions are generally used.
- The `-t` option lets you create a tag for you image.
- `<username>` is your docker hub username.
- `<image-name>` is the name you want to give to the image.
- `<tag>` is like the version number for the image.
- `.` is the path where `Dockerfile` is present, here we have it in the root of the project

Docker starts creating image layers from the instructions mentioned in the `Dockerfile`. Once done, you can check your built image in Docker Desktop.

### Running the container
To run the image inside a container, we will use the following:
```
docker run <username>/<image-name>:<tag>
```
This will run a container from the image that we built in the above process. You should see a similar output once you run the above command.

![Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n09itskcivh84b6pqx2b.jpg)

Congratulations🎉🎉! You have created your first Docker Container successfully. You can check the container in Docker Desktop and even publish this to Docker Hub. You can share this image with others and they can simply run this as a standalone application. No installation fuss, no dependency issues, nothing! They won't even know what's inside the container but the container works as required!


*CREDITS*
Cover photo by [Venti]("https://unsplash.com/@ventiviews?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/1cqIcrWFQBI?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)