This tutorial is deprecated!

This tutorial was published in 2020 and is no longer maintained. The code might not work as expected and to be honest I would have taken it offline if it wasn't for the fact that it still gets a lot of traffic. I hope you can still find some value in it. I have removed some parts that definetly don't work anymore. I personally really enjoy Nuxt 3 with tailwindcss and Vercel these days. Feel free to checkout my personal website.

Dockerizing Our Front- & Backend

At this point we have a front- and backend that runs perfectly on our local machine. While this tutorial will make more sense if you completed the previous parts, it can also be helpful in general. The goal of this part is that we want to prepare our web-apps for easy and modern deployment. We want to be able to quickly run our front- and backend on any machine and have the ability to scale the application if needed. As with everything else there are plenty of ways to accomplish it. For this series we will work with Docker as it has gained incredible popularity over the past years. This tutorial is split into four subparts:

  • What is Docker?

  • Dockerizing the frontend

  • Dockerizing the backend

  • Running it all at once

What is Docker?

There are millions of explanations on what docker is all over the internet. I want to touch the most important parts but I won't go into details here. My main points were taken from this video.

Lets say we built our backend as jar-file and tested it locally. Now we need to find a place in the cloud to run it. The first challenge that we encounter now is that we can not guarantee that our backend runs in the cloud just like it does locally. Only if the cloud environment is the same as our local environment, we could make such a promise. To get the gap between our local and the cloud environment as small as possible we need to tell our cloud-provider what we need. However, as a cloud provider you can not have a million developers tell you how their individual cloud setup should look like. That is why cloud-providers offer different packages. They vary between providing a (virtual) machine and providing us with a static environment to run our application in. In case of an individual machine it is now up to us, the developer, to make sure the machine behaves as our local machine. That costs too much time and is also expensive as we don't really need an entire machine. We just need a place to run our jar-file. In case of providing us with a static environment we would now have to make sure that our local environment behaves the same. This isn't useful either. Exactly here becomes docker useful.

Docker provides a common ground and is literally comparable with real-life-shipping-containers. A banana-company only worries about how to get their bananas into the container. Once it is closed it does't matter what is in there. It is basically treated like every other container and the shipping-companies know how to work with it. Docker provides a standard that is flexible enough but also makes sure the software runs in the cloud the same way it does locally.

We use docker to create a docker-image of our app. Just image we would burn it on a CD. That image is build using a dockerfile that defines how the docker-image should be built. That image can then be used inside a docker-container.

Docker is a powerful tool and provides more useful features (e.g. scaling). However this is not as relevant here.

Dockerizing the frontend

To dockerize the frontend please make sure that you have docker installed. Additionally we have to look at our base url in config.nuxt.js. You see, if we would deploy our app in the cloud as it is, it would always think our backend is reachable at localhost:8080. That is why we have to extract every environment specific variable.

Extracting environment specific variables

In our frontend we basically have one environment specific variable and that is the URL of our backend.

You may recall that we useed the proxy module in the nuxt.config.js file. All we have to do here is add the environment variables. If no value is present we set it to a default value (http://localhost:8080/)

Creating the dockerfile

Next we will create a dockerfile in our frontend folder called frontend.dockerfile . Our docker file contains the following code.

Hopefully, the comments on each line explain what's going on. To build the image we simply execute this command on the terminal. Make sure to run it from your projects root directory!

  • —file → The file to use for the build

  • -t → To identify our image we tag it

  • . → The location of the build context (the app). In our case the current directory, referenced as .

Dockerizing the backend

Similar to our frontend we have to extract every environment specific variable before we can dockerize or backend.

Extracting environment specific variables

We have two environment specific variables in our backend. The url of or frontend and the url of our database.

All environment specific variables are set in the application.properties file under resources. Each line contains the key and the value. For the value we will set it to an environment variable (that we will provide through docker) or a default value. Insert the following code.

You may wonder why we haven't set the URI for mogoDB before. That is because spring per default assumed to find the mongoDB under that URI. However, that will change once we deploy it. That is why we extract it. The server port will be used in the next part of the tutorial by heroku.

Creating the dockerfile

Next we will create a dockerfile in our backend folder called backend.dockerfile. Our docker file contains the following code.

Hopefully, the comments on each line explain what's going on.

There is one big difference between the frontend- and the backend-dockerfile. The former contains code to build the application. If we make changes to the backend, we will need to build it first using this command.

To build the image we simply execute this command on the terminal. Again, make sure to run it from your projects root directory!

  • —file → The file to use for the build

  • -t → To identify our image we tag it

  • . → The location of the build context (the app). In our case the current directory, referenced as .

Running it all at once

Now that we have everything we need we will use docker-compose to fire everything up. The docker compose tells docker which services (with which images) to start and also sets the environment variables. Create a new file docker-compose.yml in your project's root folder.

To run the app execute

Your application should start and run successfully.



The complete code after completing all parts can be found here.

Part II: The Frontend Using VueJs and NuxtJS