Skip to content

Commit

Permalink
Merge branch '3.6.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
melix committed Nov 18, 2022
2 parents 32920f8 + bc636b1 commit 6a2210f
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;

Expand All @@ -26,6 +27,13 @@ public interface CRaCConfiguration {
*/
Property<String> getPlatform();

/**
* The optional docker network name to use during building
* @return the network name
*/
@Optional
Property<String> getNetwork();

/**
* Any arguments passed to java in the final image
* @return list of arguments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

public class MicronautCRaCPlugin implements Plugin<Project> {

public static final String CRAC_DEFAULT_BASE_IMAGE = "ubuntu:20.04";
public static final String CRAC_DEFAULT_BASE_IMAGE = "ubuntu:22.04";
public static final String CRAC_DEFAULT_BASE_IMAGE_PLATFORM = "linux/amd64";
public static final String CRAC_DEFAULT_READINESS_COMMAND = "curl --output /dev/null --silent --head http://localhost:8080";
private static final String CRAC_TASK_GROUP = "CRaC";
Expand Down Expand Up @@ -162,6 +162,7 @@ private CheckpointTasksOfNote configureCheckpointDockerBuild(Project project,
task.targetImageId("checkpoint:latest");
task.getContainerName().set(CRAC_CHECKPOINT);
task.getHostConfig().getPrivileged().set(true);
task.getHostConfig().getNetwork().convention(configuration.getNetwork());
String local = project.getLayout().getBuildDirectory().dir(BUILD_DOCKER_DIRECTORY + imageName + "/cr").map(d -> d.getAsFile().getAbsolutePath()).get();
task.getHostConfig().getBinds().put(local, "/home/app/cr");
});
Expand Down
4 changes: 4 additions & 0 deletions crac-plugin/src/main/resources/checkpoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ echo 599 > /proc/sys/kernel/ns_last_pid
trap 'echo "Killing $PROCESS" && kill -0 $PROCESS 2>/dev/null && kill $PROCESS' EXIT

echo "Starting application"

# Fix for WSL and OS X Docker Kernels
GLIBC_TUNABLES=glibc.pthread.rseq=0

# Run the app in the background
/azul-crac-jdk/bin/java \
-XX:CRaCCheckpointTo=cr \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,8 @@ private Optional<TaskProvider<MicronautDockerfile>> configureDockerBuild(Project
task.dependsOn(buildLayersTask);
task.setGroup(BasePlugin.BUILD_GROUP);
task.setDescription("Builds a Docker Image (image " + imageName + ")");
if (f.exists()) {
task.getDockerFile().set(f);
} else {
task.getDockerFile()
.convention(dockerFileTask.flatMap(Dockerfile::getDestFile));
}
task.getDockerFile().convention(dockerFileTask.flatMap(Dockerfile::getDestFile));
task.getImages().set(Collections.singletonList(project.getName()));
;
task.getInputDir().set(dockerFileTask.flatMap(Dockerfile::getDestDir));
});

Expand Down Expand Up @@ -263,12 +257,7 @@ private TaskProvider<NativeImageDockerfile> configureNativeDockerBuild(Project p
task.setGroup(BasePlugin.BUILD_GROUP);
task.setDescription("Builds a Native Docker Image using GraalVM (image " + imageName + ")");
task.getInputs().files(prepareContext);
if (f.exists()) {
task.getDockerFile().set(f);
} else {
task.getDockerFile()
.convention(dockerFileTask.flatMap(Dockerfile::getDestFile));
}
task.getDockerFile().convention(dockerFileTask.flatMap(Dockerfile::getDestFile));
task.getImages().set(Collections.singletonList(project.getName()));
task.dependsOn(buildLayersTask);
task.getInputDir().set(dockerFileTask.flatMap(Dockerfile::getDestDir));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
import io.micronaut.gradle.docker.model.Layer;
import io.micronaut.gradle.docker.model.LayerKind;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.Directory;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.DuplicatesStrategy;
import org.gradle.api.internal.file.FileOperations;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.CacheableTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;

Expand All @@ -21,6 +26,10 @@ public abstract class BuildLayersTask extends DefaultTask {
@Nested
public abstract ListProperty<Layer> getLayers();

@Input
@Optional
public abstract Property<DuplicatesStrategy> getDuplicatesStrategy();

@OutputDirectory
public abstract DirectoryProperty getOutputDir();

Expand All @@ -42,13 +51,25 @@ public void action() {
final Provider<Directory> layerDir = layerDirectoryOf(layer, getOutputDir(), libsDir, resourcesDir, classesDir);
if (layer.getLayerKind().get() == LayerKind.APP) {
// special case for now
fileOperations.copy(copy -> copy.from(layer.getFiles()).into(getOutputDir()).rename(s -> "application.jar"));
fileOperations.copy(copy -> {
configureDuplicatesStrategy(copy);
copy.from(layer.getFiles()).into(getOutputDir()).rename(s -> "application.jar");
});
} else {
fileOperations.copy(copy -> copy.from(layer.getFiles()).into(layerDir));
fileOperations.copy(copy -> {
configureDuplicatesStrategy(copy);
copy.from(layer.getFiles()).into(layerDir);
});
}
}
}

private void configureDuplicatesStrategy(CopySpec copy) {
if (getDuplicatesStrategy().isPresent()) {
copy.setDuplicatesStrategy(getDuplicatesStrategy().get());
}
}

private static Provider<Directory> layerDirectoryOf(Layer layer,
Provider<Directory> appDir,
Provider<Directory> libsDir,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,56 @@ class BuildLayersSpec extends AbstractGradleBuildSpec {
new File(testProjectDir.root, "build-custom/docker/main/layers").exists()
!new File(testProjectDir.root, "build/docker/main/layers").exists()
}

void 'test build layers with duplicates strategy'() {
given:
settingsFile << "rootProject.name = 'hello-world'"
buildFile << """
plugins {
id "io.micronaut.minimal.application"
id "io.micronaut.docker"
}
micronaut {
version "3.5.1"
runtime "netty"
testRuntime "junit5"
}
$repositoriesBlock
dependencies {
runtimeOnly("ch.qos.logback:logback-classic")
testImplementation("io.micronaut:micronaut-http-client")
}
mainClassName="example.Application"
def jar1 = tasks.register("otherJar", Jar) {
destinationDirectory = file("build/libs1")
archiveBaseName = 'toto'
from sourceSets.main.output
}
def jar2 = tasks.register("otherJar2", Jar) {
destinationDirectory = file("build/libs2")
archiveBaseName = 'toto'
from sourceSets.main.output
}
configurations.runtimeClasspath.dependencies.add(dependencies.create(files(jar1, jar2)))
tasks.withType(io.micronaut.gradle.docker.tasks.BuildLayersTask) {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
"""

when:
def result = build('buildLayers')

def task = result.task(":buildLayers")

then:
task.outcome == TaskOutcome.SUCCESS
new File(testProjectDir.root, "build/docker/main/layers").exists()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,58 @@ class Application {

}

def "test build docker image using custom Dockerfile"() {
given:
settingsFile << "rootProject.name = 'hello-world'"
buildFile << """
plugins {
id "io.micronaut.minimal.application"
id "io.micronaut.docker"
}
micronaut {
version "3.5.1"
}
$repositoriesBlock
mainClassName="example.Application"
"""
testProjectDir.newFolder("src", "main", "java", "example")
def javaFile = testProjectDir.newFile("src/main/java/example/Application.java")
javaFile.parentFile.mkdirs()
javaFile << """
package example;
class Application {
public static void main(String... args) {
}
}
"""

testProjectDir.newFile("Dockerfile") << """
FROM openjdk:17-alpine
WORKDIR /home/alternate
COPY layers/libs /home/alternate/libs
COPY layers/classes /home/alternate/classes
COPY layers/resources /home/alternate/resources
COPY layers/application.jar /home/alternate/application.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/home/alternate/application.jar"]
"""
when:
def result = build('dockerBuild', '-s')

def task = result.task(":dockerBuild")
then:
result.output.contains("WORKDIR /home/alternate")
result.output.contains("Successfully tagged hello-world:latest")
task.outcome == TaskOutcome.SUCCESS

}

@Issue('https://github.com/micronaut-projects/micronaut-gradle-plugin/issues/161')
void 'create group and user for running the application instead of using root'() {
given:
Expand Down
33 changes: 30 additions & 3 deletions src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,8 @@ If you wish to split your native executable tests from your regular tests you ca

=== Docker Support

==== Building docker images

The Micronaut plugin includes integration with the https://bmuschko.github.io/gradle-docker-plugin[Gradle Docker plugin] allowing you to easily build applications and native executables using Docker containers.

Applications are built as layered JARs using the `buildLayers` task ensuring optimized Docker images for Java applications.
Expand Down Expand Up @@ -743,6 +745,8 @@ tasks.named<DockerBuildImage>("dockerBuildCrac") {

Notice that you can supply two different image names to push to for the JVM version and the native version of the application.

==== Customized docker files

If you wish to customize the docker builds that are used, the easiest way is to run `./gradlew dockerfile` (or `dockerfileNative` for the native version) and copy the generated `Dockerfile` from `build/docker` to your root directory and modify as required.

To customize the JVM arguments or native executable arguments, use the `args` method of the `dockerfile` and `dockerfileNative` tasks:
Expand All @@ -769,6 +773,8 @@ tasks.named<io.micronaut.gradle.docker.NativeImageDockerfile>("dockerfileNative"

The above configuration uses a max heap setting of `128m` for Java and `64m` for native executable for the application.

==== Adding additional instructions

To add additional docker instructions to the generated Dockerfile, such as adding a HEALTHCHECK, you can do the following. The additional instructions will be added at the end of the `Dockerfile` just before the `ENTRYPOINT`.

[source, groovy, subs="verbatim,attributes", role="multi-language-sample"]
Expand Down Expand Up @@ -797,6 +803,27 @@ tasks.named<io.micronaut.gradle.docker.NativeImageDockerfile>("dockerfileNative"

You can also add any of the other instructions/commands that the docker plugin supports, see {docker-plugin}/blob/master/src/main/groovy/com/bmuschko/gradle/docker/tasks/image/Dockerfile.groovy[the Dockerfile task documentation].

==== Duplicates on classpath

In some projects, it may happen that different transitive dependencies have the same file name.
In this case, the task which builds the layers will fail with a duplicate error.
You can workaround this issue by configuring the duplicates strategy on the task:

[source, groovy, subs="verbatim,attributes", role="multi-language-sample"]
----
tasks.withType<io.micronaut.gradle.docker.tasks.BuildLayersTask> {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
----

[source, kotlin, subs="verbatim,attributes", role="multi-language-sample"]
----
tasks.withType(io.micronaut.gradle.docker.tasks.BuildLayersTask) {
duplicatesStrategy.set(DuplicatesStrategy.INCLUDE)
}
----


=== Micronaut Runtimes

A higher level concept of "runtimes" is included in the Micronaut Gradle plugin which essentially allows the plugin to decide which server runtime to include in the dependencies of the application when building the application. For example consider this minimal build:
Expand Down Expand Up @@ -1507,7 +1534,7 @@ Micronaut CRaC is a module which adds support for https://openjdk.org/projects/c

It is capable of generating a docker image containing a CRaC enabled JDK and a pre-warmed, checkpointed application via a new task `dockerCracBuild`.

IMPORTANT: Currently CRaC support has only been tested on Ubuntu 18.04 and 20.04. It also requires an x86 machine architecture.
IMPORTANT: Currently CRaC support has only been tested on Ubuntu 18.04, 20.04 and 22.04. It also requires an x86 machine architecture.

When executed, this task will:

Expand Down Expand Up @@ -1561,7 +1588,7 @@ micronaut {
enabled = true
// the base docker image to use for the Checkpoint and final images
baseImage = "ubuntu:20.04"
baseImage = "ubuntu:22.04"
// The platform to build the image for (currently must be linux/amd64)
platform = "linux/amd64"
Expand All @@ -1586,7 +1613,7 @@ micronaut {
enabled.set(true)
// the base docker image to use for the Checkpoint and final images
baseImage.set("ubuntu:20.04")
baseImage.set("ubuntu:22.04")
// The platform to build the image for (currently must be linux/amd64)
platform.set("linux/amd64")
Expand Down
Loading

0 comments on commit 6a2210f

Please sign in to comment.