Containerize the Front End of an Application with a Multi-Step Docker Build

Joel Lord
InstructorJoel Lord
Share this video with your friends

Social Share Links

Send Tweet

For your front end, a VueJs application has been created from the CLI. VueJS, just like React and Angular applications have a development mode as well as a production mode.

Once you are ready to deploy this application, you won’t want to use the same code as you do when you develop. In fact, you will need to run another script to build a production application. This script will take all of your JavaScript files and merge everything into a single minified JavaScript file. It will do the same for your CSS. By doing so, you will end up with a minimal set of files that can be served over any static file webserver. In this case, you will be using an Nginx server to serve those files. Nginx is an open-source, high-performance HTTP server that will be able to handle many requests to your front end.

We'll do this with a multi-step build in a Dockerfile that will discard the first container that we use to build the source code and run it in a container that's built on top of the nginx image.

Instructor: [0:00] In the last lessons, you saw how to use containers and how to create one for your backend. Now is the time to see more advanced container images. In this lesson, we'll use a container to build our container. This is called a multistage build.

[0:17] For your frontend, a Veu.js application has been created from the CLI. Veu.js, just like React in Angular applications, have a development mode as well as a production mode. When you start in the frontend, at the beginning of this course, you've used npm run serve. This is a development server that is built with Node.js.

[0:39] It watches your files for changes and is optimized to recompile the application and refresh your browser automatically. This is great for development. Once you're ready to deploy this application, you won't want to use the same code.

[0:53] In fact, you'll need to run another script to build a production application. This script will take all of your JavaScript files and merge everything in a single minified JavaScript file. It will do the same for your CSS.

[1:07] By doing so, you will end up with a minimal set of files that can be served over any static file web server. In this case, you'll be using an Nginx server to serve these files. Nginx is an open-source, high-performance HTTP server that will be able to handle manual requests to your front end.

[1:26] When building our front end container, we will only want a container that has Nginx and a minimal HTML, CSS, and JavaScript files, not the full Node.js runtimes. This is why we use a multistep build.

[1:40] The first step will use a container with Node.js to create the files. The second step will be our Nginx server with the files. The container that was used to generate your production files will then be discarded. You will only be left with that second container which is lightweight and optimized for the web.

[2:00] Let's start by creating our docker file. Like in our previous examples, your container will need to start from a base image. In order to build our application, you will need Node and NPM.

[2:13] We can start from Node 14. We will give it an alliance by using the, as keyword. Next, you can copy all of your source code over and change your working directory to the /app folder where the application is now stored inside your container.

[2:31] We can ask this container to install any dependencies, and then run the NPM script that will build our production version. For a Vue.js application, this will create a /app/disk folder with those static files. You now have a container with the production version of your application that is ready to go.

[2:51] This Node.js container can't serve the files at the moment. It doesn't have a server built in. What you will need to do now is to create another container with an Nginx server, and copy the files from the first step into the second container.

[3:07] You can start from an Nginx based image and change your working directory to /usr/share/nginx/html, which is the default folder from which Nginx will serve files. Now, we can copy the file from the first container into this new container by using the --from parameter and the alliance that we gave to that first step.

[3:30] We will take the files from the /app/disk folder, which is our compile website, and copy them into the working directory of this second container. The Nginx image already exposes the port 80, and automatically starts the server once the image is started.

[3:46] You don't need to do anything else. Everything will be handled for you. You can now save this image, and go back to your terminal. You can build this new docker image by using docker build. Let's give it the name katescourse-front. The location of the path is the current work in there.

[4:08] You will now see the steps for both the container is being built. That first container will then be removed so that you will only be left with that last little part, only the Nginx server serving your production ready application.

[4:24] Your front end is now containerized. You can start this image by executing a docker run. Add the -d flag so that it runs in d dash mode. Also add the --rm and --name flags. We will call this one, front.

[4:43] Finally, add a port mapping. Nginx is running on port 80 inside the container, but we will need to map into another port on your machine. Let's use port 8888 to map into the port 80 of our container. Finally, give it the name of the image to start. In our case, it's katescourse-front.

[5:06] Let's open up our browser, go to localhost 8888. You should now see the application running. If you try to generate an image, it should fail. That is because I don't have a back end, nor a database running at the moment. If that is also the case, you can check if your containers are running by using docker ps. If they are not running, you can start them by using the same commands that you've used previously.

[5:43] Now that all services are started, go back to your browser, refresh the page, and you should be able to generate a new meme. Interestingly, you didn't need to add the front end to your case course network.

[5:58] This is because the front end is living in your browser. Any requests that are made by the front end are actually made by our browser on your development machine. Those requests are reaching out to the Internet to the server called localhost. It just so happens that this server is in your local development machine.

[6:18] Everything should now be working. Well, almost. Once you deploy this application, there's a chance that you might want to run your back end service on another service than the localhost.

[6:31] Let's simulate this. First, let's stop the back end server with docker stop, and reuse the same command to restart it, but this time, we'll map to the Port 3001. Refresh this page, try to generate a meme again, and our application is broken again.

[6:50] If you open up the developer tools, you can see that all the requests are still going to Port 3000. It seems the value of our back end was hard-coded in the front end code. Your application will work as long as all the containers are running locally, but it will break if you move the back end to another server, or to another board.

[7:10] To solve this issue, we will need to use environment variables inside of our front end application. This will cause an issue due to the fact that the front end lives in the browser and not on the server where the environment variables are stored. We will see how to solve this in the next lesson.