Getting Started with vue-cli on Docker

Getting started with vue-cli on Docker

Now that vue-cli as "the standard tooling baseline for the Vue ecosystem" has recently been released as stable in v3.x. here is a linear walk-through on how to use it in dockerized environment: Although the documentation for vue-cli is excellent - as always in vuejs - this post walks you through the minimum steps.

Nevertheless if you are pretty new to vuejs but willing to dive into vuejs (and vue-cli as a predefined toolbox for it) you will need to go through the documentation. In other words: this post assumes at least minor to intermediate knowledge in vuejs.

What is vue-cli?

The very short answer is that it is the same as create-react-app for react and provides an integrated and predefined tool chain for developing with vue.

The little longer answer according to the docs:

Vue CLI aims to be the standard tooling baseline for the Vue ecosystem. It ensures the various build tools work smoothly together with sensible defaults so you can focus on writing your app instead of spending days wrangling with configurations. At the same time, it still offers the flexibility to tweak the config of each tool without the need for ejecting. (source)

Further feature listings such project scaffolding and rapid prototyping can also be found there.

Do I Really need it (now)?

If you are just getting started with vuejs or only want to test if it is the right framework for you and/or the project ... then probably not.

Don't forget that you can add vue to any (existing) project by just adding:

# https://vuejs.org/v2/guide/#Getting-Started

<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

# or

<!-- production version, optimized for size and speed -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

This is all you need to get the whole functionality of vue to your project and you can instantly test how it feels to work with it at the given task - no other setup (whether on the client- nor on the server-side) is required. Even the official guide recommends this way (and has a JSFIddle Hello World Example):

The Installation page provides more options of installing Vue. Note: We do not recommend that beginners start with vue-cli, especially if you are not yet familiar with Node.js-based build tools. (source)

The (almost) short answer here: If using this approach you could/should consider vue always then when you usually would use e.g. jQuery for some extra functionality provided by an external library ... with vuejs and the one-liner above you get the functionality of a full-blown framework - and its (growing) ecosystem.

An example of a server-side rendered Express application (with Pug templates) using vuejs only via a <script> tag on the client-side can be found here.

Requirements

As for v3.x. vue-cli the official docs state:

Vue CLI requires Node.js version 8.9 or above (8.11.0+ recommended). You can manage multiple versions of Node on the same machine with nvm or nvm-windows.

For some utilities such as linting or some plugins such as vuetify a git installation and repo may also be required.

This post uses Docker and a docker swarm as a development environment. This of course is not mandatory for using vue-cli. Regarding hot reloading during development it may even be easier/faster to not work with Docker. There is an extra post covering this topic and the available options here.

Setup for Development

To use Docker right from the beginning without any locally installed nodejs you could use something like the following:

# use a docker host bind to the disk of your e.g. laptop
docker run -itd -v /path/on/host:/path/in/container node:10.9-slim

docker ps
docker exec -it <container_id> /bin/bash
    # now inside the container
	cd /path/in/container
	npm install -g @vue/cli
	vue create your-app
        # pick your choices now or stick with the default config
        # After the installation you should see something like
            # Vue CLI v3.0.1
            # yarn install v1.9.2
    exit
docker rm -f <container_id>

Now the container has written your app directory to /path/on/host/your-app. Now with the code "locally" available we can create a basic Dockerfile:

FROM node:10.9-slim

# not mandatory if you EXPORT a fixed port. See below.
ARG YOUR_APP_WEB_HTTP_PORT

RUN apt-get -y update \
	&& apt-get install -y git

RUN yarn global add @vue/cli -g

WORKDIR /path/in/container/your-app

RUN apt-get autoremove -y \
    && apt-get autoclean -y \
    && apt-get clean -y \
    && rm -rf /var/lib/apt/lists/*

# Or just use EXPORT 8080
EXPOSE ${YOUR_APP_WEB_HTTP_PORT}
# If yout want use vue-cli UI you need to also EXPORT 8000 

USER node

# switch to npm if you chose it as package manager
CMD ["yarn", "serve"]

A basic docker-compose file for using a docker stack during development:

version: "3.3"

services: 
  s1_wb:
    build: 
      context: ./path/to/dockerfile_dir
      dockerfile: Dockerfile.dev
      args:
        - YOUR_APP_WEB_HTTP_PORT=8080
    image: <your_registry>/<your-app_image-name>:<your-app_image-tag>
    ports:
      - "8080:8080"
      - "8000:8000"  # only needed if using vue-cli UI
    volumes:
      - /path/on/host:/path/in/container
    stdin_open: true
    tty: true
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure 
        max_attempts: 5
      resources:
        limits:
          cpus: 4
          memory: 4096M
    environment:
      # https://cli.vuejs.org/guide/mode-and-env.html#modes
      # development is used by vue-cli-service serve
      - NODE_ENV=development
      # one way for hot reloading ... see above for details 
      - CHOKIDAR_USEPOLLING=true
      - CHOKIDAR_INTERVAL=100
      - YOUR_APP_WEB_HTTP_PORT=8080

With this in place you are ready to start deploying this development docker stack by:

docker-compose -f docker-compose.dev.yml build
docker-compose -f docker-compose.dev.yml push
docker stack deploy --compose-file=docker-compose.dev.yml ${COMPOSE_PROJECT_NAME} --with-registry-auth

You can verify by e.g.:

docker stack ps ${COMPOSE_PROJECT_NAME}
docker stack services ${COMPOSE_PROJECT_NAME}
docker ps -a | grep ${COMPOSE_PROJECT_NAME}

Depending on your setup (Docker Host in a VM on your laptop or on a remote machine) you can now access the default vue-cli app in your browser on: http://<docker_host_ip>:8080.

You can now attach (connect interactively) to your running container by:

docker attach <container_id>

With this command you do connect to the actual process (already running in the container) yarn serve. The initial webpack dev-server build might take a while but after that hot reloading after saving file changes in your editor should happen much quicker and be visible in the shell where you attached to the container.

If you chose to setup unit testing as well you could do (with exec opening a separate process in the running container):

docker ps
docker exec -it <container_id> /bin/bash
    # now inside the container ... within set WORKDIR
	yarn test:unit
	#	PASS
	exit

If you want to try out vue-cli UI:

docker ps
docker exec -it <container_id> /bin/bash
    # now inside the container ... within set WORKDIR
	vue ui
    # port 8000 has to be exposed and mapped as well
    # in your browser on `http://<docker_host_ip>:8000`
	# ctrl+C to end it
	exit

The most import command to see how vue-cli and especially webpack and webpack dev-server are configured is probably:

# inside the container
vue-cli-service inspect

See the docs for further information and available custom configuration:
https://cli.vuejs.org/guide/webpack.html#simple-configuration
https://webpack.js.org/concepts/
https://webpack.js.org/configuration/dev-server/
https://webpack.js.org/configuration/watch/
https://cli.vuejs.org/guide/browser-compatibility.html#polyfills
https://cli.vuejs.org/guide/mode-and-env.html#modes
https://cli.vuejs.org/guide/mode-and-env.html#using-env-variables-in-client-side-code

Summary

While this post is not intended to get you completely introduced to vue and vue-cli per se it showed how to set it up on a containerized basis. As mentioned if you just want to try out vue do not use vue-cli, but just add vue to your index.html. If you then come to realize that vuejs, its concepts and ecosystem are the right choice for you then come back here if you are also using Docker in your tool chain.

Initially I wanted to cover here also deployment options for a production build of a vue-cli based application but this post is already long enough and the topic is probably worth another dedicated blog post. Nevertheless you can find some useful links below.

Further Information

VueJS:
https://vuejs.org
https://vuejs.org/v2/guide/#Getting-Started
https://github.com/vuejs/awesome-vue

Vue-CLI:
https://github.com/vuejs/vue-cli
https://cli.vuejs.org
https://cli.vuejs.org/guide/webpack.html#simple-configuration

Webpack:
https://webpack.js.org/concepts/
https://webpack.js.org/configuration/dev-server/
https://webpack.js.org/configuration/watch/

React:
https://reactjs.org
https://github.com/facebook/create-react-app
https://reactjs.org/docs/create-a-new-react-app.html
https://reactjs.org/docs/add-react-to-a-website.html

Deployment (production build):
https://cli.vuejs.org/guide/deployment.html#general-guidelines
https://cli.vuejs.org/guide/deployment.html#routing-with-history-pushstate
https://cli.vuejs.org/guide/browser-compatibility.html#modern-mode
https://mherman.org/blog/dockerizing-a-react-app/

Hot reloading:
https://daten-und-bass.io/blog/enabling-hot-reloading-with-vuejs-and-vue-cli-in-docker/

Using vuejs via <script> tag only (in a server-side rendered Express App):
https://github.com/daten-und-bass/p-g-a_sample/blob/master/views/index.pug

Using vue-cli for an application:
https://github.com/daten-und-bass/mercator-shop