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

AWS CodePipeline deploy Spring Boot application to Elastic BeansTalk

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

1 和 2 步骤成功通过,而部署步骤失败。我在 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,它会完美运行。

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

问题出在工件的子文件夹中,不可能像我的构建规范那样使用工件位置:

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

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

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

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

虽然 Deny 的回答是正确的,但我认为它没有清楚地解释问题。

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/<name>.jar。您可以通过从 s3 下载工件并自行解压缩来确认这一点(就像 elastic beanstalk 在 vm 中所做的那样)。

所以当 elastic beanstalk 尝试部署它时它失败了,因为它寻找顶级 <name>.jar 至多 somedir/<name>.jar 并且你明白了相当神秘的错误消息

Unable to launch application as the source bundle does not contain either a file named application.jar or a 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 文件。 elastic beanstalk 会处理剩下的事情

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

希望这对其他人有帮助。