POSTS / Containerize Vue.js Application and Deploy on Server
I’ve been struggling on deploying String10/ChinaOpenDataPortal-FrontEnd-Vue@9d43c36
for a whole day. Here’s some log of steps and issues.
Containerize Vue.js App
Build a docker image is easy. Following Vue CLI Guide is just everything you need.
I wrote a Dockerfile
like this:
# build stage
FROM node:lts-alpine as build-stage
COPY ./ /app
WORKDIR /app
RUN npm install
RUN npm run build
# production stage
FROM nginx:stable-alpine as production-stage
COPY /app/dist /app
COPY docker/nginx.conf /etc/nginx/nginx.conf
with nginx.conf
just as guide showing:
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;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /app;
index index.html;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
.dockerignore
went like this:
**/node_modules
**/dist
Rewrite Environment Variables
I put a .env
file for convenience, which causes a big problem. During build, environment variables will be injected into the application. The resulting static files just contain the content of my .env
as hardcoded strings.
As StackOverflow user NehaM’s answer shows, we can put a dummy value as env-vars while build then replace it using a custom entrypoint
. Here you can refer the entrypoint
as a script executes as the docker container start running. With the help of entrypoint
, we get a runtime configurable image without borthering from the origin .env
file.
Here’s the script:
#!/bin/sh
ROOT_DIR=/app
# Replace env vars in files served by NGINX
for file in ${ROOT_DIR}/index.html ${ROOT_DIR}/assets/*.js;
do
sed -i 's|VUE_APP_MY_VARIABLE_PLACEHOLDER|'${VUE_APP_MY_VARIABLE}'|g' $file
# Your other variables here...
done
# Let container execution proceed
exec "$@"
Then update the Dockerfile
:
# build stage
FROM node:lts-alpine as build-stage
COPY ./ /app
WORKDIR /app
RUN npm install
+ ARG VUE_APP_MY_VARIABLE=VUE_APP_MY_VARIABLE_PLACEHOLDER
RUN npm run build
# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /app
+ ARG POSTPROCESSING_SCRIPT=rewrite-env-vars.sh
+ COPY docker/${POSTPROCESSING_SCRIPT} /docker-entrypoint.d/${POSTPROCESSING_SCRIPT}
+ RUN chmod +x /docker-entrypoint.d/${POSTPROCESSING_SCRIPT}
COPY docker/nginx.conf /etc/nginx/nginx.conf
.dockerignore
:
**/node_modules
**/dist
+ .env*
Push to Docker Hub
Run command:
docker build -f docker/Dockerfile -t USER_NAME/IMAGE_NAME .
docker push USER_NAME/IMAGE_NAME
Deploy on Server
Create docker-compose.yml
:
version: '3.4'
services:
frontend:
image: 'USER_NAME/IMAGE_NAME'
container_name: CONTAINER_NA<E
restart: unless-stopped
ports:
- 'PORT:80'
environment:
- 'VUE_APP_MY_VARIABLE=XXXX'
Then run docker compose up -d
to start a docker container.
Nginx Configuration
Refer to #34.