DEV Community

Zane
Zane

Posted on

Building an Efficient Jenkins + Docker + Vue Project Automated Deployment Environment

Highlights

  • Custom Shell scripts make controlling the integrated deployment environment more convenient and flexible.
  • If the server is replaced, the workload for redeployment is relatively small.

Preparations

First, you need to have a server. I used an Alibaba Cloud ECS instance in the East China region. There are plenty of tutorials online for purchasing a server. After the purchase, you will have a public IP and a password to log into the server via SSH.

If you are not familiar with Docker, I recommend checking out its documentation first. Docker containers are like shipping containers on a cargo ship. Each container holds its own goods and doesn’t affect the others. For example, a Redis service and a MongoDB service can each be placed in their own container. These containers rely on an execution environment, which Docker calls an Image. Each container manages its own lifecycle.

Jenkins is an open-source software project developed in Java, mainly used for continuous integration. Essentially, it allows you to pre-write scripts, and once these scripts are successfully debugged, they can be automatically executed for future deployments without modification.

Installing Docker

Reference Documentation

Uninstalling Old Versions

$ sudo apt-get remove docker docker-engine docker.io
Enter fullscreen mode Exit fullscreen mode

Installing via APT

Since APT sources use HTTPS to ensure that software is not tampered with during download, we need to add the HTTPS transport package and CA certificates first.

$ sudo apt-get update
Enter fullscreen mode Exit fullscreen mode
$ sudo apt-get install 
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
Enter fullscreen mode Exit fullscreen mode

Given the network issues in China, it is strongly recommended to use domestic sources. For official sources, see the comments.

To verify the legitimacy of the downloaded packages, add the GPG key for the software source.

$ curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

# Official Source
# $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Enter fullscreen mode Exit fullscreen mode

Next, add the Docker software source to source.list:

$ sudo add-apt-repository \
    "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
    $(lsb_release -cs) \
    stable"

# Official Source
# $ sudo add-apt-repository \
    # "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
    # $(lsb_release -cs) \
    # stable"
Enter fullscreen mode Exit fullscreen mode

The above command adds the stable version of the Docker CE APT source. If you need the test or nightly build versions, change stable to test or nightly.

Installing Docker CE

Update the APT package cache and install Docker CE:

$ sudo apt-get update

$ sudo apt-get install docker-ce
Enter fullscreen mode Exit fullscreen mode

Installing Automatically via Script

For testing or development environments, Docker provides a convenient installation script to simplify the process. On Ubuntu systems, you can use this script:

$ curl -fsSL get.docker.com -o get-docker.sh

$ sudo sh get-docker.sh --mirror Aliyun
Enter fullscreen mode Exit fullscreen mode

Running this command will automatically prepare everything and install the Edge version of Docker CE on your system.

Starting Docker CE

$ sudo systemctl enable docker

$ sudo systemctl start docker
Enter fullscreen mode Exit fullscreen mode

Creating the Docker User Group

By default, Docker commands communicate with the Docker engine using a Unix socket. Only the root user and users in the Docker group can access the Docker engine's Unix socket. For security reasons, it is generally not recommended to use the root user directly on a Linux system. A better approach is to add users who need to use Docker to the Docker user group.

Create the Docker group:

$ sudo groupadd docker
Enter fullscreen mode Exit fullscreen mode

Add the current user to the Docker group:

$ sudo usermod -aG docker $USER
Enter fullscreen mode Exit fullscreen mode

Log out and log back in, then test Docker.

Testing Docker Installation

$ docker run hello-world

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
d1725b59e92d: Pull complete
Digest: sha256:0add3ace90ecb4adbf7777e9aacf18357296e799f81cabc9fde470971e499788
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image, which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
Enter fullscreen mode Exit fullscreen mode

If you see the above output, the installation was successful.

Image Acceleration

If you find that pulling Docker images is very slow, you can configure Docker's domestic image acceleration.

Alibaba Cloud Mirror Acceleration

Installing Docker Compose

Reference Documentation

Run this command to download the latest stable version of Docker Compose:

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Enter fullscreen mode Exit fullscreen mode

Apply executable permissions to the binary:

$ sudo chmod +x /usr/local/bin/docker-compose
Enter fullscreen mode Exit fullscreen mode

Check the version:

$ docker-compose --version
Enter fullscreen mode Exit fullscreen mode

Installing Jenkins

To install Jenkins, I chose to use Docker Compose. Docker Compose automates Docker operations, allowing you to complete all complex Docker operations with a single command.

First, create a directory structure on the server (this is just a demo):

/home/jenkins
     - docker-compose.yml
     - jenkins-home
Enter fullscreen mode Exit fullscreen mode

Next, write a docker-compose.yml file to install Jenkins:

version: '3'    # Specifies the format of the docker-compose.yml file
services:       # Collection of multiple containers
  docker_jenkins: 
    user: root  # Using root to avoid some permission issues
    restart: always # Restart policy
    image: jenkins/jenkins:lts  # Specifies the image to use, in this case, LTS (Long-Term Support)
    container_name: jenkins # Container name
    ports:      # Exposed ports
      - '8080:8080'
      - '50000:50000'
    volumes:    # Volume mount paths
      - /home/jenkins/jenkins_home/:/var/jenkins_home  # Mounts the directory we created to Jenkins's home directory inside the container
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/bin/docker:/usr/bin/docker     # Allows the use of Docker commands inside the container
      - /usr/local/bin/docker-compose:/usr/local/bin/docker-compose # Allows the use of Docker Compose commands inside the container
Enter fullscreen mode Exit fullscreen mode

Navigate to the Jenkins directory and execute:

$ docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

This command will automatically pull the image and configure everything.

If everything goes well, you can now access your server at http://your-server-address:port and see the following interface:

Open the Jenkins directory you created and navigate to jenkins-home:

/home/jenkins/jenkins-home
Enter fullscreen mode Exit fullscreen mode

Enter the secrets directory:

$ cat initialAdminPassword
Enter fullscreen mode Exit fullscreen mode

Copy the content from this file and paste it into the administrator password field.

Next, install two plugins:

NodeJS Plugin
Publish Over SSH
Enter fullscreen mode Exit fullscreen mode


Scroll down to the bottom.




Start Creating Project Deployment

Official Reference

1. First, create an nginx.conf file in the root directory of your project:

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  www.lovelp.xin;  # Domain name
    location / {
      root   /app;  # Directory location
      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;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Create a Dockerfile in the root directory of your project:

FROM node
WORKDIR /app

COPY package*.json ./
RUN npm install -g cnpm --registry=https://registry.npm.taobao.org
RUN cnpm install
COPY ./ /app
RUN npm run build:prod

FROM nginx
RUN mkdir /app
COPY --from=0 /app/dist /app
COPY nginx.conf /etc/nginx/nginx.conf
Enter fullscreen mode Exit fullscreen mode

3. Create a setup.sh script in the root directory of your project to help execute commands:

#!/usr/bin/env bash
image_version=`date +%Y%m%d%H%M`;
# Stop the shop_admin container
docker stop shop_admin || true;
# Remove the shop_admin container
docker rm shop_admin || true;
# Remove the shop/admin image
docker rmi --force $(docker images | grep shop/admin | awk '{print $3}')
# Build the shop/admin:$image_version image
docker build . -t shop/admin:$image_version;
# List the images
docker images;
# Create a container named shop_admin from the shop/admin image
docker run -p 9527:80 -d --name shop_admin shop/admin:$image_version;
# View logs
docker logs shop_admin;
# Remove images generated during the build process
docker rmi $(docker images -f "dangling=true" -q)
# Automatically clean up space
docker system prune -a -f
Enter fullscreen mode Exit fullscreen mode

4. Finally, create a project on Jenkins:

Finally, you can happily click on Build Now.

Top comments (9)

Collapse
 
denys_bochko profile image
Denys Bochko

I am just curious why to use jenkins? I think it is an old tech. Gitlab offers pipelines that work very well for deployments of back-end and front-end apps. One less app to install/configure and maintain.
The setup is one yml file in the project that tells gitlab what to do. I deploy one of my vue projects that way.

Collapse
 
zand profile image
Zane

For simpler projects with fewer requirements, using GitLab CI/CD directly is often more convenient and faster. However, we opt for Jenkins because its extensive plugin ecosystem and compatibility with our architecture make it a better fit for our needs.

Collapse
 
denys_bochko profile image
Denys Bochko

The reason I asked is that a lot of teams use it because that is the only thing they know. But in your case, it seems that it's all been thought through.
Which cloud are you using with that setup, if you don't mind me asking?

Collapse
 
martinbaun profile image
Martin Baun

This is great! What's your tech-stack?

Collapse
 
zand profile image
Zane

As for the front-end technology stack, there are many.

Collapse
 
zand profile image
Zane

Our current deploy technology stack is gitlab + jenkins + k8s.

Collapse
 
martinbaun profile image
Martin Baun

Pretty cool :)

Collapse
 
vkinsane profile image
Vishal Khandate

Fantastic guide on setting up an automated deployment pipeline with Jenkins, Docker, and Vue! This is a must-read for anyone looking to streamline their DevOps workflow.

Collapse
 
zand profile image
Zane

Thank you for your recognition.