Making MySQL Query Results More Concise with GROUP_CONCAT
October 13, 2018Couchbase – Big OFFSETs can be a big problem
December 13, 2018Docker build problems
Docker is a great tool for deploying scalable web applications for a large variety of technologies ranging from Node.js, Python, MySQL, and more. We have been using Docker at Computer Know How for some time but we recently ran into a challenge with an application we were setting up for Docker.
The application was written in Vue.js so we wanted to deploy the application using the NGINX Alpine image. However, we needed to have Node.js installed to build the static files from the Vue.js source files. We looked into some options like Scott Mebberson’s alpine-nginx-nodejs Docker image, but that image used Node.js 6 and our application required Node.js 8 to build properly. That forced us to look for another option.
I knew that there must be a better way to pre-build the Vue.js application and then deploy it using the NGINX Alpine Docker image, so I did some research and found the perfect solution: multi-stage builds.
Multi-stage builds
Multi-stage builds allow you to use intermediate images to build the application piece by piece until you construct the final image where you run the application. With this information, the build became quite simple and required only two stages:
- Build the Vue.js application to create the distributable files
- Serve the distributable files using an NGINX web server
Using the multi-stage build documentation I constructed a Dockerfile to perform the two stages required for building this application.
# https://docs.docker.com/develop/develop-images/multistage-build
# Step 1: Build with Node.js
FROM node:8.12.0 AS builder
# Make project directory
RUN mkdir /project
WORKDIR /project
# Copy folders
COPY src src
COPY public public
# Copy files
COPY package.json package.json
COPY babel.config.js babel.config.js
COPY postcss.config.js postcss.config.js
COPY vue.config.js vue.config.js
# Build application
RUN npm install -g npm@latest
RUN npm install --silent --progress=false
RUN npm run build
# Setp 2: Deliver the dist folder with Nginx
FROM nginx:alpine
# Copy Nginx configuration for the application
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Copy the Vue.js build output to the Nginx site directory
COPY --from=builder /project/dist /usr/share/nginx/html
It worked perfectly, and we were able to deploy the application. Multi-stage builds also have the advantage of creating smaller containers because intermediate images and files are not kept unless they are copied to the final stage of the build.