View Javadoc
1   package io.micronaut.build;
2   
3   import com.github.dockerjava.api.command.BuildImageCmd;
4   import com.google.common.io.FileWriteMode;
5   import com.google.common.io.Files;
6   import io.micronaut.build.services.ApplicationConfigurationService;
7   import io.micronaut.build.services.DockerService;
8   import io.micronaut.build.services.JibConfigurationService;
9   import org.apache.maven.plugin.MojoExecutionException;
10  import org.apache.maven.plugins.annotations.Mojo;
11  import org.apache.maven.plugins.annotations.ResolutionScope;
12  import org.apache.maven.project.MavenProject;
13  
14  import javax.inject.Inject;
15  import java.io.File;
16  import java.io.IOException;
17  import java.nio.charset.Charset;
18  
19  /**
20   * <p>Implementation of the <code>docker-native</code> packaging.</p>
21   * <p><strong>WARNING</strong>: this goal is not intended to be executed directly. Instead, specify the packaging type
22   * using the <code>packaging</code> property, eg:</p>
23   *
24   * <pre>mvn package -Dpackaging=docker-native</pre>
25   *
26   * @author Álvaro Sánchez-Mariscal
27   * @since 1.1
28   */
29  @Mojo(name = DockerNativeMojo.DOCKER_NATIVE_PACKAGING, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
30  public class DockerNativeMojo extends AbstractDockerMojo {
31  
32      public static final String DOCKER_NATIVE_PACKAGING = "docker-native";
33      public static final String DEFAULT_GRAAL_JVM_VERSION = "java11";
34  
35      @SuppressWarnings("CdiInjectionPointsInspection")
36      @Inject
37      public DockerNativeMojo(MavenProject mavenProject, JibConfigurationService jibConfigurationService,
38                              ApplicationConfigurationService applicationConfigurationService, DockerService dockerService) {
39          super(mavenProject, jibConfigurationService, applicationConfigurationService, dockerService);
40      }
41  
42      @Override
43      public void execute() throws MojoExecutionException {
44          checkJavaVersion();
45  
46          try {
47              copyDependencies();
48  
49              MicronautRuntime runtime = MicronautRuntime.valueOf(micronautRuntime.toUpperCase());
50  
51              switch (runtime.getBuildStrategy()) {
52                  case LAMBDA:
53                      buildDockerNativeLambda();
54                      break;
55  
56                  case ORACLE_FUNCTION:
57                      buildOracleCloud();
58                      break;
59  
60                  case DEFAULT:
61                      buildDockerNative();
62                      break;
63              }
64  
65  
66          } catch (Exception e) {
67              throw new MojoExecutionException(e.getMessage(), e);
68          }
69      }
70  
71      private void checkJavaVersion() throws MojoExecutionException {
72          if (javaVersion().getMajorVersion() > 11) {
73              throw new MojoExecutionException("To build native images you must set the Java target byte code level to Java 11 or below");
74          }
75      }
76  
77      private void buildDockerNativeLambda() throws IOException {
78          BuildImageCmd buildImageCmd = dockerService.buildImageCmd("DockerfileAwsCustomRuntime")
79                  .withBuildArg("GRAALVM_VERSION", graalVmVersion())
80                  .withBuildArg("GRAALVM_JVM_VERSION", graalVmJvmVersion());
81  
82          getLog().info("Using GRAALVM_VERSION: " + graalVmVersion());
83          getLog().info("Using GRAALVM_JVM_VERSION: " + graalVmJvmVersion());
84  
85          if (nativeImageBuildArgs != null && !nativeImageBuildArgs.trim().isEmpty()) {
86              getLog().info("Using GRAALVM_ARGS: " + nativeImageBuildArgs);
87              buildImageCmd = buildImageCmd.withBuildArg("GRAALVM_ARGS", nativeImageBuildArgs);
88          }
89  
90          String imageId = dockerService.buildImage(buildImageCmd);
91          File functionZip = dockerService.copyFromContainer(imageId, "/function/function.zip");
92          getLog().info("AWS Lambda Custom Runtime ZIP: " + functionZip.getPath());
93      }
94  
95      private void buildDockerNative() throws IOException {
96          String dockerfileName = "DockerfileNative";
97          if (staticNativeImage) {
98              getLog().info("Generating a static native image");
99              dockerfileName = "DockerfileNativeStatic";
100         }
101 
102         buildDockerfile(dockerfileName, true);
103     }
104 
105     private void buildOracleCloud() throws IOException {
106         buildDockerfile("DockerfileNativeOracleCloud", false);
107     }
108 
109     private void buildDockerfile(String dockerfileName, boolean passClassName) throws IOException {
110         String from = getFrom();
111         String port = getPort();
112         getLog().info("Exposing port: " + port);
113 
114         File dockerfile = dockerService.loadDockerfileAsResource(dockerfileName);
115 
116         if (appArguments != null && appArguments.size() > 0) {
117             getLog().info("Using application arguments: " + appArguments);
118             Files.asCharSink(dockerfile, Charset.defaultCharset(), FileWriteMode.APPEND).write(System.lineSeparator() + getCmd());
119         }
120 
121         BuildImageCmd buildImageCmd = dockerService.buildImageCmd()
122                 .withDockerfile(dockerfile)
123                 .withTags(getTags())
124                 .withBuildArg("BASE_IMAGE", from)
125                 .withBuildArg("PORT", port);
126 
127         getLog().info("Using BASE_IMAGE: " + from);
128 
129         if (passClassName) {
130             getLog().info("Using CLASS_NAME: " + mainClass);
131             buildImageCmd = buildImageCmd.withBuildArg("CLASS_NAME", mainClass);
132         }
133 
134         if (nativeImageBuildArgs != null && !nativeImageBuildArgs.trim().isEmpty()) {
135             getLog().info("Using GRAALVM_ARGS: " + nativeImageBuildArgs);
136             buildImageCmd = buildImageCmd.withBuildArg("GRAALVM_ARGS", nativeImageBuildArgs);
137         }
138 
139         dockerService.buildImage(buildImageCmd);
140     }
141 
142 }