A step-by-step guide to develop and deploy Vue apps with docker, part one
Tags: devops, javascript, docker, vue
Published: 2021-08-13 19:44:42

[Previously](https://blog.q-bit.me/quick-dirty-how-to-deploy-a-fullstack-vue-js-app-with-a-working-node-js-backend/), I've described a very simple way to develop and deploy a Vue.js app using a combination of `git` and `npm`. This works fine to quickly prototype an app and see how it behaves in the wild. In case you're in for a productive project, you probably want to use a more predictable end-to-end workflow.

This series of articles will equip you with the knowledge to create, develop and deploy a Vue project with Docker. With some tweaks, you can also use the featured `Dockerfiles` to deploy any project, using other frameworks such as React or Svelte.

Introducing Docker
------------------

Docker is a tool to build and deploy containerized units of software. So next to the source code for the application, a Docker project will also bring the environment to run it.

In a nutshell, compared to the quick & dirty approach I've described previously, there are several significant advantages, such as:

*   Node.js is not required on the hosting machine, neither on your local device, for development, testing, or productive usage.
*   The installation of node modules and the building of the app can be done inside the container(s).
*   We can easily replace the static express folder with a 'real' server. In this case, we'll use `nginx` to serve the web app.
*   Sharing code and replicating errors in a team context is much easier.
*   Docker itself comes with some goodies, such as [networks](https://docs.docker.com/network/) and [docker-compose](https://docs.docker.com/compose/reference/), making it easy to manage apps, APIs, and databases altogether.

Docker is built around two core structures: Containers and Images.  
To not confuse these two, keep the following in mind when reading ahead:

1.  **Images are blueprints for containers**. They include the source code and the required runtime, like Python or Node.js
2.  **Containers are living units of software.** They are running based on an underlying image.

If you would like to dig deeper into how Docker helps you with your development workflow, you can find some references at the end of this article.

Installing Docker
-----------------

For the scope of this article, we want to make use of all of Docker's capabilities. That means: **You need to have no other tool installed but Docker itself**. We'll use it to execute all further setup steps for the Vue development and build process.

### Linux (Ubuntu) quick setup

Taken from [https://docs.docker.com/engine/install/ubuntu/](https://docs.docker.com/engine/install/ubuntu/)

```shell
# Remove previous versions of docker
sudo apt-get remove docker docker-engine docker.io containerd runc

# Update package list & install necessary dependencies
sudo apt-get update
sudo apt-get install \
  apt-transport-https \
  ca-certificates \
  curl \
  gnupg \
  lsb-release

# Add Docker's GPG key to your local mashine
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Install Docker
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

### Windows setup

As Windows does not support containerization out of the box, you will need Docker Desktop to keep following along. You can download it using the link below.

https://docs.docker.com/docker-for-windows/install/

Setting up the project
----------------------

It is common for web frameworks to require some steps in between project initialization and deployment. To make sure this process can be replicated, Docker makes use of `Dockerfiles`, single files that describe steps to build an `Image`.

Naturally, you can use a local Node.js setup for development and containerize the app when it's ready for shipping. In this case, however, I'd like to leave the whole setup to Docker. So before we jump into development, let's start by setting an image that creates our project's structure and enables us to extend it.

### The initial project structure

Change into a directory of your choice and create the following folder structure:

```shell
/
| - /dockerfiles
|   | - Setup.Dockerfile  # 1
|   | - Dev.Dockerfile    # 2
|   | - Deploy.Dockerfile # 3
```

To give you an idea of what these three `Dockerfiles` will help us achieve:

1.  This image is responsible to scaffold a basic project structure, as well as installing further npm packages.
2.  We will use the second one to serve the project during development.
3.  Image three is responsible for building and shipping the app once we're ready to do so.

So much for the theory. Let's walk through these steps now, one by one.

### Step 1: Initialize the app

While it is common to use Docker for app development and deployment, in this case, we will also use it to set up our initial project structure. Like so, we can reduce the amount of software to be installed on our local machine and keep the setup process lean & replicable.

We'll start by using the [Vue CLI](https://cli.vuejs.org/) to set up our app's structure. Since it depends on Node.js, we'll start `FROM` node:14 and add some additional command layers on top.

Into the `Setup.Dockerfile`, add the following content:

```shell
FROM node:14

WORKDIR /vue-setup

RUN npm install -g @vue/cli

# The following commands ensure access to our files
# If we left them out, changing files on our local setup
# would fail due to insufficient permissions. 
RUN userdel -r node

ARG USER_ID

ARG GROUP_ID

RUN addgroup --gid $GROUP_ID user

RUN adduser --disabled-password --gecos '' --uid $USER_ID --gid $GROUP_ID user

# Set the active user and open the interactive terminal
USER user

ENTRYPOINT [ "bash" ]
```

We can then build our vue\_helper image using the following command.

```shell
# Build an image named vue_helper using the Setup.Dockerfile
# The build args manage permissions when executing commands from inside the container
docker build \
  --build-arg USER_ID=$(id -u) \
  --build-arg GROUP_ID=$(id -g) \
  -t vue_helper - < ./dockerfiles/Setup.Dockerfile
```

Executing the next command will bind the container's working directory to our local machine, using a [bind-mount](https://docs.docker.com/storage/bind-mounts/).

> Make sure the replace `/path/to/project/` with your own project path.

```shell
docker run -v /path/to/project/:/vue-setup -it vue_helper
```

Next, a terminal from inside the container will open. Here, we can now install the Vue app itself and add more npm modules, if necessary.

```shell
user@b24a617a1dfa:/vue-setup$ vue create vue_app
```

You will then be prompted through the [standard Vue CLI setup](https://cli.vuejs.org/guide/creating-a-project.html). In case you are unsure what to choose, just confirm all standard steps.

Given everything till this point went well, you will notice a new directory named `vue_app` appearing in your project folder. It origins from inside the container and means that everything went according to plan and our project is ready to be worked on.

Let's recapitulate what happened till this point:

*   We've used Docker to create a new image named `vue_helper`.
*   It uses a bind-mount and an interactive session terminal to help us scaffold our Vue project.
*   By using `Vue create` inside the container with a dedicated user, we have a basic project boilerplate available on our local device - without ever installing anything on it.

Stay tuned for the next part, where we will:

*   Explore how to serve the containerized app during development.
*   Build an application image and have it run on our local machine.
*   Deploy the image to Dockerhub and serve it on a [Digital Ocean Droplet](https://www.digitalocean.com/products/droplets/)

References
----------

### Docker 101 - self-paced tutorial

https://www.docker.com/101-tutorial

### Official Docker documentation

https://docs.docker.com/get-started/

> This post was originally published at https://blog.q-bit.me/how-to-develop-and-deploy-a-vue-js-app-with-docker-part-one/
Thank you for reading. If you enjoyed this article, let's stay in touch on Twitter 🐤 [@qbitme](https://twitter.com/qbitme)