Hands-on docker: Deploying Your First Containerized App

This post and all of it's content has been written with the assumption that you are familiar with basic Docker concepts. If you are not, or just need a review of the topic, please click here.

Once you have learnt the basics of docker, I am sure you want to implement you knowledge, right? I certainly know I was. I believe the best way to learn is by doing. So let's learn Docker in the most effective way we can, by using it.

ALL THE COMMANDS IN THIS WALK-THROUGH NEED TO BE RUN WITH ADMIN PRIVILEGES

The first step in this process is to install docker. I am assuming you do not have docker installed. If you do, you can skip this part.

The docker installation steps are quite complex and differ for every OS. You will find several OS-specific guides to install docker if you look for them. There is actually an installation guide on the docker website itself. Here is the link to it https://docs.docker.com/engine/install/.

Before we create the container, we need the image. To create the image, we need to define it first. The definition of a docker image is called a Dockerfile. You can download the Dockerfile and other necessary files here.


  • Dockerfile
  • index.html
  • script.js

The Dockerfile is the main part of the whole thing. Lets look at it further. Here are the contents

# Use NGINX as a base image
FROM nginx:alpine

# Copy HTML and JavaScript files to the NGINX default serving directory
COPY index.html /usr/share/nginx/html/
COPY script.js /usr/share/nginx/html/

# Expose port 80
EXPOSE 80

The comments do a good job of explaining what is going on, but let's go through it anyways.

  1. From: This tells docker which image you are starting form. Every image you make from a Dockerfile has to originate at some image. After that, you make modifications to the image to get it to a place where you want. We are starting with the Nginx image. Nginx is a very popular web server. The part after the colon is called the tag. We are using the Nginx docker image installed on Alpine Linux.
  2. Copy: This copies a file from our file system to the image. We are copying the index.html and the script.js files that were located in the zip file you downloaded above. We are putting them in the /usr/share/nginx/html directory. This is the directory where all the content that nginx serves is stored.
  3. Expose: This keyword does nothing. It is best practice to have it there, though, so it will be there. This tells the reader that port 80 on the container should be opened to get the utility out of the container.

Now that we have covered the zip file and all it's contents, we can now build the image. To build it, we use the following command.

docker build -t hello-world .

You can replace hello-world with any image name you want.

WARNING: The above command needs to be executed with admin privileges.

Make sure you are executing that command within the folder which contains the contents of your zip file. Let's break down what the command does.

Docker: This is the utility that we will be using throughout this tutorial to interact with the docker containers.

Build: This command builds a docker image using a Dockerfile. This takes 1 argument, the relative path to the Dockerfile or the directory containing the Dockerfile you want to use.

-t: The t stands for tag. This is essentially the name of your image. In the example, I used hello-world, but you can use anything you want.

.: As mentioned above, the docker build command takes 1 argument. It is the relative path or the Dockerfile or the directory containing the Dockerfile you want to use. The dot represents the current working directory. This is why it was so important to execute this command from the folder where the contents of the zip file are located. You could, theoretically, execute it from anywhere and simply change the path, though.

We have now created the image from the Dockerfile that you downloaded. Lets see it. To list all the images you have, run the following command:
docker images

In the output, you should see the image that you just built using the docker build command. Now that we have the image, we should make a container out of it.

docker run -d --name hello-world -p8080:80 hello-world

This is a complicated command. Let's break it down.

  1. docker: This is the utility that we are using to interact with docker. It is the docker CLI.
  2. run: This tells docker to create a new container.
  3. -d: This flag tells docker to run the container as a process in the background.
  4. --name: This tells docker what name to refer to the container by. In this case, I used an example of hello-world. You can choose any name you want.
  5. -p: This shows the port(s) that docker has to expose for this container. In this case, we are exposing port 80 on the container to port 8080 on the host. Now, any traffic coming to port 8080 on the host will be directed to the container, and any responses from the container will be sent through the host.
  6. hello-world: This is the name of our image. If your image has a different name, you should put that name here.

Now that this container is created, you can send a request to the container and see the response. Open a new browser tab and open http://localhost:8080. You will see a very simple HTML page which counts the amount of times a page has been loaded.

I encourage you to play around with this more. Maybe see what other things you can add to the Dockerfile. Maybe you can change the files you put in. Maybe you can even use a completely new image! You can do a lot with docker!

CHALLENGE: Build an app that has multiple containers. You can make an API and a frontend, you can make a frontend, backend, and a database, you can use several API's each with their own database, you have many possibilities.

Conclusion

I built this walk-through thinking about what I would want 2 years ago. This is the perfect resource for past me. I hope you followed along and found this tutorial valuable. I encourage you to continue playing around with docker and see what you can make. The possibilities are endless.

If you have any more questions about things covered in this article, you know of another thing I should cover, or you think I should just have done something better, please leave a comment. Thank you for reading.


Comments

Popular posts from this blog

Persistent Data in Docker: Explanation + Hands-On Demo

Pods to Deployments | Kubernetes Architecture Evolution

Docker Compose Explained: Simplifying Multi-Container Deployments