共计 7251 个字符,预计需要花费 19 分钟才能阅读完成。
Docker 和 Spring Boot 是十分风行的组合,咱们将利用 GitLab CI 的劣势,并在应用程序服务器上主动构建,推送和运行 Docker 镜像。
GitLab CI
Gitlab CI/CD 服务是 GitLab 的一部分,每当开发人员将代码推送到 GitLab 存储库时,它都会在所需的环境中构建,测试和存储最新的更改。
抉择 GitLab CI 的一些次要起因:
- 易于学习,应用和可扩大
- 保护容易
- 整合容易
- CI 齐全属于 GitLab 存储库的一部分
- 良好的 Docker 集成
- 镜像托管(Container registry)- 基本上是你本人的公有 Docker Hub
- 从老本上来说,GitLab CI 是一个很好的解决方案。每个月你有 2000 分钟的收费构建工夫,对于某些我的项目来说,这是入不敷出的
我把 Docker 的教程和文章整顿成了 PDF,关注微信关注号 Java 后端,回复 666 就能下载了。
为什么 GitLab CI 超过 Jenkins
这无疑是一个宽泛探讨的话题,然而在本文中,咱们将不深入探讨该话题。GitLab CI 和 Jenkins 都有长处和毛病,它们都是性能十分弱小的工具。
那为什么抉择 GitLab?
如前所述,CI 齐全是 GitLab 存储库的一部分,这意味着不须要装置它,并且保护起码。yml 脚本实现后,你便或多或少地实现了所有工作。
对于小型我的项目应用 Jenkins,你就必须本人设置和配置所有内容。通常,你还须要一台专用的 Jenkins 服务器,这也须要额定的老本和保护。
应用 GitLab CI 前提条件
如果须要与这些前提条件无关的任何帮忙,我已提供相应指南的链接。
- 你曾经在 GitLab 上推送了 Spring Boot 我的项目
- 你已在应用程序服务器上安装了 Docker(指南)
- 你具备 Docker 镜像的镜像托管(在本指南中将应用 Docker Hub)
- 你曾经在服务器上生成了 SSH RSA 密钥(指南)
你要创立什么
你将创立Dockerfile 和.gitlab-ci.yml, 它们将主动用于:
- 构建应用程序 Jar 文件
- 构建 Docker 镜像
- 将镜像推送到 Docker 存储库
- 在应用程序服务器上运行镜像
根本我的项目信息
本文的 Spring Boot 应用程序是通过 Spring Initializr 生成的。这是一个基于 Java 8 或 Java11 构建的 Maven 我的项目。前面,咱们将介绍 Java 8 和 Java 11 对 Docker 镜像有什么影响。
Docker 文件
让咱们从 Dockerfile 开始。
FROM maven:3.6.3-jdk-11-slim AS MAVEN_BUILD
#FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD FOR JAVA 8
ARG SPRING_ACTIVE_PROFILE
MAINTAINER Jasmin
COPY pom.xml /build/
COPY src /build/src/
WORKDIR /build/
RUN mvn clean install -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE && mvn package -B -e -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE
FROM openjdk:11-slim
#FROM openjdk:8-alpine FOR JAVA 8
WORKDIR /app
COPY --from=MAVEN_BUILD /build/target/appdemo-*.jar /app/appdemo.jar
ENTRYPOINT ["java", "-jar", "appdemo.jar"]
与该 Dockerfile 相干的常识很少。
Java 版本
让咱们从 Docker 的角度看一下 Java 8 和 11 之间的区别。长话短说:这是 Docker 镜像的大小和部署工夫。
基于 Java 8 构建的 Docker 镜像将显著小于基于 Java 11 的镜像。这也意味着 Java 8 我的项目的构建和部署工夫将更快。
Java 8- 构建工夫:约 4 分钟,镜像大小为 约 180 MB
Java 11- 构建工夫:约 14 分钟,镜像大小约为 480 MB
留神: 在理论利用中,这些数字可能会有所不同。
Docker 镜像
正如在后面示例中曾经看到的那样,因为 Java 版本的缘故,咱们在应用程序镜像大小和构建工夫方面存在微小差别。其背地的理论起因是在 Dockerfile 中应用了 Docker 镜像。
如果咱们再看一下 Dockerfile,那么Java 11 镜像很大的真正起因是因为它蕴含了没有通过验证 / 测试的 open-jdk:11 镜像的 Alpine 版本。
如果你不相熟 OpenJDK 镜像版本,倡议你浏览 OpenJDK Docker 官网文档。在这里,你能够找到无关每个 OpenJDK 版本的镜像的阐明。
备注:动静的变量
在ENTRYPOINT
中,与环境相干的属性,咱们只能写死,如下:
ENTRYPOINT [“java”,“-Dspring.profiles.active = development”,“-jar”,“appdemo.jar”]
为了使它动静,你心愿将其简略地转换为:
ENTRYPOINT [“java”,“-Dspring.profiles.active = $ SPRINT_ACTIVE_PROFILE”,“-jar”,“appdemo.jar”]
以前,这是不可能的,然而侥幸的是,这将在.gitlab-ci.yml 中通过 ARG SPRING_ACTIVE_PROFILE 修复。
gitlab-ci.yml
在编写此文件之前,要筹备的货色很少。基本上,咱们想要实现的是,只有推送代码,就会在相应的环境上主动部署。
创立.env 文件和分支
咱们首先须要创立蕴含与环境相干的分支和.env 文件。每个分支实际上代表咱们的应用程序将运行的环境。
咱们将在三个不同的环境中部署咱们的应用程序:开发,测试和生产(development, QA, and production)。这意味着咱们须要创立三个分支。
咱们的 dev,QA 和 prod 应用程序将在不同的服务器上运行,并且将具备不同的 Docker 容器标签,端口和 SSH 密钥。这就要求咱们的gitlab-ci.yml 文件将要是动静的,通过为咱们领有的每个环境创立.env 文件来解决该问题。
.develop.env .qa.env .master.env
重要阐明: 命名这些文件时,有一个简略的规定:应用 GitLab 分支来命名,因而文件名应如下所示:。$ BRANCH_NAME.env
例如,这是.develop.env 文件。
export SPRING_ACTIVE_PROFILE='development'
export DOCKER_REPO='username/demo_app:dev'
export APP_NAME='demo_app_dev'
export PORT='8080'
export SERVER_IP='000.11.222.33'
export SERVER_SSH_KEY="$DEV_SSH_PRIVATE_KEY"
与.env 文件无关的重要阐明:
SPRING_ACTIVE_PROFILE:不言自明,咱们要应用哪些 Spring 应用程序属性。DOCKER_REPO:这是 Docker 镜像的存储库;在这里,咱们惟一须要留神的是 Docker image TAG,对于每种环境,咱们将应用不同的标签,这意味着咱们将应用dev,qa 和prod 标签。
咱们的 Docker 核心看起来像这样。
如你所见,存在一个带有三个不同标签的存储库,每当将代码推送到 GitLab 分支上时,每个标签(应用程序版本)都会被更新。
- APP_NAME: 此属性十分重要,它是对容器的命名。如果你未设置此属性,则 Docker 将为你的容器随机命名。这可能是一个问题,因为你将无奈以洁净的形式进行运行容器。
- 端口:这是咱们心愿运行 Docker 容器的端口。
- SERVER_IP:应用程序应用的服务器 IP。通常,每个环境都将位于不同的服务器上。
- SERVER_SSH_KEY:这是咱们曾经在每台服务器上生成的 SSH 密钥。
$DEV_SSH_PRIVATE_KEY
实际上是来自 GitLab 存储库的变量。
创立 GitLab 变量
最初须要做的是创立 GitLab 变量。
关上你的 GitLab 存储库,而后转到:Settings -> CI/CD。在 Variables局部中,增加新变量:
- DOCKER_USER:用于拜访 Docker Hub 或其余镜像托管的用户名
- DOCKER_PASSWORD: 用于拜访镜像托管的明码
- $ ENV_SSH_PRIVATE_KEY: 先前在服务器上生成的 SSH 私钥。
SSH KEY 的重要阐明:
你须要复制残缺的密钥值,包含:—– BEGIN RSA PRIVATE KEY —– 和 —– END RSA PRIVATE KEY —–
最初,你的 GitLab 变量应如下所示。
创立 gitlab-ci.yml 文件
最初,让咱们创立将所有内容放在一起的文件。
services:
- docker:19.03.7-dind
stages:
- build jar
- build and push docker image
- deploy
build:
image: maven:3.6.3-jdk-11-slim
stage: build jar
before_script:
- source .${CI_COMMIT_REF_NAME}.env
script:
- mvn clean install -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE && mvn package -B -e -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE
artifacts:
paths:
- target/*.jar
docker build:
image: docker:stable
stage: build and push docker image
before_script:
- source .${CI_COMMIT_REF_NAME}.env
script:
- docker build --build-arg SPRING_ACTIVE_PROFILE=$SPRING_ACTIVE_PROFILE -t $DOCKER_REPO .
- docker login -u $DOCKER_USER -p $DOCKER_PASSWORD docker.io
- docker push $DOCKER_REPO
deploy:
image: ubuntu:latest
stage: deploy
before_script:
- '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 *ntStrictHostKeyChecking nonn" > ~/.ssh/config
- source .${CI_COMMIT_REF_NAME}.env
script:
- ssh root@$SERVER "docker login -u $DOCKER_USER -p $DOCKER_PASSWORD docker.io; docker stop $APP_NAME; docker system prune -a -f; docker pull $DOCKER_REPO; docker container run -d --name $APP_NAME -p $PORT:8080 -e SPRING_PROFILES_ACTIVE=$SPRING_ACTIVE_PROFILE $DOCKER_REPO; docker logout"
让咱们解释一下这里产生了什么:
services:
- docker:19.03.7-dind
这是一项服务,使咱们能够在 Docker 中应用 Docker。在 Docker 中运行 Docker 通常不是一个好主见,然而对于此用例来说,这是齐全能够的,因为咱们将构建镜像并将其推送到存储库中。
stages:
- build jar
- build and push docker image
- deploy
对于每个 gitlab-ci.yml 文件,必须首先定义执行步骤。脚本将依照步骤定义的程序执行。
在每个步骤,咱们都必须增加以下局部:before_script: – source .${CI_COMMIT_REF_NAME}.env
这只是事后加载之前创立的 env. files, 文件。依据正在运行的分支来主动注入变量。(这就是为什么咱们必须应用分支名称来命名.env 文件的起因)
这些是咱们部署过程中的执行步骤。
如你所见,,有三个带有绿色复选标记的圆圈,这示意所有步骤均已胜利执行。
build:
image: maven:3.6.3-jdk-11-slim
stage: build jar
before_script:
- source .${CI_COMMIT_REF_NAME}.env
script:
- mvn clean install -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE && mvn package -B -e -Dspring.profiles.active=$SPRING_ACTIVE_PROFILE
artifacts:
paths:
- target/*.jar
这是执行第一步骤代码的一部分,构建了一个 jar 文件,该文件能够下载。这实际上是一个可选步骤,仅用于演示构建 jar 并从 GitLab 下载它是如许容易。
第二步骤是在 Docker 存储库中构建并推送 Docker 镜像。
docker build:
image: docker:stable
stage: build and push docker image
before_script:
- source .${CI_COMMIT_REF_NAME}.env
script:
- docker build --build-arg SPRING_ACTIVE_PROFILE=$SPRING_ACTIVE_PROFILE -t $DOCKER_REPO .
- docker login -u $DOCKER_USER -p $DOCKER_PASSWORD docker.io
- docker push $DOCKER_REPO
这一步骤,咱们不得不应用 docker:19.03.7-dind 服务。如你所见,咱们应用的是最新的稳固版本的 Docker,咱们只是在为适当的环境构建镜像,而后对 Dockerhub 进行身份验证并推送镜像。
咱们脚本的最初一部分是:
deploy:
image: ubuntu:latest
stage: deploy
before_script:
- '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 *ntStrictHostKeyChecking nonn" > ~/.ssh/config
- source .${CI_COMMIT_REF_NAME}.env
script:
- ssh root@$SERVER "docker stop $APP_NAME; docker system prune -a -f; docker pull $DOCKER_REPO; docker container run -d --name $APP_NAME -p $PORT:8080 -e SPRING_PROFILES_ACTIVE=$SPRING_ACTIVE_PROFILE $DOCKER_REPO"
在此步骤中,咱们应用 Ubuntu Docker 镜像,因而咱们能够 SSH 到咱们的应用程序服务器并运行一些 Docker 命令。其中的局部代码 before_script
大部分来自官网文档,然而,当然,咱们能够对其进行一些调整以满足咱们的需要。为不对私钥进行验证,增加了以下代码行:
- echo -e "Host *ntStrictHostKeyChecking nonn" > ~/.ssh/config
你也能够参考指南验证私钥。如你在最初阶段的脚本局部中所见,咱们正在执行一些 Docker 命令。
- 进行正在运行的 Docker 容器:
docker stop $APP_NAME
。(这就是咱们要在.env 文件中定义APP_NAME
的起因) - 删除所有未运行的 Docker 镜像
docker system prune -a -f
。这实际上不是强制性的,但我想删除服务器上所有未应用的镜像。 - 拉取最新版本的 Docker 镜像(该镜像是在上一个阶段中构建并推送的)。
- 最初,应用以下命令运行 Docker 镜像:
docker container run -d --name $APP_NAME -p $PORT:8080 -e SPRING_PROFILES_ACTIVE=$SPRING_ACTIVE_PROFILE $DOCKER_REPO
译文链接:https://dzone.com/articles/au…
翻译:https://blog.csdn.net/weixin_…