DEV Community

Cover image for How to Serve a Vue App with nginx in Docker
Nick Scialli (he/him)
Nick Scialli (he/him)

Posted on • Originally published at typeofnan.dev

How to Serve a Vue App with nginx in Docker

Let's create a website using the Vue framework and learn how to serve it in a Docker container using nginx.


If you enjoy this post, please give it a 💓, 🦄, or 🔖 and consider signing up for 📬 my free weekly dev newsletter


To start out, we are going to use the Vue CLI to generate a starter Vue app.

We will name this app vue-nginx-docker.

npx @vue/cli create vue-nginx-docker
Enter fullscreen mode Exit fullscreen mode

For this tutorial I'll be using yarn, so if you want to follow along exactly be sure to select "yarn" when generating the application. It's totally fine to select npm as well; you will just need to adjust some of the Docker commands accordingly.

Once the app is set up, navigate to the new app folder:

cd vue-nginx-docker
Enter fullscreen mode Exit fullscreen mode

Now we know we'll need a couple files to use with Docker: a Dockerfile and a .dockerignore file. Let's make them now.

touch Dockerfile
Enter fullscreen mode Exit fullscreen mode

For our .dockerignore file, let's make sure to ignore our dependency files in node_modules like we would with git.

echo "node_modules" > .dockerignore
Enter fullscreen mode Exit fullscreen mode

Building Out the Dockerfile

Time to build out the Dockerfile! There are a lot of ways we could do this, but today we'll use a multi-stage process:

  • Stage 1: Node image for building frontend assets
  • Stage 2: nginx stage to serve frontend assets

Stage 1: Building the front-end assets

Our first stage will:

  • Use a node image
  • Copy all our Vue files into a working directory
  • Install the project dependencies with yarn
  • Build the app with yarn

Here's how this looks in Docker!

# Name the node stage "builder"
FROM node:10 AS builder
# Set working directory
WORKDIR /app
# Copy all files from current directory to working dir in image
COPY . .
# install node modules and build assets
RUN yarn install && yarn build
Enter fullscreen mode Exit fullscreen mode

Next up, we actually serve the content we just built!

Stage 2: Our nginx server

Our second stage will:

  • Use an nginx image
  • Remove any default static assets from the nginx image
  • Copy our static assets from the builder image we created in the first stage
  • Specify the entrypoint for our container to run nginx

Here's what this stage looks like in the Dockerfile:

# nginx state for serving content
FROM nginx:alpine
# Set working directory to nginx asset directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static assets
RUN rm -rf ./*
# Copy static assets from builder stage
COPY --from=builder /app/dist .
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]
Enter fullscreen mode Exit fullscreen mode

Importantly, Vue builds the static assets into the dist folder by default, so we copy our files from there. If your app builds the files into another folder for some reason, adjust accordingly.

Putting it All Together

Okay! Let's put this all together and run our app.

Our multi-stage Dockerfile should now look like this:

# Multi-stage
# 1) Node image for building frontend assets
# 2) nginx stage to serve frontend assets

# Name the node stage "builder"
FROM node:10 AS builder
# Set working directory
WORKDIR /app
# Copy all files from current directory to working dir in image
COPY . .
# install node modules and build assets
RUN yarn install && yarn build

# nginx state for serving content
FROM nginx:alpine
# Set working directory to nginx asset directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static assets
RUN rm -rf ./*
# Copy static assets from builder stage
COPY --from=builder /app/dist .
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]
Enter fullscreen mode Exit fullscreen mode

Now that we have assembled our Dockerfile, let's build an image called vue-nginx:

docker build -t vue-nginx .
Enter fullscreen mode Exit fullscreen mode

Now that our image is built, we can start a container with the following command, which will serve our app on port 8080.

docker run --rm -it -p 8080:80 vue-nginx
Enter fullscreen mode Exit fullscreen mode

Navigate to http://localhost:8080, and you should now see our default Vue app!


If you enjoy this post, please give it a 💓, 🦄, or 🔖 and consider signing up for 📬 my free weekly dev newsletter

Top comments (3)

Collapse
 
vchaindz profile image
vchaindz

Thanks for the article! In my case an additional generate was required for dist to be created:
RUN yarn install && yarn build && yarn generate

Collapse
 
hendisantika profile image
Hendi Santika • Edited

I am running docker build OK.
I am running docker run. It was stuck & got hang.

What is the issue?

Thanks

Collapse
 
mw44118 profile image
W. Matthew Wilson

This is nice and simple! It is worth pointing out how this won’t rebuild your docker image every time you change your code, but that isn’t always what you need!