AWS CodePipeline 将 Spring Boot 应用程序部署到 Elastic BeansTalk

Posted

技术标签:

【中文标题】AWS CodePipeline 将 Spring Boot 应用程序部署到 Elastic BeansTalk【英文标题】:AWS CodePipeline deploy Spring Boot application to Elastic BeansTalk 【发布时间】:2020-07-05 12:15:10 【问题描述】:

我用 3 个步骤为 SpringBoot Java 应用程序构建了一个简单的 CodePipeline:

来源:从 GitHub 获取源代码 构建:jar 文件 部署:到 AWS Elastic Beanstalk 实例

1 和 2 步骤成功通过,而 Deploy 步骤失败。我在 Elastic Beanstalk 日志中看到的唯一错误:

01_configure_application.sh] : Activity execution failed, because: Executing: /usr/bin/unzip -o -d /var/app/staging /opt/elasticbeanstalk/deploy/appsource/source_bundle
  FileMagic v0.7.1: compiled magic version [5.21] does not match with shared library magic version [5.37]
  Archive:  /opt/elasticbeanstalk/deploy/appsource/source_bundle
    inflating: /var/app/staging/microservices/my-service/target/my-service.jar  
  Unable to launch application as the source bundle does not contain either a file named application.jar or a Procfile.
  Unable to launch application as the source bundle does not contain either a file named application.jar or a Procfile. (ElasticBeanstalk::ExternalInvocationError)
caused by: Executing: /usr/bin/unzip -o -d /var/app/staging /opt/elasticbeanstalk/deploy/appsource/source_bundle
  FileMagic v0.7.1: compiled magic version [5.21] does not match with shared library magic version [5.37]
  Archive:  /opt/elasticbeanstalk/deploy/appsource/source_bundle
    inflating: /var/app/staging/microservices/my-service/target/my-service.jar  
  Unable to launch application as the source bundle does not contain either a file named application.jar or a Procfile.
  Unable to launch application as the source bundle does not contain either a file named application.jar or a Procfile. (Executor::NonZeroExitStatus)

我的构建规范:

build:
  commands:
      - mvn -P ci --settings settings.xml install -DskipTests
artifacts:
  files:
     - microservices/my-service/target/my-service.jar

如果我使用 AWS Web Interface 将这个 jar 直接部署到 AWS Elastic Beanstalk,它会完美运行。

请帮帮我。 我已准备好按需共享任何其他配置。

【问题讨论】:

【参考方案1】:

虽然 Denys 的回答是正确的,但我认为它并不能清楚地解释问题。

artifacts 指令下输出时,工件必须是***或最多一个深度目录

例如使用gradle的spring项目默认是在执行bootJar任务后输出到<project root>/build/libs/<artifact name>.jar

直觉上你会这样定义:

version: 0.2

phases:
  install:
    runtime-versions:
      java: corretto8
  build:
    commands:
      # bootJar task outputs to build/libs/<name>.jar
      - ./gradlew bootJar
artifacts:
  files:
      - build/libs/<name>.jar

此构建将成功并将压缩的工件上传到 S3。解压后你会得到:

build/libs/&lt;name&gt;.jar。您可以通过从 s3 下载工件并自己解压缩来确认这一点(就像弹性 beanstalk 在 vm 中所做的那样)。

因此,当弹性 beanstalk 尝试部署它时,它会失败,因为它会查找*** &lt;name&gt;.jar最多 somedir/&lt;name&gt;.jar,您会收到相当神秘的错误消息

由于源包不包含名为 application.jar 或 Procfile 的文件,因此无法启动应用程序。

它很神秘,因为它意味着必须将工件命名为 application.jar 或者必须添加 Procfile。这些都不是真的

所以解决方案围绕着使该 jar 文件成为***文件。你可以:

将构建工具中的输出工件定义为将其置于顶层(不理想)

build 阶段添加第二个命令,将 jar 文件移到顶层,例如:

version: 0.2

phases:
  install:
    runtime-versions:
      java: corretto8
  build:
    commands:
      # bootJar task outputs to build/libs/<name>.jar
      - ./gradlew bootJar
      # move the jar (by wildcard, agnostic to its name) to top level app.jar
      - mv build/libs/*.jar app.jar
artifacts:
  files:
      # publish the now top level app.jar as the artifact
      - app.jar

最合适的解决方案是使用post_build 指令,该指令专为清理/重组步骤而设计,如下所示:

version: 0.2

phases:
  install:
    runtime-versions:
      java: corretto8
  build:
    commands:
      # bootJar task outputs to build/libs/<name>.jar
      - ./gradlew bootJar
  post_build:
    commands:
      # move the jar (by wildcard, agnostic to its name) to top level app.jar
      - mv build/libs/*.jar app.jar
artifacts:
  files:
      # publish the now top level app.jar as the artifact
      - app.jar

解压后你会得到app.jar ***和弹性豆茎很高兴!请注意app.jarbuild/libs 是任意的,设置它们对您和您的项目有意义。重要的是artifacts.files 是一个***jar 文件。弹性豆茎会处理剩下的事情

如果您是 CP 新手或有一个简单的项目,则无需按照其他类似问题中的建议使用 config.yml 覆盖或添加 Procfile

希望这对其他人有帮助。

【讨论】:

惊人的答案,对我帮助很大,谢谢!【参考方案2】:

问题出在工件的子文件夹中,无法像在我的 Buildspec 中那样使用工件位置:

artifacts:
  files:
     - microservices/my-service/target/my-service.jar

唯一正确的方式是folder/myapp.jar,例如:

artifacts:
  files:
     - target/my-service.jar

所以你应该在你的 maven 配置中指定 outputDirectory 如果它不同

【讨论】:

以上是关于AWS CodePipeline 将 Spring Boot 应用程序部署到 Elastic BeansTalk的主要内容,如果未能解决你的问题,请参考以下文章

AWS:帮助在 Codepipeline 中设置 CodeDeploy

AWS CloudFormation CodePipeline、ParameterOverrides、将列表传递给嵌套堆栈

通过 Cloudformation、CodeBuild 和 CodePipeline 将 python 包部署到 AWS Lambda

将 git merge 集成到 master 作为 AWS Codepipeline 中的最后一步

如何使用 AWS CodeDeploy/CodePipeline/S3 将 Gitlab-Ci 部署到 EC2

AWS CodePipeline 错误:不允许跨账户传递角色