Creating single page apps has become a more frequently requested task of web developers (like me) and deployment in containers, across zones and under monitoring, seems like a natural step.

In this post we’re going to have a look at how to deploy a Vue.js SPA with docker.

Let’s start off by installing the vue-cli to create a boilerplate project. Make sure you have Docker installed as well.

My video course on Vue.js has just been released with PACKT:



Click here to check it out!

Installing the Vue CLI is just an npm install away:

npm install -g @vue/cli

Now we create a project with vue create projectName (I’ll choose vue-docker as my project name` and pick the Manually select features configuration option.

Next, we’ll arrow key down to Router , hit SPACE and ENTER . I chose to hit ENTER for the rest of the options as well.

After a quick installation, you should see output that looks a bit like this:

⚓ Running completion hooks... 🎉 Successfully created project vue-docker. 👉 Get started with the following commands: $ cd vue-docker $ npm run serve

Now we change to the directory that our app was set up at and verify it works with:

cd vue-docker npm run serve

You should see something similar to the screenshot below in your browser at http://localhost:8080 :

To create a docker container, we’ll need to create a Dockerfile that runs nginx, a high performance web server.

Dockerfile

# Create the container from the alpine linux image FROM alpine:3.7 # Add nginx and nodejs RUN apk add --update nginx nodejs # Create the directories we will need RUN mkdir -p /tmp/nginx/vue-single-page-app RUN mkdir -p /var/log/nginx RUN mkdir -p /var/www/html # Copy the respective nginx configuration files COPY nginx_config/nginx.conf /etc/nginx/nginx.conf COPY nginx_config/default.conf /etc/nginx/conf.d/default.conf # Set the directory we want to run the next commands for WORKDIR /tmp/nginx/vue-single-page-app # Copy our source code into the container COPY . . # Install the dependencies, can be commented out if you're running the same node version RUN npm install # run webpack and the vue-loader RUN npm run build # copy the built app to our served directory RUN cp -r dist/* /var/www/html # make all files belong to the nginx user RUN chown nginx:nginx /var/www/html # start nginx and keep the process from backgrounding and the container from quitting CMD ["nginx", "-g", "daemon off;"]

We also need to create the nginx config files that we’re referencing, nginx.conf and default.conf in the directory nginx_config :

nginx.conf

user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile off; keepalive_timeout 60; #gzip on; include /etc/nginx/conf.d/*.conf; }

default.conf

server { location / { root /var/www/html; try_files $uri $uri/ /index.html; } }

The try_files line is significant, because if a file can not be found, we will serve the index.html file and let the Vue Router figure out which component to display. This is somewhat of a fallback to index.html .

Now let’s build our docker container and name it vue-docker-container :

docker build -t vue-docker-container .

and lastly we can run our container with:

docker run -p 8080:80 vue-docker-container

Now you should be able to see your app in your browser again, but this time it’s being run from with Docker and you are free to deploy your container where ever you please!

Modifying the Vue Router to use HTML5 history mode

In order to remove the # in the URL, we need to pass the mode option to the Vue router and set it to history like below:

import Vue from 'vue' import Router from 'vue-router' import Home from './views/Home.vue' import About from './views/About.vue' Vue.use(Router) export default new Router({ mode: 'history', routes: [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', component: About } ] })

Deploying to Docker without building “in container”

You don’t have to build your app inside the Dockerfile, you can also simply run npm run build and then copy your directory in with

COPY dist /var/www/html

in your Dockerfile . This also saves you the additional nodejs dependency, but that requires you to do one more step and if you have a team working on a project, they might use different versions to build which might add unwanted variations.