How to Deploy a Vue Application on Cloud Run
Tags: javascript, serverless, vue, gcp
Published: 2019-10-16 18:19:16

---
title: How to Deploy a Vue Application on Cloud Run
published: true
description: How to make use of environment variables in vue
tags: javascript, serverless, vue, gcp 
---
![feature_image](https://thepracticaldev.s3.amazonaws.com/i/szvkrzhfvwjcc9whq199.png)

##Introduction

Deploying a vue application on cloud run is as straight forward as deploying a node application on cloud run. Deploying a vue application with access to environment variables? not so much. In this article, we will take a look at how we can deploy a vue application on cloud run as well as how we can access environment variables at run time.

##Prerequisites
This tutorial uses the following:
 - Must have a user account on [GCP](https://cloud.google.com/) (Google Cloud Platform) 
 - Must have [Docker] (https://docs.docker.com/v17.09/engine/installation/) installed (version >= 18.09.0)
 - Must have [node](https://nodejs.org/)  installed (version >= 12.5.0)
 - Must have [npm](https://nodejs.org/) installed (version >= 6.9.0)
 - Must have [vue-cli](https://cli.vuejs.org/guide/installation.html) installed
 - Must have a basic knowledge of vue
 - Must have a basic knowledge of docker
 - Must have a basic knowledge of bash

If you have the first six prerequisites sorted out you can proceed to the next section.

## Create a Vue Application
In this section, we are going to set up our vue application and build it into a docker image.

Let's create a vue application by running the following commands:

`$ vue create <app-name>`

Since this tutorial is geared towards deploying a vue application on cloud run (CR) we are not going all out on features, we will keep it simple.

![vue app installation](https://thepracticaldev.s3.amazonaws.com/i/m6jtf5cmd5ot8uanxydd.png)

If your installation is right, you should see the very familiar vue welcome page when you run `$ npm run serve`

To demonstrate the use of environment variables we are going to tweak
`App.vue` and `HelloWorld.vue` respectively like so:

```html
//App.vue

<template>
  <div id="app">
    <img v-if="imgUrl" alt="env gif" :src="imgUrl">
    <img v-else="" alt="Vue logo" src="@/assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

...

```

In the code snippet above we are displaying the original vue logo if the variable `imgUrl` is false. We are going to define `imgUrl` in the created hook like so:

```javascript
//App.vue

...

data(){
  return {
    imgUrl: ''
  }
},

created(){
 this.imgUrl = process.env.VUE_APP_IMG_URL
}

...

```

To keep things simple I cleaned up my `HelloWorld` component like so:

```html
// @/components/HelloWorld.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

...

```

> To use environment variables in your vue application
> you should have a `.env` file in the root directory of your project
> and a variable `VUE_APP_IMG_URL` which contains the URL to your image.

If you visit your vue application on `http://localhost:8080` you should see an image like the one below:

![fresh vue installation](https://thepracticaldev.s3.amazonaws.com/i/qwyb8o2h5bnn766tbdsw.png)

This is because vue is compiled and bundled with webpack which means environment variables will only be made available at build time and not at run-time despite webpack's hot reload being used in development mode. To view changes to our env variables we will have to restart the dev server.
To deploy our vue app to cloud run, we will need a dockerise our application and we will know how to in the next section.

##Build Application Image
In this section, we will learn how to build a docker image that can run our vue application in production.
To do this we will need a docker image with a web server ([NGINX](https://www.nginx.com/resources/glossary/nginx/) ) and node installed.
We can pull these packages in like so:

```shell

FROM nginx:alpine

# Install npm and node
RUN apk add --update npm

# Add bash
RUN apk add --no-cache bash

WORKDIR /app

COPY package.json ./

RUN npm install

COPY . .

# # Make our shell script executable
RUN chmod +x start.sh

COPY ./nginx.conf /etc/nginx/conf.d/default.conf


CMD ["/bin/bash", "-c", "/app/start.sh && nginx -g 'daemon off;'"]

```

This dockerfile has some dependencies; the `nginx.conf` file and the bash script `start.sh` that builds our application at run time which is triggered by the docker [CMD](https://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/) command. We will fulfil these dependencies by creating the above-said files in the root directory of our vue application like so:

### `nginx.conf`

```shell
server {
    listen 8080;
    server_name _;
    
    charset utf-8;
      root /usr/share/nginx/html;    
      index index.html index.htm;

    location / {
      root /usr/share/nginx/html;      
      autoindex on;
      #try_files $uri $uri/ /index.html =404;    
      try_files $uri $uri/ /index.html =404;    
    }   

}

```
>We are listening on port `8080` because that's a cloud run requirement
>as we can find in the cloud run [contract](https://cloud.google.com/run/docs/reference/container-contract).

### `start.sh`

```shell
#!/bin/bash

if [ ! -d "/app/dist" ] 
then
    npm run build

    echo "Build finished...";

    echo "Delete node_modules folder";

    rm -rf node_modules

    echo "START COPY";

    cp -rf  /app/dist/. /usr/share/nginx/html/

    echo "END COPY";
fi

```
> In this file, Since we are building at runtime, we will wouldn't 
> want to build our application every single time a request is made to
> our application. To avoid this, we will check if the `dist` directory 
> exists before we build the static assets and copy them into the nginx 
> web directory.

Now we have fulfilled our dockerfile dependencies we can now build the docker image and push to [GCR](https://cloud.google.com/container-registry/) (google container registry).

>To adhere to the [12 Factor app rule](https://www.nginx.com/blog/microservices-reference-architecture-nginx-twelve-factor-app/) no. 3 we are going to populate
>our `.env` file with a default value which is going to be dynamic with
>respect to different cloud run revisions. 

In our application root directory, we will build the docker image like so:

`$ docker build -t cr-tutorial .`

When completed, we will tag the image and push it to gcr. To do so, you need to have auth for docker to use `gcloud`. You can find out more information on how to do so on the [container registry page](https://cloud.google.com/container-registry/docs/pushing-and-pulling). If that's sorted, we can tag and push to gcr like so:

`$ docker tag cr-tutorial gcr.io/[PROJECT_ID]/cr-tutorial`

>Where `cr-tutorial` is the local image name and
>[PROJECT_ID] is your GCP project id


`$docker push gcr.io/[PROJECT_ID]/cr-tutorial`

>When push is completed, gcr.io/[PROJECT_ID]/cr-tutorial
>will be your application image URL which will come in 
>handy soon.

## Deploying to cloud run
To deploy our vue application image to cloud run, we will visit the cloud run page on GCP and click on the `create service` option on the info panel.

![create_service_image](https://thepracticaldev.s3.amazonaws.com/i/78g5lq8ale08mvngva9c.png)

In the create service panel, we are going to set our application settings as well as input the link to our application image (gcr.io/[PROJECT_ID]/cr-tutorial) like so:

![create_service_panel](https://thepracticaldev.s3.amazonaws.com/i/dl0ab6bmy6jtqzpa17y7.png)

If you're ok with the config, you can click the create button below to deploy your application to cloud run. When the deployment is done, when you visit your cloud run app URL, you should see a screen like so:

![cloud_run_app](https://thepracticaldev.s3.amazonaws.com/i/b843mqfo5jw4lmdwquq9.png)

Now to demonstrate our use of `.env` variables at run-time, we will deploy a new revision on cloud run and pass in our env variables.

### Deploying a new CR revision
To deploy a new revision we will click on the `Deploy revision` option on the deployed service info panel

![deploy_revision](https://thepracticaldev.s3.amazonaws.com/i/ay8kezncw13x4c0jcw5i.png)


Then we will fill up our `VUE_APP_IMG_URL`(https://bit.ly/2MiYZT2) value in the `env` section like so:

![deploy_revision_panel](https://thepracticaldev.s3.amazonaws.com/i/3dcwfpkwcx2dvn4lw7un.png)

When the revision is done, you should see something that looks like the image below:

![updated_revision_gif](https://thepracticaldev.s3.amazonaws.com/i/bs9rlsfk36847ocj8xtx.gif)

##Conclusion
In this tutorial, we have been able to deploy a vue application which receives environment variables at run-time. This is because the application is being built at run-time as well. You can find the repository for this project on [GitHub](https://github.com/enkaypeter/vue-cloudrun-tutorial).