惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
有赞技术团队
有赞技术团队
T
The Blog of Author Tim Ferriss
F
Fortinet All Blogs
D
DataBreaches.Net
F
Full Disclosure
腾讯CDC
博客园 - 【当耐特】
MyScale Blog
MyScale Blog
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
Last Week in AI
Last Week in AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
爱范儿
爱范儿
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
SegmentFault 最新的问题
The Register - Security
The Register - Security
WordPress大学
WordPress大学
博客园 - 聂微东
雷峰网
雷峰网
J
Java Code Geeks
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Privacy International News Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
A
Arctic Wolf
Scott Helme
Scott Helme
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tor Project blog
博客园 - 三生石上(FineUI控件)
Know Your Adversary
Know Your Adversary
AWS News Blog
AWS News Blog
G
Google Developers Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
CERT Recently Published Vulnerability Notes
O
OpenAI News
Project Zero
Project Zero
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Application and Cybersecurity Blog
Application and Cybersecurity Blog
云风的 BLOG
云风的 BLOG
N
News and Events Feed by Topic
MongoDB | Blog
MongoDB | Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Microsoft Security Blog
Microsoft Security Blog
Cisco Talos Blog
Cisco Talos Blog
P
Palo Alto Networks Blog
Schneier on Security
Schneier on Security

Loong's Blog

Trip to Changchun National Day Records in 2025 Long Term Planning Remote Networking for Online Games Summary of 2024 Teamwork Using Git Use DDNS To Access Intranet Devices Development Environment Management Tools About Blog Migration Two-month Life Experience In Hefei Crack The Optical Modem Superuser Password Archives Develop Essay Practice Teamwork Tool Toss Links Search Journal Network
Automated Build Via Jenkins
2023-02-16 · via Loong's Blog

Featured image of post Automated Build Via Jenkins

Automated Build Via Jenkins

 Continuing on from the previous experiment, we will implement a one-click deployment project through Jenkins.

Project Overview

 The project is a frontend and backend separation project. The backend is a multimodule project using SpringBoot, and its structure is as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
+---backend             # Backend 
|   +---src
|   \---target
+---frontend            # Frontend
|   +---dist
|   \---src
+---others              # Other Backend Modules
|   +---mqtt
|       +---src
|       \---target
+---data                # Database Config
|   +---conf
|   +---init
|   \---sql
+---conf                # Config
|   +---emqx
|   \---nginx
+---dockerfile
+---shell               # Scripts To Help Build Images
\---docker-compose.yml

Problems

 For convenience, the automated build process is done in a Jenkins container. With Docker, we don’t have to spend a lot of time configuring the environment. Next, let me introduce the problems encountered.

Commends not found

 Through the logs, I observed that the npm command could not be found. Because I manged the Node environment through nvm and didn’t configure the PATH variable, npm command always failed to execute.

 Finally I mounted the nvm installation directory and configuration to the Jenkins container. When the container is started, first make the configuration file in the /etc/profile.d directory take effect, and then switch the node environment. The Pipeline I wrote is as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
stage('build-frontend') {
    steps {
        dir("./frontend") {
            sh '''
                source /etc/profile.d/nvm.sh
                nvm use 16.15.0
                npm cache clean –force
                npm cache verify
                if [ -f dist ]; then rm dist -rf; fi;
                pnpm config get registry
                pnpm config set registry https://registry.npmmirror.com/
                pnpm install
                pnpm run build:prod
                '''
        }
    }
}

Note: Errors such as commands not found can be solved by mounting its installation directory and making the configuration effective.

How to deploy remotely via ssh

 After configuring the private key on the global credentials, it is best to deploy remotely in Pipeline through a plugin (SSH Pipeline Steps). You can refer to my configuration.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
steps {
    withCredentials(bindings: [ \
            sshUserPrivateKey(credentialsId: 'private-key',
            keyFileVariable: 'primaryKeyVar',
            passphraseVariable: 'pwdVar',
            usernameVariable: 'userVar')]) {
        script {
            def remote = [:]
            remote.name = '192.168.137.2'
            remote.host = '192.168.137.2'
            remote.user = userVar
            remote.identityFile = primaryKeyVar
            remote.allowAnyHosts = true
            stage('Remote SSH') {
                sshCommand remote: remote, command: "mkdir -p ${REMOTE_WORKDIR}/frontend"
                // Frontend Packaging File
                sshPut remote: remote, from: "./frontend/dist", into: "${REMOTE_WORKDIR}/frontend"
                // Show All Files Transferred
                sshCommand remote: remote, command: "ls -lrt ${REMOTE_WORKDIR}/**"
            }
        }
    }
}

How to control the startup order of services

 When writing docker-compose.yml, if you need to control the startup order, the depends_on field alone is not enough. It only controls the startup order, but doesn’t guarantee that the next service will be started only after the service is successfully started.

 I referred to many articles and found a solution. By mounting wait-for-it.sh, write a script to replace the container’s entrypoint. If you have any question, you can also refer to [this article] (https://www.cnblogs.com/wang_yb/p/9400291.html).

 I downloaded the script called *wait-for-it from [https: //github.com/vishnubob/wait-for-it](https: //github.com/vishnubob/wait-for-it). I renamed it entrypoint.sh and put it in the shell directory. Below is part of the docker-compose configuration.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
service:
    backend:
        build:
            context: .
            dockerfile: dockerfile/backend-Dockerfile
        image: backend_app
        container_name: prod-backend-app
        ports:
            - "13245:13245"
        environment:
            TZ: Asia/Shanghai
            PORT: 13245
            PROFILE: prod
        volumes:
            - ./shell/entrypoint.sh:/entrypoint.sh
        depends_on:
            - emq
            - influx

 The Dockerfile of the service called backend is renamed backend-Dockerfile and is placed in the dockerfile directory. Since the backend service relies on the mysql and redis services, the content of its Dockerfile is as follows:

1
2
3
4
5
FROM openjdk:8-jdk
ADD backend/target/*.jar /app.jar
CMD bash /entrypoint.sh mysqldb:3306 -t 30 -- echo "mysql started" \
    && bash /entrypoint.sh redisdb:6379 -t 20 -- echo "redisdb started" \
    && java -jar -Dfile.encoding=utf-8 -Dserver.port=${PORT} -Dspring.profiles.active=${PROFILE} /app.jar

How to configure Emqx

 First of all, the version of Emqx is 4.4.2.

 I referred to the official document and configured the container through environment variables. The emq_web_hook plugins is effective but the emq_http_auth plugin is always ineffective. I tried various methods but failed. At last, solved it by mounting its configuration file.

 You can refer to my docker-compose configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
service:
    emq:
        user: root
        restart: always
        container_name: prod-emqx
        image: emqx/emqx:4.4.2
        ports:
            - "18083:18083"
            - "1883:1883"
            - "8083:8083"
            - "8084:8084"
            - "8883:8883"
        volumes:
            - /etc/localtime:/etc/localtime
            - /root/docker/emqx/log:/opt/emqx/log
            - ./conf/emqx/emqx_auth_http.conf:/opt/emqx/etc/plugins/emqx_auth_http.conf
            - ./conf/emqx/emqx_web_hook.conf:/opt/emqx/etc/plugins/emqx_web_hook.conf
        environment:
            EMQX_ALLOW_ANONYMOUS: false # allow_anonymous
            EMQX_LOADED_PLUGINS: "emqx_management,emqx_auth_http,emqx_dashboard,emqx_web_hook"
            EMQX_DASHBOARD__DEFAULT_USER__LOGIN: root
            EMQX_DASHBOARD__DEFAULT_USER__PASSWORD: 12345
        networks:
            app_net:
                ipv4_address: 172.31.0.10
        depends_on:
            - auth
        links:
            - auth

The frontend can’t access the backend container’s interface

 Many articles introduce the use of nginx as the base image to build the front-end image.

 I referred this article and wrote the nginx configuration file, the example is as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
server {
    listen       13246;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    #Location配置
    location /api/ {
        rewrite  /api/(.*)  /$1  break;
        proxy_pass http://backend:13245;
    }
}

 Since I had not learned nginx in depth, I encountered various problems. After repeated attempts, I finally achieved my expectations.

Additional Notes

 The project is based on Vue3 and SpringBoot, and uses Jenkins container for automated construction and deployment. For convenience and space saving, the best way is to install common tool software on the host machine and then mount it into the container.

 Next I will add some installation dependencies

  1. Install Docker
1
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
  1. Install jdk8
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
rm /tmp/jdk*.tar.gz -f
wget https://repo.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.tar.gz -P /tmp
ls -lht /tmp/ | grep jdk
mkdir -p /usr/local/java/
tar -zxf /tmp/jdk-8u202-linux-x64.tar.gz -C /usr/local/java/ && ls /usr/local/java/ -l
# Add environment jdk1.8 environment variables
cat > /etc/profile.d/java.sh <<EOF
export JAVA_HOME=/usr/local/java/jdk1.8.0_202
export JRE_HOME=\${JAVA_HOME}/jre
export CLASSPATH=.:\${JAVA_HOME}/lib:\${JRE_HOME}/lib
export PATH=\${JAVA_HOME}/bin:\$PATH
EOF

source /etc/profile.d/java.sh
ln -s ${JAVA_HOME}/bin/java /usr/bin/java
java -version
  1. Install Maven
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
maven_version=3.9.0
rm /tmp/*maven*.tar.gz -rf
#wget https://dlcdn.apache.org/maven/maven-3/3.9.0/binaries/apache-maven-3.9.0-bin.tar.gz -P /tmp
wget https://mirrors.aliyun.com/apache/maven/maven-3/3.9.0/binaries/apache-maven-3.9.0-bin.tar.gz -P /tmp
ls -lht /tmp/ | grep maven
mkdir -p /usr/local/maven/
tar -zxf /tmp/apache-maven-*.tar.gz -C /usr/local/maven/ && ls /usr/local/maven/ -l
# Add Maven environment variables
cat > /etc/profile.d/maven.sh << EOF
export MAVEN_VERSION="${maven_version}"
export M2_HOME=/usr/local/maven/apache-maven-\${MAVEN_VERSION}
export MAVEN_HOME=/usr/local/maven/apache-maven-3.9.0
export PATH=\${MAVEN_HOME}/bin:\${PATH}
EOF
chmod +x /etc/profile.d/maven.sh
source /etc/profile.d/maven.sh
mvn -version
  1. Install nvm
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
nvm_version=0.39.3
rm /tmp/v${nvm_version}.tar.gz -rf
wget https://github.com/nvm-sh/nvm/archive/refs/tags/v${nvm_version}.tar.gz -P /tmp
ls -lht /tmp/ | grep "v${nvm_version}.tar.gz"
mkdir -p /usr/local/nvm/
tar -zxf /tmp/v${nvm_version}.tar.gz -C /usr/local/nvm/ && ls /usr/local/nvm/ -l
# Add nvm environment variables
cat << EOF  > /etc/profile.d/nvm.sh
export NVM_VERSION="${nvm_version}"
export NVM_DIR="/usr/local/nvm/nvm-\${NVM_VERSION}"
[ -s "\$NVM_DIR/nvm.sh" ] && \. "\$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "\$NVM_DIR/bash_completion" ] && \. "\$NVM_DIR/bash_completion"
EOF

chmod +x /etc/profile.d/nvm.sh
source /etc/profile.d/nvm.sh
nvm version
  1. Install docker-compose

 It is recommended to download docker-compose from github official website, some mirror website packages are too old.

1
2
3
curl -L https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose -v

Summary

 By applying the newly learned Jenkins automation technology to the project, time can be greatly saved. Operation and maintenance do not have to repeatedly deploy manually, and testing becomes a part of development. Only test scripts need to be written. Each time the developer submits code, the test scripts will be automatically executed and then deployed to the remote via ssh. From the traditional stage-by-stage development, where a stage cannot be skipped directly, development can now be quickly tested and put into production to get feedback, doubling efficiency. Perhaps this is why the CI/CD concept and tools are popular.

References

  1. https://github.com/vishnubob/wait-for-it

  2. https://www.cnblogs.com/wang_yb/p/9400291.html

  3. https://juejin.cn/post/6844903837774397447

  4. https://juejin.cn/post/7095729903684829191


2023-02-16 First Update

2023-02-26 Add Dependent Installation configuration

2024-07-06 Support English