NodeJS (Vue) projects can also be deployed by packaging them into Docker images. The principle is to first package the project into a static page, and then copy the static page directly to the Nginx image for running.
1. Server environment configuration
The installation and configuration of the server Nginx was explained earlier. It is slightly different here. However, because this article is packaged and released by deploying the Nginx mirror and the front-end mirror page at the same time, there is no need to create /data/container/nginx/html here. directory, because the static page to be published is already in the /nginx/html directory in the Nginx image. This also reduces the steps of manual deployment and installation of Nginx. Instead, the shell command is called in the Jenkins task to automatically perform the installation.
1. Create a new Dockerfile file to define the Nginx image and copy the successfully packaged static files to the image. This file is placed in the root directory of the front-end project. Jenkins will search for the Dockerfile file from here when packaging.
FROM nginx:latest
# 维护者信息
MAINTAINER gitegg
# 将生成的静态页面文件复制到nginx的/usr/share/nginx/html/目录
COPY dist/ /usr/share/nginx/html/
# 容器启动时运行的命令
CMD ["nginx", "-g", "daemon off;"]
2. Deployment and backup directory preparation
- Create a new /opt/tmp directory, which is used to transfer the package to the temporary directory of the server through the Publish Over SSH plug-in after Jenkins is packaged (if it has been created before, there is no need to create it again here).
- Create a new /opt/bak directory to store backups of all deployed packages to facilitate rollback of subsequent versions. This directory may take up a lot of space, so you need to choose a mounting directory with large disk space (if you have created it before, there is no need to create it again here).
- Create a new /opt/script directory, which is used to execute relevant command scripts for installation and backup operations after Jenkins completes the package transfer (if it has been created before, there is no need to create it here again).
- Create a new /data/container/nginx/www to map the /var/www directory in the Nginx container.
- Create new /data/container/nginx/logs, map the /var/log/nginx directory in the Nginx container, and store nginx running logs.
- Create a new /data/container/nginx/etc to map the /etc/nginx directory in the Nginx container
- Create a new /data/container/nginx/etc/nginx.conf to map the /etc/nginx/nginx.conf configuration file in the Nginx container
mkdir -p /opt/tmp /opt/bak /opt/script /data/container/nginx/www /data/container/nginx/logs /data/container/nginx/etc
chmod -R 777 /opt/tmp /opt/bak /opt/script /data/container/nginx/www /data/container/nginx/logs /data/container/nginx/etc
3. Write the Nginx configuration file nginx.conf according to the system deployment requirements. The following is a simple configuration method. Under normal circumstances, https requests also need to configure an SSL certificate, as well as ipv6 configuration, etc. The Nginx configuration will be explained in detail later. Be sure to put the modified nginx.conf file in the /data/container/nginx/etc/ directory, otherwise nginx will report an error that the configuration file cannot be found when it starts.
server {
listen 80;
server_name 域名;
gzip on;
gzip_buffers 32 4K;
gzip_comp_level 6;
gzip_min_length 100;
gzip_types application/javascript text/css text/xml text/plain application/x-javascript image/jpeg image/gif image/png;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;
#charset koi8-r;
access_log /var/log/nginx/portal.access.log main;
location / {
root /nginx/html/gitegg_portal;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /gitegg-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://172.17.0.1:8080/;
}
}
4. Instructions for writing deployment scripts
- Define input parameters. You can pass parameters into the script through Jenkins tasks. We have defined the following 7 parameters:
container_name=portal-server: Container name
image_name=portal-server: Image name
version=latest: Image version
portal_port=80: Host Host port mapping
server_port=80: Service port in the container
portal_ssl_port=443: Host port mapping
serve_sslr_port=443: Service port in the container - Check the parameters to see if no parameters have been passed in. You can judge based on your actual situation. For example, which parameters must be passed in? Set the number of parameters to no less than a certain number.
echo "param validate"
if [ $# -lt 1 ]; then
echo "you must use like this : ./publish_docker_portal.sh <container_name> <image_name> <version> [portal port] [server port] [portal ssl port] [server ssl port]"
exit
fi
- Input parameter assignment. If there are parameters passed in, the service parameters will be taken. If no parameters are passed in, the default values will be taken.
if [ "$1" != "" ]; then
container_name="$1"
fi
echo "container_name=" $container_name
if [ "$2" != "" ]; then
image_name="$2"
fi
if [ "$3" != "" ]; then
version="$3"
fi
echo "version=" $version
if [ "$4" != "" ]; then
portal_port="$4"
fi
echo "portal_port=" $portal_port
if [ "$5" != "" ]; then
server_port="$5"
fi
echo "server_port=" $server_port
if [ "$6" != "" ]; then
portal_ssl_port="$6"
fi
echo "portal_ssl_port=" $portal_ssl_port
if [ "$7" != "" ]; then
serve_sslr_port="$7"
fi
echo "serve_sslr_port=" $serve_sslr_port
- stop and delete the container
echo "执行docker ps"
docker ps
if [[ "$(docker inspect $container_name 2> /dev/null | grep $container_name)" != "" ]];
then
echo $container_name "容器存在,停止并删除"
echo "docker stop" $container_name
docker stop $container_name
echo "docker rm" $container_name
docker rm $container_name
else
echo $container_name "容器不存在"
fi
- stop and remove mirror
# 删除镜像
echo "执行docker images"
docker images
if [[ "$(docker images -q $image_name 2> /dev/null)" != "" ]];
then
echo $image_name '镜像存在,删除镜像'
docker rmi $(docker images -q $image_name 2> /dev/null) --force
else
echo $image_name '镜像不存在'
fi
- Back up the image package for this installation
#bak image
echo "bak image" $image_name
BAK_DIR=/opt/bak/docker/$image_name/`date +%Y%m%d`
mkdir -p "$BAK_DIR"
cp "/opt/tmp/portal-image.tar" "$BAK_DIR"/"$image_name"_`date +%H%M%S`.tar
- Execute the command to install the image package
echo "docker load" $image_name
docker load --input /opt/tmp/portal-image.tar
- Execute the run command
echo "docker run" $image_name
docker run -d -p $portal_port:$server_port -p $portal_ssl_port:$server_ssl_port --name=$container_name -e TZ="Asia/Shanghai" --restart=always -v /data/container/nginx/www:/var/www -v /data/container/nginx/logs:/var/log/nginx -v /data/container/nginx/etc:/etc/nginx -v /data/container/nginx/etc/nginx.conf:/etc/nginx/nginx.conf -v /etc/localtime:/etc/localtime -v /usr/share/zoneinfo/Asia/Shanghai:/etc/timezone -v /bxl/container/nginx/ssl:/nginx/ssl $image_name
- Delete the installation files. Since they have been backed up before, the temporary installation files will be deleted here.
echo "remove tmp " $image_name
rm -rf /opt/tmp/portal-image.tar
- Print the completed command
echo "Docker Portal is starting,please try to access $container_name conslone url"
- Complete installation and deployment script
container_name=portal-server
image_name=portal-server
version=latest
portal_port=80
server_port=80
portal_ssl_port=443
serve_sslr_port=443
echo "param validate"
if [ $# -lt 1 ]; then
echo "you must use like this : ./publish_docker_portal.sh <container_name> <image_name> <version> [portal port] [server port] [portal ssl port] [server ssl port]"
exit
fi
if [ "$1" != "" ]; then
container_name="$1"
fi
echo "container_name=" $container_name
if [ "$2" != "" ]; then
image_name="$2"
fi
if [ "$3" != "" ]; then
version="$3"
fi
echo "version=" $version
if [ "$4" != "" ]; then
portal_port="$4"
fi
echo "portal_port=" $portal_port
if [ "$5" != "" ]; then
server_port="$5"
fi
echo "server_port=" $server_port
if [ "$6" != "" ]; then
portal_ssl_port="$6"
fi
echo "portal_ssl_port=" $portal_ssl_port
if [ "$7" != "" ]; then
serve_sslr_port="$7"
fi
echo "serve_sslr_port=" $serve_sslr_port
echo "执行docker ps"
docker ps
if [[ "$(docker inspect $container_name 2> /dev/null | grep $container_name)" != "" ]];
then
echo $container_name "容器存在,停止并删除"
echo "docker stop" $container_name
docker stop $container_name
echo "docker rm" $container_name
docker rm $container_name
else
echo $container_name "容器不存在"
fi
# 删除镜像
echo "执行docker images"
docker images
if [[ "$(docker images -q $image_name 2> /dev/null)" != "" ]];
then
echo $image_name '镜像存在,删除镜像'
docker rmi $(docker images -q $image_name 2> /dev/null) --force
else
echo $image_name '镜像不存在'
fi
#bak image
echo "bak image" $image_name
BAK_DIR=/opt/bak/docker/$image_name/`date +%Y%m%d`
mkdir -p "$BAK_DIR"
cp "/opt/tmp/portal-image.tar" "$BAK_DIR"/"$image_name"_`date +%H%M%S`.tar
echo "docker load" $image_name
docker load --input /opt/tmp/portal-image.tar
echo "docker run" $image_name
docker run -d -p $portal_port:$server_port -p $portal_ssl_port:$server_ssl_port --name=$container_name -e TZ="Asia/Shanghai" --restart=always -v /data/container/nginx/www:/var/www -v /data/container/nginx/logs:/var/log/nginx -v /data/container/nginx/etc:/etc/nginx -v /data/container/nginx/etc/nginx.conf:/etc/nginx/nginx.conf -v /etc/localtime:/etc/localtime -v /usr/share/zoneinfo/Asia/Shanghai:/etc/timezone -v /bxl/container/nginx/ssl:/nginx/ssl $image_name
echo "remove tmp " $image_name
rm -rf /opt/tmp/portal-image.tar
echo "Docker Portal is starting,please try to access $container_name conslone url"
2. Create a new Jenkins configuration packaging task, package and deploy the NodeJS (Vue) image
1. Before creating a new task, install the Docker Pipeline plug-in, use the Pipeline pipeline task to build and deploy, and for information about installing the Jenkins plug-in, please see the previous article on deploying Jenkins.
2. After installing the plug-in, create a new pipeline task.
3. As in the previous task, select "Discard old builds" and set the maximum number of builds to keep to 5.
4. Pull down to the "Pipeline" configuration and select Pipeline script
The pipeline script is as follows:
node {
# 从gitlab下载代码
stage('Preparation') { // for display purposes
// Get some code from a GitHub repository
echo "checkout from GitLab"
checkout scmGit(branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'git_username', url: 'http://127.0.0.1:9091/test/test.git']])
}
# NodeJS打包
stage('Build NodeJS Vue') {
echo "build nodejs code"
nodejs('Node17') {
sh 'echo $PATH'
sh 'node -v'
sh 'pnpm -v'
sh 'pnpm install'
sh 'pnpm run build'
}
}
# 此处判断本机打包是否有容器,如果有的话需要删除
stage('Delete Old Docker Container') {
echo "delete docker container"
sh '''if [[ "$(docker inspect $container_name 2> /dev/null | grep $container_name)" != "" ]];
then
echo $container_name "容器存在,停止并删除"
echo "docker stop" $container_name
docker stop $container_name
echo "docker rm" $container_name
docker rm $container_name
else
echo $container_name "容器不存在"
fi'''
}
# 此处判断本机打包是否有镜像,如果有的话需要删除
stage('Delete Old Docker Image') {
echo "delete docker image"
sh '''if [[ "$(docker images -q gitegg-portal 2> /dev/null)" != "" ]];
then
echo gitegg-portal \'镜像存在,删除镜像\'
docker rmi $(docker images -q gitegg-portal 2> /dev/null) --force
else
echo gitegg-portal \'镜像不存在,创建镜像\'
fi'''
}
# Docker打包镜像,并保存为tar
stage('Build Docker Image') {
echo "start docker build portal code"
// Run the docker build
docker.build 'gitegg-portal'
echo "save docker images tar"
sh 'docker save -o portal-image.tar gitegg-portal'
}
# 删除安装在本机的Docker镜像,非tar包
stage('Delete New Docker Image') {
echo "delete docker image"
sh '''if [[ "$(docker images -q gitegg-portal 2> /dev/null)" != "" ]];
then
echo gitegg-portal \'镜像存在,删除镜像\'
docker rmi $(docker images -q gitegg-portal 2> /dev/null) --force
else
echo gitegg-portal \'镜像不存在,创建镜像\'
fi'''
}
# 将Docker镜像tar包发送到服务器并执行部署命令
stage('Send Docker Image') {
echo "send docker image"
sshPublisher(publishers: [sshPublisherDesc(configName: 'Test', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '/opt/script/publish_docker_portal.sh gitegg-portal gitegg-portal latest 8130 8130 4413 4413', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'portal-image.tar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
stage('Publish Results') {
echo "End Publish Portal"
}
}
12. Click Build Now on the left side of the task
- Build now
- Pipeline tasks can display stage views on the right
- View the build log: After clicking Build Now, a progress bar will appear below. Click the progress bar to enter the build log interface.