Bootstrap

五. GitLab-CI/CD-实战:spring-boot项目

1. 环境准备

  • 生产环境docker;
  • maven
  • DK1.8
  • gitlab 以及gitlab-runner

总:根据之前的几篇博客,配置好对应的runner,这里 以 test_spring_boot 为runner tag为例说明;

2. 项目目录

在项目跟目录下,创建如下几个文件:

.feature.env --测试环境变量配置文件

.master.env--生产环境变量配置文件

.gitlab-ci.yml--CI/CD核心配置文件

Dockerfile--用于构建Java镜像的文件

如下图所示(注意每个文件前面的点):

3. 文件详细内容解析

a. .feature.env:

#你的spring启动环境
export SPRING_ACTIVE_PROFILE='test'
#推送docker镜像的服务器地址
export DOCKER_REPO_PUSH='192.168.1.26:5000/spring_boot_test'
#拉取docker镜像的服务器地址
export DOCKER_REPO_PULL='192.168.1.26:5000/spring_boot_test'
#Java服务地址
export SERVER_IP='192.168.1.55'
#登录服务器时,用到的key(在gitlab中配置的参数)
export SSH_PRIVATE_KEY="$DEV_SSH_PRIVATE_KEY"

 b. .master,env:具体内容同上,注意,生产环境无外网,所以通过跳板进行 登录到部署服务的服务器:

export SPRING_ACTIVE_PROFILE='prod'
export DOCKER_REPO_PUSH='docker镜像服务器外网地址:6500/spring_boot_test'
export DOCKER_REPO_PULL='docker镜像服务器内网地址:6500/spring_boot_test'
export SERVER_IP='部署服务服务器内网地址'
export SPRINGBOARD_IP='跳板机器外网地址'
export SSH_PRIVATE_KEY="$MASTER_SSH_PRIVATE_KEY"

c . Dockerfile:

FROM openjdk:8
MAINTAINER test
ARG JAR_PATH
WORKDIR /app
COPY target/lib /app/lib
COPY $JAR_PATH /app/
EXPOSE 8283
ENTRYPOINT ["java","-jar","-Duser.timezone=GMT+08","-Dloader.path=lib","spring_boot_test.jar"]

d. .gitlab-ci.yml:

# 该文件,会根据你的参数文件,判定分支上有变动,则运行
services:
  - docker:20.10.6-dind
variables:
  MAVEN_OPTS: "-Dmaven.repo.local=/root/.m2/repository"
# 定义阶段
stages:
  - build jar
  - build and push docker image
  - deploy

# 全局缓存-缓存打包完成的所有jar包
cache: &global_cache
  key: ${CI_COMMIT_REF_NAME}"spring_boot_test"
  paths:
    - .m2/repository/
    - target/lib/*.jar

#tags 标记的是使用哪个runner
build:
  image: maven:3.8.1-jdk-8-slim
  stage: build jar
  cache:
    # 继承全局缓存配置
    <<: *global_cache
  tags:
    - test_spring_boot
  #判断提交分支是否为feature,如果是feature,直接截取分支名的 feature(原分支名:feature/v1.0.0-**)
  before_script:
    - source .${CI_COMMIT_REF_NAME:0:7}.env
  # package时,关闭单元测试,不然会比较耗时
  script:
    - mvn clean && mvn package -B -e -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE -Dmaven.test.skip=true;
  artifacts:
    paths:
      - target/*.jar
    expire_in: 3600 seconds

#docker构建
docker build and push:
  image: docker:stable
  stage: build and push docker image
  tags:
    - test_spring_boot
  before_script:
    - source .${CI_COMMIT_REF_NAME:0:7}.env
  script:
    - docker build --build-arg JAR_PATH=target/*.jar -t $DOCKER_REPO_PUSH .
    - docker push $DOCKER_REPO_PUSH
  after_script:
    - source .${CI_COMMIT_REF_NAME:0:7}.env
    - docker rmi $DOCKER_REPO_PUSH

#部署
deploy:
  image: ubuntu:latest
  stage: deploy
  tags:
    - test_spring_boot
  before_script:
    - source .${CI_COMMIT_REF_NAME:0:7}.env
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
    - source .${CI_COMMIT_REF_NAME:0:7}.env
  script:
    - >
      if [ "$CI_COMMIT_REF_NAME" == "master" ]; then
        ssh -J root@$SPRINGBOARD_IP root@$SERVER_IP "docker stop spring_boot_test;
        docker system prune -a -f;
        docker pull $DOCKER_REPO_PULL;
        docker container run -d \
        --name spring_boot_test\
        -p 8283:8283 \
        -e SPRING_PROFILES_ACTIVE=$SPRING_ACTIVE_PROFILE $DOCKER_REPO_PULL;
        docker logout";
      else
        ssh root@$SERVER_IP "docker stop spring_boot_test;
        docker system prune -a -f;
        docker pull $DOCKER_REPO_PULL;
        docker container run -d \
        --name spring_boot_test\
        -p 8283:8283 \
        -e SPRING_PROFILES_ACTIVE=$SPRING_ACTIVE_PROFILE $DOCKER_REPO_PULL;
        docker logout";
      fi

说明:本项目中,打包时,是吧lib包单独打出来的,没有放到jar包中,避免jar包过大;

          <plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>3.1.1</version>
				<executions>
					<execution>
						<phase>prepare-package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>target/lib</outputDirectory>
						</configuration>
					</execution>
				</executions>
			</plugin>

4. 汇总

完成上述配置,当你提交代码时,就会在你的gitlab项目下的ci/cd看到任务的运行了:

 在每个环节,可以点击进去,看到相应的日志,包括运行不通过时,可以查看相关报错信息:

 5. 常见问题

  • dial tcp: lookup docker on 192.168.1.1:53: no such host错误。

    This error occurs with docker-based gitlab runners such as the one we’re that are configured using a docker executor. The error message means that the inner docker container doesn’t have a connection to the host docker daemon.

    解决:将/etc/gitlab-runner/config.toml中对应的[runners.docker]节点设置privileged = true,增加卷映射volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"][或|并]在.gitlab-ci.yml的job定义中增加services: - docker:dind;

  • Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?错误

    解决:增加卷映射volumes = ["/certs/client", "/cache"],然后在.gitlab-ci.yml中增加变量DOCKER_TLS_CERTDIR: "/certs"

  • 拉取代码时提示warning: failed to remove xxxx: Permission denied

    简单粗暴地编辑/etc/passwd,将gitlab-runner账号对应的uid:gid改为0:0(和root一样)。

以上,就是gitlab-CI/CD在spring-boot项目中的应用,后续会上传相关代码,请持续关注!

你的努力,终将成为你最有力的资本!

;