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
Uninstalling Old Versions
$ sudo apt-get remove docker docker-engine docker.io
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
$ sudo apt-get install
apt-transport-https \
ca-certificates \
curl \
software-properties-common
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 -
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"
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
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
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
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
Add the current user to the Docker group:
$ sudo usermod -aG docker $USER
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/
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
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
Apply executable permissions to the binary:
$ sudo chmod +x /usr/local/bin/docker-compose
Check the version:
$ docker-compose --version
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
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
Navigate to the Jenkins directory and execute:
$ docker-compose up -d
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 the secrets
directory:
$ cat initialAdminPassword
Copy the content from this file and paste it into the administrator password field.
Next, install two plugins:
NodeJS Plugin
Publish Over SSH
Scroll down to the bottom.
Start Creating Project Deployment
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;
}
}
}
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
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
4. Finally, create a project on Jenkins:
Finally, you can happily click on Build Now
.
Top comments (9)
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.
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.
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?
This is great! What's your tech-stack?
As for the front-end technology stack, there are many.
Our current deploy technology stack is gitlab + jenkins + k8s.
Pretty cool :)
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.
Thank you for your recognition.