Add support for build workspace option when building images
Closes gh-37478
This commit is contained in:
parent
d8576f319e
commit
4433fcd1f2
|
|
@ -77,6 +77,8 @@ public class BuildRequest {
|
||||||
|
|
||||||
private final List<ImageReference> tags;
|
private final List<ImageReference> tags;
|
||||||
|
|
||||||
|
private final Cache buildWorkspace;
|
||||||
|
|
||||||
private final Cache buildCache;
|
private final Cache buildCache;
|
||||||
|
|
||||||
private final Cache launchCache;
|
private final Cache launchCache;
|
||||||
|
|
@ -102,6 +104,7 @@ public class BuildRequest {
|
||||||
this.bindings = Collections.emptyList();
|
this.bindings = Collections.emptyList();
|
||||||
this.network = null;
|
this.network = null;
|
||||||
this.tags = Collections.emptyList();
|
this.tags = Collections.emptyList();
|
||||||
|
this.buildWorkspace = null;
|
||||||
this.buildCache = null;
|
this.buildCache = null;
|
||||||
this.launchCache = null;
|
this.launchCache = null;
|
||||||
this.createdDate = null;
|
this.createdDate = null;
|
||||||
|
|
@ -111,8 +114,8 @@ public class BuildRequest {
|
||||||
BuildRequest(ImageReference name, Function<Owner, TarArchive> applicationContent, ImageReference builder,
|
BuildRequest(ImageReference name, Function<Owner, TarArchive> applicationContent, ImageReference builder,
|
||||||
ImageReference runImage, Creator creator, Map<String, String> env, boolean cleanCache,
|
ImageReference runImage, Creator creator, Map<String, String> env, boolean cleanCache,
|
||||||
boolean verboseLogging, PullPolicy pullPolicy, boolean publish, List<BuildpackReference> buildpacks,
|
boolean verboseLogging, PullPolicy pullPolicy, boolean publish, List<BuildpackReference> buildpacks,
|
||||||
List<Binding> bindings, String network, List<ImageReference> tags, Cache buildCache, Cache launchCache,
|
List<Binding> bindings, String network, List<ImageReference> tags, Cache buildWorkspace, Cache buildCache,
|
||||||
Instant createdDate, String applicationDirectory) {
|
Cache launchCache, Instant createdDate, String applicationDirectory) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.applicationContent = applicationContent;
|
this.applicationContent = applicationContent;
|
||||||
this.builder = builder;
|
this.builder = builder;
|
||||||
|
|
@ -127,6 +130,7 @@ public class BuildRequest {
|
||||||
this.bindings = bindings;
|
this.bindings = bindings;
|
||||||
this.network = network;
|
this.network = network;
|
||||||
this.tags = tags;
|
this.tags = tags;
|
||||||
|
this.buildWorkspace = buildWorkspace;
|
||||||
this.buildCache = buildCache;
|
this.buildCache = buildCache;
|
||||||
this.launchCache = launchCache;
|
this.launchCache = launchCache;
|
||||||
this.createdDate = createdDate;
|
this.createdDate = createdDate;
|
||||||
|
|
@ -142,8 +146,8 @@ public class BuildRequest {
|
||||||
Assert.notNull(builder, "Builder must not be null");
|
Assert.notNull(builder, "Builder must not be null");
|
||||||
return new BuildRequest(this.name, this.applicationContent, builder.inTaggedOrDigestForm(), this.runImage,
|
return new BuildRequest(this.name, this.applicationContent, builder.inTaggedOrDigestForm(), this.runImage,
|
||||||
this.creator, this.env, this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
|
this.creator, this.env, this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
|
||||||
this.buildpacks, this.bindings, this.network, this.tags, this.buildCache, this.launchCache,
|
this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace, this.buildCache,
|
||||||
this.createdDate, this.applicationDirectory);
|
this.launchCache, this.createdDate, this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -154,8 +158,8 @@ public class BuildRequest {
|
||||||
public BuildRequest withRunImage(ImageReference runImageName) {
|
public BuildRequest withRunImage(ImageReference runImageName) {
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, runImageName.inTaggedOrDigestForm(),
|
return new BuildRequest(this.name, this.applicationContent, this.builder, runImageName.inTaggedOrDigestForm(),
|
||||||
this.creator, this.env, this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
|
this.creator, this.env, this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
|
||||||
this.buildpacks, this.bindings, this.network, this.tags, this.buildCache, this.launchCache,
|
this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace, this.buildCache,
|
||||||
this.createdDate, this.applicationDirectory);
|
this.launchCache, this.createdDate, this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -167,7 +171,7 @@ public class BuildRequest {
|
||||||
Assert.notNull(creator, "Creator must not be null");
|
Assert.notNull(creator, "Creator must not be null");
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
|
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
this.applicationDirectory);
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,8 +188,8 @@ public class BuildRequest {
|
||||||
env.put(name, value);
|
env.put(name, value);
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator,
|
||||||
Collections.unmodifiableMap(env), this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
|
Collections.unmodifiableMap(env), this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish,
|
||||||
this.buildpacks, this.bindings, this.network, this.tags, this.buildCache, this.launchCache,
|
this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace, this.buildCache,
|
||||||
this.createdDate, this.applicationDirectory);
|
this.launchCache, this.createdDate, this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -199,8 +203,8 @@ public class BuildRequest {
|
||||||
updatedEnv.putAll(env);
|
updatedEnv.putAll(env);
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator,
|
||||||
Collections.unmodifiableMap(updatedEnv), this.cleanCache, this.verboseLogging, this.pullPolicy,
|
Collections.unmodifiableMap(updatedEnv), this.cleanCache, this.verboseLogging, this.pullPolicy,
|
||||||
this.publish, this.buildpacks, this.bindings, this.network, this.tags, this.buildCache,
|
this.publish, this.buildpacks, this.bindings, this.network, this.tags, this.buildWorkspace,
|
||||||
this.launchCache, this.createdDate, this.applicationDirectory);
|
this.buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -211,7 +215,7 @@ public class BuildRequest {
|
||||||
public BuildRequest withCleanCache(boolean cleanCache) {
|
public BuildRequest withCleanCache(boolean cleanCache) {
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
|
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
this.applicationDirectory);
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,7 +227,7 @@ public class BuildRequest {
|
||||||
public BuildRequest withVerboseLogging(boolean verboseLogging) {
|
public BuildRequest withVerboseLogging(boolean verboseLogging) {
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
this.cleanCache, verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
|
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
this.applicationDirectory);
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -235,7 +239,7 @@ public class BuildRequest {
|
||||||
public BuildRequest withPullPolicy(PullPolicy pullPolicy) {
|
public BuildRequest withPullPolicy(PullPolicy pullPolicy) {
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, pullPolicy, this.publish, this.buildpacks, this.bindings,
|
this.cleanCache, this.verboseLogging, pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
|
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
this.applicationDirectory);
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,7 +251,7 @@ public class BuildRequest {
|
||||||
public BuildRequest withPublish(boolean publish) {
|
public BuildRequest withPublish(boolean publish) {
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, this.pullPolicy, publish, this.buildpacks, this.bindings,
|
this.cleanCache, this.verboseLogging, this.pullPolicy, publish, this.buildpacks, this.bindings,
|
||||||
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
|
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
this.applicationDirectory);
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -272,7 +276,7 @@ public class BuildRequest {
|
||||||
Assert.notNull(buildpacks, "Buildpacks must not be null");
|
Assert.notNull(buildpacks, "Buildpacks must not be null");
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, buildpacks, this.bindings,
|
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, buildpacks, this.bindings,
|
||||||
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
|
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
this.applicationDirectory);
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,7 +301,7 @@ public class BuildRequest {
|
||||||
Assert.notNull(bindings, "Bindings must not be null");
|
Assert.notNull(bindings, "Bindings must not be null");
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, bindings,
|
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, bindings,
|
||||||
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate,
|
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
this.applicationDirectory);
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -310,7 +314,8 @@ public class BuildRequest {
|
||||||
public BuildRequest withNetwork(String network) {
|
public BuildRequest withNetwork(String network) {
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
network, this.tags, this.buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
|
network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -332,7 +337,21 @@ public class BuildRequest {
|
||||||
Assert.notNull(tags, "Tags must not be null");
|
Assert.notNull(tags, "Tags must not be null");
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
this.network, tags, this.buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
|
this.network, tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
|
this.applicationDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new {@link BuildRequest} with an updated build workspace.
|
||||||
|
* @param buildWorkspace the build workspace
|
||||||
|
* @return an updated build request
|
||||||
|
*/
|
||||||
|
public BuildRequest withBuildWorkspace(Cache buildWorkspace) {
|
||||||
|
Assert.notNull(buildWorkspace, "BuildWorkspace must not be null");
|
||||||
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
|
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
|
this.network, this.tags, buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -344,7 +363,8 @@ public class BuildRequest {
|
||||||
Assert.notNull(buildCache, "BuildCache must not be null");
|
Assert.notNull(buildCache, "BuildCache must not be null");
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
this.network, this.tags, buildCache, this.launchCache, this.createdDate, this.applicationDirectory);
|
this.network, this.tags, this.buildWorkspace, buildCache, this.launchCache, this.createdDate,
|
||||||
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -356,7 +376,8 @@ public class BuildRequest {
|
||||||
Assert.notNull(launchCache, "LaunchCache must not be null");
|
Assert.notNull(launchCache, "LaunchCache must not be null");
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
this.network, this.tags, this.buildCache, launchCache, this.createdDate, this.applicationDirectory);
|
this.network, this.tags, this.buildWorkspace, this.buildCache, launchCache, this.createdDate,
|
||||||
|
this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -368,8 +389,8 @@ public class BuildRequest {
|
||||||
Assert.notNull(createdDate, "CreatedDate must not be null");
|
Assert.notNull(createdDate, "CreatedDate must not be null");
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
this.network, this.tags, this.buildCache, this.launchCache, parseCreatedDate(createdDate),
|
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache,
|
||||||
this.applicationDirectory);
|
parseCreatedDate(createdDate), this.applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instant parseCreatedDate(String createdDate) {
|
private Instant parseCreatedDate(String createdDate) {
|
||||||
|
|
@ -393,7 +414,8 @@ public class BuildRequest {
|
||||||
Assert.notNull(applicationDirectory, "ApplicationDirectory must not be null");
|
Assert.notNull(applicationDirectory, "ApplicationDirectory must not be null");
|
||||||
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
return new BuildRequest(this.name, this.applicationContent, this.builder, this.runImage, this.creator, this.env,
|
||||||
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
this.cleanCache, this.verboseLogging, this.pullPolicy, this.publish, this.buildpacks, this.bindings,
|
||||||
this.network, this.tags, this.buildCache, this.launchCache, this.createdDate, applicationDirectory);
|
this.network, this.tags, this.buildWorkspace, this.buildCache, this.launchCache, this.createdDate,
|
||||||
|
applicationDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -513,6 +535,10 @@ public class BuildRequest {
|
||||||
return this.tags;
|
return this.tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Cache getBuildWorkspace() {
|
||||||
|
return this.buildWorkspace;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the custom build cache that should be used by the lifecycle.
|
* Return the custom build cache that should be used by the lifecycle.
|
||||||
* @return the build cache
|
* @return the build cache
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@ package org.springframework.boot.buildpack.platform.build;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import com.sun.jna.Platform;
|
import com.sun.jna.Platform;
|
||||||
|
|
@ -70,9 +72,9 @@ class Lifecycle implements Closeable {
|
||||||
|
|
||||||
private final ApiVersion platformVersion;
|
private final ApiVersion platformVersion;
|
||||||
|
|
||||||
private final VolumeName layersVolume;
|
private final Cache layers;
|
||||||
|
|
||||||
private final VolumeName applicationVolume;
|
private final Cache application;
|
||||||
|
|
||||||
private final Cache buildCache;
|
private final Cache buildCache;
|
||||||
|
|
||||||
|
|
@ -101,17 +103,13 @@ class Lifecycle implements Closeable {
|
||||||
this.builder = builder;
|
this.builder = builder;
|
||||||
this.lifecycleVersion = LifecycleVersion.parse(builder.getBuilderMetadata().getLifecycle().getVersion());
|
this.lifecycleVersion = LifecycleVersion.parse(builder.getBuilderMetadata().getLifecycle().getVersion());
|
||||||
this.platformVersion = getPlatformVersion(builder.getBuilderMetadata().getLifecycle());
|
this.platformVersion = getPlatformVersion(builder.getBuilderMetadata().getLifecycle());
|
||||||
this.layersVolume = createRandomVolumeName("pack-layers-");
|
this.layers = getLayersBindingSource(request);
|
||||||
this.applicationVolume = createRandomVolumeName("pack-app-");
|
this.application = getApplicationBindingSource(request);
|
||||||
this.buildCache = getBuildCache(request);
|
this.buildCache = getBuildCache(request);
|
||||||
this.launchCache = getLaunchCache(request);
|
this.launchCache = getLaunchCache(request);
|
||||||
this.applicationDirectory = getApplicationDirectory(request);
|
this.applicationDirectory = getApplicationDirectory(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected VolumeName createRandomVolumeName(String prefix) {
|
|
||||||
return VolumeName.random(prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Cache getBuildCache(BuildRequest request) {
|
private Cache getBuildCache(BuildRequest request) {
|
||||||
if (request.getBuildCache() != null) {
|
if (request.getBuildCache() != null) {
|
||||||
return request.getBuildCache();
|
return request.getBuildCache();
|
||||||
|
|
@ -130,11 +128,6 @@ class Lifecycle implements Closeable {
|
||||||
return (request.getApplicationDirectory() != null) ? request.getApplicationDirectory() : Directory.APPLICATION;
|
return (request.getApplicationDirectory() != null) ? request.getApplicationDirectory() : Directory.APPLICATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cache createVolumeCache(BuildRequest request, String suffix) {
|
|
||||||
return Cache.volume(
|
|
||||||
VolumeName.basedOn(request.getName(), ImageReference::toLegacyString, "pack-cache-", "." + suffix, 6));
|
|
||||||
}
|
|
||||||
|
|
||||||
private ApiVersion getPlatformVersion(BuilderMetadata.Lifecycle lifecycle) {
|
private ApiVersion getPlatformVersion(BuilderMetadata.Lifecycle lifecycle) {
|
||||||
if (lifecycle.getApis().getPlatform() != null) {
|
if (lifecycle.getApis().getPlatform() != null) {
|
||||||
String[] supportedVersions = lifecycle.getApis().getPlatform();
|
String[] supportedVersions = lifecycle.getApis().getPlatform();
|
||||||
|
|
@ -153,12 +146,7 @@ class Lifecycle implements Closeable {
|
||||||
this.executed = true;
|
this.executed = true;
|
||||||
this.log.executingLifecycle(this.request, this.lifecycleVersion, this.buildCache);
|
this.log.executingLifecycle(this.request, this.lifecycleVersion, this.buildCache);
|
||||||
if (this.request.isCleanCache()) {
|
if (this.request.isCleanCache()) {
|
||||||
if (this.buildCache.getVolume() != null) {
|
deleteCache(this.buildCache);
|
||||||
deleteVolume(this.buildCache.getVolume().getVolumeName());
|
|
||||||
}
|
|
||||||
if (this.buildCache.getBind() != null) {
|
|
||||||
deleteBind(this.buildCache.getBind().getSource());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
run(createPhase());
|
run(createPhase());
|
||||||
this.log.executedLifecycle(this.request);
|
this.log.executedLifecycle(this.request);
|
||||||
|
|
@ -183,8 +171,8 @@ class Lifecycle implements Closeable {
|
||||||
phase.withArgs("-process-type=web");
|
phase.withArgs("-process-type=web");
|
||||||
}
|
}
|
||||||
phase.withArgs(this.request.getName());
|
phase.withArgs(this.request.getName());
|
||||||
phase.withBinding(Binding.from(this.layersVolume, Directory.LAYERS));
|
phase.withBinding(Binding.from(getCacheBindingSource(this.layers), Directory.LAYERS));
|
||||||
phase.withBinding(Binding.from(this.applicationVolume, this.applicationDirectory));
|
phase.withBinding(Binding.from(getCacheBindingSource(this.application), this.applicationDirectory));
|
||||||
phase.withBinding(Binding.from(getCacheBindingSource(this.buildCache), Directory.CACHE));
|
phase.withBinding(Binding.from(getCacheBindingSource(this.buildCache), Directory.CACHE));
|
||||||
phase.withBinding(Binding.from(getCacheBindingSource(this.launchCache), Directory.LAUNCH_CACHE));
|
phase.withBinding(Binding.from(getCacheBindingSource(this.launchCache), Directory.LAUNCH_CACHE));
|
||||||
if (this.request.getBindings() != null) {
|
if (this.request.getBindings() != null) {
|
||||||
|
|
@ -200,10 +188,42 @@ class Lifecycle implements Closeable {
|
||||||
return phase;
|
return phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Cache getLayersBindingSource(BuildRequest request) {
|
||||||
|
if (request.getBuildWorkspace() != null) {
|
||||||
|
return getBuildWorkspaceBindingSource(request.getBuildWorkspace(), "layers");
|
||||||
|
}
|
||||||
|
return createVolumeCache("pack-layers-");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cache getApplicationBindingSource(BuildRequest request) {
|
||||||
|
if (request.getBuildWorkspace() != null) {
|
||||||
|
return getBuildWorkspaceBindingSource(request.getBuildWorkspace(), "app");
|
||||||
|
}
|
||||||
|
return createVolumeCache("pack-app-");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cache getBuildWorkspaceBindingSource(Cache buildWorkspace, String suffix) {
|
||||||
|
return (buildWorkspace.getVolume() != null) ? Cache.volume(buildWorkspace.getVolume().getName() + "-" + suffix)
|
||||||
|
: Cache.bind(buildWorkspace.getBind().getSource() + "-" + suffix);
|
||||||
|
}
|
||||||
|
|
||||||
private String getCacheBindingSource(Cache cache) {
|
private String getCacheBindingSource(Cache cache) {
|
||||||
return (cache.getVolume() != null) ? cache.getVolume().getName() : cache.getBind().getSource();
|
return (cache.getVolume() != null) ? cache.getVolume().getName() : cache.getBind().getSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Cache createVolumeCache(String prefix) {
|
||||||
|
return Cache.volume(createRandomVolumeName(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cache createVolumeCache(BuildRequest request, String suffix) {
|
||||||
|
return Cache.volume(
|
||||||
|
VolumeName.basedOn(request.getName(), ImageReference::toLegacyString, "pack-cache-", "." + suffix, 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected VolumeName createRandomVolumeName(String prefix) {
|
||||||
|
return VolumeName.random(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
private void configureDaemonAccess(Phase phase) {
|
private void configureDaemonAccess(Phase phase) {
|
||||||
if (this.dockerHost != null) {
|
if (this.dockerHost != null) {
|
||||||
if (this.dockerHost.isRemote()) {
|
if (this.dockerHost.isRemote()) {
|
||||||
|
|
@ -255,6 +275,9 @@ class Lifecycle implements Closeable {
|
||||||
return this.docker.container().create(config);
|
return this.docker.container().create(config);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
if (this.application.getBind() != null) {
|
||||||
|
Files.createDirectories(Path.of(this.application.getBind().getSource()));
|
||||||
|
}
|
||||||
TarArchive applicationContent = this.request.getApplicationContent(this.builder.getBuildOwner());
|
TarArchive applicationContent = this.request.getApplicationContent(this.builder.getBuildOwner());
|
||||||
return this.docker.container()
|
return this.docker.container()
|
||||||
.create(config, ContainerContent.of(applicationContent, this.applicationDirectory));
|
.create(config, ContainerContent.of(applicationContent, this.applicationDirectory));
|
||||||
|
|
@ -266,8 +289,17 @@ class Lifecycle implements Closeable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
deleteVolume(this.layersVolume);
|
deleteCache(this.layers);
|
||||||
deleteVolume(this.applicationVolume);
|
deleteCache(this.application);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteCache(Cache cache) throws IOException {
|
||||||
|
if (cache.getVolume() != null) {
|
||||||
|
deleteVolume(cache.getVolume().getVolumeName());
|
||||||
|
}
|
||||||
|
if (cache.getBind() != null) {
|
||||||
|
deleteBind(cache.getBind().getSource());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteVolume(VolumeName name) throws IOException {
|
private void deleteVolume(VolumeName name) throws IOException {
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,22 @@ class BuildRequestTests {
|
||||||
.withMessage("Tags must not be null");
|
.withMessage("Tags must not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void withBuildWorkspaceVolumeAddsWorkspace() throws IOException {
|
||||||
|
BuildRequest request = BuildRequest.forJarFile(writeTestJarFile("my-app-0.0.1.jar"));
|
||||||
|
BuildRequest withWorkspace = request.withBuildWorkspace(Cache.volume("build-workspace"));
|
||||||
|
assertThat(request.getBuildWorkspace()).isNull();
|
||||||
|
assertThat(withWorkspace.getBuildWorkspace()).isEqualTo(Cache.volume("build-workspace"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void withBuildWorkspaceBindAddsWorkspace() throws IOException {
|
||||||
|
BuildRequest request = BuildRequest.forJarFile(writeTestJarFile("my-app-0.0.1.jar"));
|
||||||
|
BuildRequest withWorkspace = request.withBuildWorkspace(Cache.bind("/tmp/build-workspace"));
|
||||||
|
assertThat(request.getBuildWorkspace()).isNull();
|
||||||
|
assertThat(withWorkspace.getBuildWorkspace()).isEqualTo(Cache.bind("/tmp/build-workspace"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void withBuildVolumeCacheAddsCache() throws IOException {
|
void withBuildVolumeCacheAddsCache() throws IOException {
|
||||||
BuildRequest request = BuildRequest.forJarFile(writeTestJarFile("my-app-0.0.1.jar"));
|
BuildRequest request = BuildRequest.forJarFile(writeTestJarFile("my-app-0.0.1.jar"));
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,8 @@ class LifecycleTests {
|
||||||
given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId());
|
given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId());
|
||||||
given(this.docker.container().create(any(), any())).willAnswer(answerWithGeneratedContainerId());
|
given(this.docker.container().create(any(), any())).willAnswer(answerWithGeneratedContainerId());
|
||||||
given(this.docker.container().wait(any())).willReturn(ContainerStatus.of(0, null));
|
given(this.docker.container().wait(any())).willReturn(ContainerStatus.of(0, null));
|
||||||
BuildRequest request = getTestRequest().withBuildCache(Cache.volume("build-volume"))
|
BuildRequest request = getTestRequest().withBuildWorkspace(Cache.volume("work-volume"))
|
||||||
|
.withBuildCache(Cache.volume("build-volume"))
|
||||||
.withLaunchCache(Cache.volume("launch-volume"));
|
.withLaunchCache(Cache.volume("launch-volume"));
|
||||||
createLifecycle(request).execute();
|
createLifecycle(request).execute();
|
||||||
assertPhaseWasRun("creator", withExpectedConfig("lifecycle-creator-cache-volumes.json"));
|
assertPhaseWasRun("creator", withExpectedConfig("lifecycle-creator-cache-volumes.json"));
|
||||||
|
|
@ -223,7 +224,8 @@ class LifecycleTests {
|
||||||
given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId());
|
given(this.docker.container().create(any())).willAnswer(answerWithGeneratedContainerId());
|
||||||
given(this.docker.container().create(any(), any())).willAnswer(answerWithGeneratedContainerId());
|
given(this.docker.container().create(any(), any())).willAnswer(answerWithGeneratedContainerId());
|
||||||
given(this.docker.container().wait(any())).willReturn(ContainerStatus.of(0, null));
|
given(this.docker.container().wait(any())).willReturn(ContainerStatus.of(0, null));
|
||||||
BuildRequest request = getTestRequest().withBuildCache(Cache.bind("/tmp/build-cache"))
|
BuildRequest request = getTestRequest().withBuildWorkspace(Cache.bind("/tmp/work"))
|
||||||
|
.withBuildCache(Cache.bind("/tmp/build-cache"))
|
||||||
.withLaunchCache(Cache.bind("/tmp/launch-cache"));
|
.withLaunchCache(Cache.bind("/tmp/launch-cache"));
|
||||||
createLifecycle(request).execute();
|
createLifecycle(request).execute();
|
||||||
assertPhaseWasRun("creator", withExpectedConfig("lifecycle-creator-cache-bind-mounts.json"));
|
assertPhaseWasRun("creator", withExpectedConfig("lifecycle-creator-cache-bind-mounts.json"));
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@
|
||||||
"HostConfig": {
|
"HostConfig": {
|
||||||
"Binds": [
|
"Binds": [
|
||||||
"/var/run/docker.sock:/var/run/docker.sock",
|
"/var/run/docker.sock:/var/run/docker.sock",
|
||||||
"pack-layers-aaaaaaaaaa:/layers",
|
"/tmp/work-layers:/layers",
|
||||||
"pack-app-aaaaaaaaaa:/workspace",
|
"/tmp/work-app:/workspace",
|
||||||
"/tmp/build-cache:/cache",
|
"/tmp/build-cache:/cache",
|
||||||
"/tmp/launch-cache:/launch-cache"
|
"/tmp/launch-cache:/launch-cache"
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@
|
||||||
"HostConfig": {
|
"HostConfig": {
|
||||||
"Binds": [
|
"Binds": [
|
||||||
"/var/run/docker.sock:/var/run/docker.sock",
|
"/var/run/docker.sock:/var/run/docker.sock",
|
||||||
"pack-layers-aaaaaaaaaa:/layers",
|
"work-volume-layers:/layers",
|
||||||
"pack-app-aaaaaaaaaa:/workspace",
|
"work-volume-app:/workspace",
|
||||||
"build-volume:/cache",
|
"build-volume:/cache",
|
||||||
"launch-volume:/launch-cache"
|
"launch-volume:/launch-cache"
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -193,14 +193,22 @@ The value supplied will be passed unvalidated to Docker when creating the builde
|
||||||
The values provided to the `tags` option should be full image references in the form of `[image name]:[tag]` or `[repository]/[image name]:[tag]`.
|
The values provided to the `tags` option should be full image references in the form of `[image name]:[tag]` or `[repository]/[image name]:[tag]`.
|
||||||
|
|
|
|
||||||
|
|
||||||
|
| `buildWorkspace`
|
||||||
|
|
|
||||||
|
| A temporary workspace that will be used by the builder and buildpacks to store files during image building.
|
||||||
|
The value can be a named volume or a bind mount location.
|
||||||
|
| A named volume in the Docker daemon, with a name derived from the image name.
|
||||||
|
|
||||||
| `buildCache`
|
| `buildCache`
|
||||||
|
|
|
|
||||||
| A cache containing layers created by buildpacks and used by the image building process.
|
| A cache containing layers created by buildpacks and used by the image building process.
|
||||||
|
The value can be a named volume or a bind mount location.
|
||||||
| A named volume in the Docker daemon, with a name derived from the image name.
|
| A named volume in the Docker daemon, with a name derived from the image name.
|
||||||
|
|
||||||
| `launchCache`
|
| `launchCache`
|
||||||
|
|
|
|
||||||
| A cache containing layers created by buildpacks and used by the image launching process.
|
| A cache containing layers created by buildpacks and used by the image launching process.
|
||||||
|
The value can be a named volume or a bind mount location.
|
||||||
| A named volume in the Docker daemon, with a name derived from the image name.
|
| A named volume in the Docker daemon, with a name derived from the image name.
|
||||||
|
|
||||||
| `createdDate`
|
| `createdDate`
|
||||||
|
|
@ -420,7 +428,7 @@ The publish option can be specified on the command line as well, as shown in thi
|
||||||
----
|
----
|
||||||
|
|
||||||
[[build-image.examples.caches]]
|
[[build-image.examples.caches]]
|
||||||
=== Builder Cache Configuration
|
=== Builder Cache and Workspace Configuration
|
||||||
|
|
||||||
The CNB builder caches layers that are used when building and launching an image.
|
The CNB builder caches layers that are used when building and launching an image.
|
||||||
By default, these caches are stored as named volumes in the Docker daemon with names that are derived from the full name of the target image.
|
By default, these caches are stored as named volumes in the Docker daemon with names that are derived from the full name of the target image.
|
||||||
|
|
@ -440,7 +448,10 @@ include::../gradle/packaging/boot-build-image-caches.gradle[tags=caches]
|
||||||
include::../gradle/packaging/boot-build-image-caches.gradle.kts[tags=caches]
|
include::../gradle/packaging/boot-build-image-caches.gradle.kts[tags=caches]
|
||||||
----
|
----
|
||||||
|
|
||||||
The caches can be configured to use bind mounts instead of named volumes, as shown in the following example:
|
Builders and buildpacks need a location to store temporary files during image building.
|
||||||
|
By default, this temporary build workspace is stored in a named volume.
|
||||||
|
|
||||||
|
The caches and the build workspace can be configured to use bind mounts instead of named volumes, as shown in the following example:
|
||||||
|
|
||||||
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
|
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
|
||||||
.Groovy
|
.Groovy
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ tasks.named("bootJar") {
|
||||||
|
|
||||||
// tag::caches[]
|
// tag::caches[]
|
||||||
tasks.named("bootBuildImage") {
|
tasks.named("bootBuildImage") {
|
||||||
|
buildWorkspace {
|
||||||
|
bind {
|
||||||
|
source = "/tmp/cache-${rootProject.name}.work"
|
||||||
|
}
|
||||||
|
}
|
||||||
buildCache {
|
buildCache {
|
||||||
bind {
|
bind {
|
||||||
source = "/tmp/cache-${rootProject.name}.build"
|
source = "/tmp/cache-${rootProject.name}.build"
|
||||||
|
|
@ -24,6 +29,7 @@ tasks.named("bootBuildImage") {
|
||||||
|
|
||||||
tasks.register("bootBuildImageCaches") {
|
tasks.register("bootBuildImageCaches") {
|
||||||
doFirst {
|
doFirst {
|
||||||
|
bootBuildImage.buildWorkspace.asCache().with { print "buildWorkspace=$source" }
|
||||||
bootBuildImage.buildCache.asCache().with { println "buildCache=$source" }
|
bootBuildImage.buildCache.asCache().with { println "buildCache=$source" }
|
||||||
bootBuildImage.launchCache.asCache().with { println "launchCache=$source" }
|
bootBuildImage.launchCache.asCache().with { println "launchCache=$source" }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,11 @@ plugins {
|
||||||
|
|
||||||
// tag::caches[]
|
// tag::caches[]
|
||||||
tasks.named<BootBuildImage>("bootBuildImage") {
|
tasks.named<BootBuildImage>("bootBuildImage") {
|
||||||
|
buildWorkspace {
|
||||||
|
bind {
|
||||||
|
source.set("/tmp/cache-${rootProject.name}.work")
|
||||||
|
}
|
||||||
|
}
|
||||||
buildCache {
|
buildCache {
|
||||||
bind {
|
bind {
|
||||||
source.set("/tmp/cache-${rootProject.name}.build")
|
source.set("/tmp/cache-${rootProject.name}.build")
|
||||||
|
|
@ -22,6 +27,7 @@ tasks.named<BootBuildImage>("bootBuildImage") {
|
||||||
|
|
||||||
tasks.register("bootBuildImageCaches") {
|
tasks.register("bootBuildImageCaches") {
|
||||||
doFirst {
|
doFirst {
|
||||||
|
println("buildWorkspace=" + tasks.getByName<BootBuildImage>("bootBuildImage").buildWorkspace.asCache().bind.source)
|
||||||
println("buildCache=" + tasks.getByName<BootBuildImage>("bootBuildImage").buildCache.asCache().bind.source)
|
println("buildCache=" + tasks.getByName<BootBuildImage>("bootBuildImage").buildCache.asCache().bind.source)
|
||||||
println("launchCache=" + tasks.getByName<BootBuildImage>("bootBuildImage").launchCache.asCache().bind.source)
|
println("launchCache=" + tasks.getByName<BootBuildImage>("bootBuildImage").launchCache.asCache().bind.source)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,8 @@ public abstract class BootBuildImage extends DefaultTask {
|
||||||
|
|
||||||
private final String projectName;
|
private final String projectName;
|
||||||
|
|
||||||
|
private final CacheSpec buildWorkspace;
|
||||||
|
|
||||||
private final CacheSpec buildCache;
|
private final CacheSpec buildCache;
|
||||||
|
|
||||||
private final CacheSpec launchCache;
|
private final CacheSpec launchCache;
|
||||||
|
|
@ -91,6 +93,7 @@ public abstract class BootBuildImage extends DefaultTask {
|
||||||
getCleanCache().convention(false);
|
getCleanCache().convention(false);
|
||||||
getVerboseLogging().convention(false);
|
getVerboseLogging().convention(false);
|
||||||
getPublish().convention(false);
|
getPublish().convention(false);
|
||||||
|
this.buildWorkspace = getProject().getObjects().newInstance(CacheSpec.class);
|
||||||
this.buildCache = getProject().getObjects().newInstance(CacheSpec.class);
|
this.buildCache = getProject().getObjects().newInstance(CacheSpec.class);
|
||||||
this.launchCache = getProject().getObjects().newInstance(CacheSpec.class);
|
this.launchCache = getProject().getObjects().newInstance(CacheSpec.class);
|
||||||
this.docker = getProject().getObjects().newInstance(DockerSpec.class);
|
this.docker = getProject().getObjects().newInstance(DockerSpec.class);
|
||||||
|
|
@ -222,6 +225,25 @@ public abstract class BootBuildImage extends DefaultTask {
|
||||||
@Option(option = "network", description = "Connect detect and build containers to network")
|
@Option(option = "network", description = "Connect detect and build containers to network")
|
||||||
public abstract Property<String> getNetwork();
|
public abstract Property<String> getNetwork();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the build temporary workspace that will be used when building the image.
|
||||||
|
* @return the cache
|
||||||
|
*/
|
||||||
|
@Nested
|
||||||
|
@Optional
|
||||||
|
public CacheSpec getBuildWorkspace() {
|
||||||
|
return this.buildWorkspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customizes the {@link CacheSpec} for the build temporary workspace using the given
|
||||||
|
* {@code action}.
|
||||||
|
* @param action the action
|
||||||
|
*/
|
||||||
|
public void buildWorkspace(Action<CacheSpec> action) {
|
||||||
|
action.execute(this.buildWorkspace);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the build cache that will be used when building the image.
|
* Returns the build cache that will be used when building the image.
|
||||||
* @return the cache
|
* @return the cache
|
||||||
|
|
@ -400,6 +422,9 @@ public abstract class BootBuildImage extends DefaultTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
private BuildRequest customizeCaches(BuildRequest request) {
|
private BuildRequest customizeCaches(BuildRequest request) {
|
||||||
|
if (this.buildWorkspace.asCache() != null) {
|
||||||
|
request = request.withBuildWorkspace((this.buildWorkspace.asCache()));
|
||||||
|
}
|
||||||
if (this.buildCache.asCache() != null) {
|
if (this.buildCache.asCache() != null) {
|
||||||
request = request.withBuildCache(this.buildCache.asCache());
|
request = request.withBuildCache(this.buildCache.asCache());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -343,7 +343,8 @@ class PackagingDocumentationTests {
|
||||||
void bootBuildImageWithBindCaches() {
|
void bootBuildImageWithBindCaches() {
|
||||||
BuildResult result = this.gradleBuild.script("src/docs/gradle/packaging/boot-build-image-bind-caches")
|
BuildResult result = this.gradleBuild.script("src/docs/gradle/packaging/boot-build-image-bind-caches")
|
||||||
.build("bootBuildImageCaches");
|
.build("bootBuildImageCaches");
|
||||||
assertThat(result.getOutput()).containsPattern("buildCache=/tmp/cache-gradle-[\\d]+.build")
|
assertThat(result.getOutput()).containsPattern("buildWorkspace=/tmp/cache-gradle-[\\d]+.work")
|
||||||
|
.containsPattern("buildCache=/tmp/cache-gradle-[\\d]+.build")
|
||||||
.containsPattern("launchCache=/tmp/cache-gradle-[\\d]+.launch");
|
.containsPattern("launchCache=/tmp/cache-gradle-[\\d]+.launch");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ java {
|
||||||
bootBuildImage {
|
bootBuildImage {
|
||||||
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.2"
|
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.2"
|
||||||
pullPolicy = "IF_NOT_PRESENT"
|
pullPolicy = "IF_NOT_PRESENT"
|
||||||
|
buildWorkspace {
|
||||||
|
bind {
|
||||||
|
source = System.getProperty('java.io.tmpdir') + "/junit-image-pack-${rootProject.name}-work"
|
||||||
|
}
|
||||||
|
}
|
||||||
buildCache {
|
buildCache {
|
||||||
bind {
|
bind {
|
||||||
source = System.getProperty('java.io.tmpdir') + "/junit-image-cache-${rootProject.name}-build"
|
source = System.getProperty('java.io.tmpdir') + "/junit-image-cache-${rootProject.name}-build"
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ java {
|
||||||
bootBuildImage {
|
bootBuildImage {
|
||||||
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.2"
|
builder = "projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.2"
|
||||||
pullPolicy = "IF_NOT_PRESENT"
|
pullPolicy = "IF_NOT_PRESENT"
|
||||||
|
buildWorkspace {
|
||||||
|
volume {
|
||||||
|
name = "pack-${rootProject.name}.work"
|
||||||
|
}
|
||||||
|
}
|
||||||
buildCache {
|
buildCache {
|
||||||
volume {
|
volume {
|
||||||
name = "cache-${rootProject.name}.build"
|
name = "cache-${rootProject.name}.build"
|
||||||
|
|
|
||||||
|
|
@ -202,12 +202,19 @@ The value supplied will be passed unvalidated to Docker when creating the builde
|
||||||
The values provided to the `tags` option should be full image references in the form of `[image name]:[tag]` or `[repository]/[image name]:[tag]`.
|
The values provided to the `tags` option should be full image references in the form of `[image name]:[tag]` or `[repository]/[image name]:[tag]`.
|
||||||
|
|
|
|
||||||
|
|
||||||
|
| `buildWorkspace`
|
||||||
|
| A temporary workspace that will be used by the builder and buildpacks to store files during image building.
|
||||||
|
The value can be a named volume or a bind mount location.
|
||||||
|
| A named volume in the Docker daemon, with a name derived from the image name.
|
||||||
|
|
||||||
| `buildCache`
|
| `buildCache`
|
||||||
| A cache containing layers created by buildpacks and used by the image building process.
|
| A cache containing layers created by buildpacks and used by the image building process.
|
||||||
|
The value can be a named volume or a bind mount location.
|
||||||
| A named volume in the Docker daemon, with a name derived from the image name.
|
| A named volume in the Docker daemon, with a name derived from the image name.
|
||||||
|
|
||||||
| `launchCache`
|
| `launchCache`
|
||||||
| A cache containing layers created by buildpacks and used by the image launching process.
|
| A cache containing layers created by buildpacks and used by the image launching process.
|
||||||
|
The value can be a named volume or a bind mount location.
|
||||||
| A named volume in the Docker daemon, with a name derived from the image name.
|
| A named volume in the Docker daemon, with a name derived from the image name.
|
||||||
|
|
||||||
| `createdDate` +
|
| `createdDate` +
|
||||||
|
|
@ -403,7 +410,7 @@ include::../maven/packaging-oci-image/docker-pom-authentication-command-line.xml
|
||||||
----
|
----
|
||||||
|
|
||||||
[[build-image.examples.caches]]
|
[[build-image.examples.caches]]
|
||||||
=== Builder Cache Configuration
|
=== Builder Cache and Workspace Configuration
|
||||||
|
|
||||||
The CNB builder caches layers that are used when building and launching an image.
|
The CNB builder caches layers that are used when building and launching an image.
|
||||||
By default, these caches are stored as named volumes in the Docker daemon with names that are derived from the full name of the target image.
|
By default, these caches are stored as named volumes in the Docker daemon with names that are derived from the full name of the target image.
|
||||||
|
|
@ -416,7 +423,10 @@ The cache volumes can be configured to use alternative names to give more contro
|
||||||
include::../maven/packaging-oci-image/caches-pom.xml[tags=caches]
|
include::../maven/packaging-oci-image/caches-pom.xml[tags=caches]
|
||||||
----
|
----
|
||||||
|
|
||||||
The caches can be configured to use bind mounts instead of named volumes, as shown in the following example:
|
Builders and buildpacks need a location to store temporary files during image building.
|
||||||
|
By default, this temporary build workspace is stored in a named volume.
|
||||||
|
|
||||||
|
The caches and the build workspace can be configured to use bind mounts instead of named volumes, as shown in the following example:
|
||||||
|
|
||||||
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
||||||
----
|
----
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<image>
|
<image>
|
||||||
|
<buildWorkspace>
|
||||||
|
<bind>
|
||||||
|
<source>/tmp/cache-${project.artifactId}.work</source>
|
||||||
|
</bind>
|
||||||
|
</buildWorkspace>
|
||||||
<buildCache>
|
<buildCache>
|
||||||
<bind>
|
<bind>
|
||||||
<source>/tmp/cache-${project.artifactId}.build</source>
|
<source>/tmp/cache-${project.artifactId}.build</source>
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,11 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<image>
|
<image>
|
||||||
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.2</builder>
|
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.2</builder>
|
||||||
|
<buildWorkspace>
|
||||||
|
<bind>
|
||||||
|
<source>${java.io.tmpdir}/junit-image-cache-${test-build-id}-work</source>
|
||||||
|
</bind>
|
||||||
|
</buildWorkspace>
|
||||||
<buildCache>
|
<buildCache>
|
||||||
<bind>
|
<bind>
|
||||||
<source>${java.io.tmpdir}/junit-image-cache-${test-build-id}-build</source>
|
<source>${java.io.tmpdir}/junit-image-cache-${test-build-id}-build</source>
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,11 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<image>
|
<image>
|
||||||
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.2</builder>
|
<builder>projects.registry.vmware.com/springboot/spring-boot-cnb-builder:0.0.2</builder>
|
||||||
|
<buildWorkspace>
|
||||||
|
<volume>
|
||||||
|
<name>cache-${test-build-id}.work</name>
|
||||||
|
</volume>
|
||||||
|
</buildWorkspace>
|
||||||
<buildCache>
|
<buildCache>
|
||||||
<volume>
|
<volume>
|
||||||
<name>cache-${test-build-id}.build</name>
|
<name>cache-${test-build-id}.build</name>
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,8 @@ public class Image {
|
||||||
|
|
||||||
List<String> tags;
|
List<String> tags;
|
||||||
|
|
||||||
|
CacheInfo buildWorkspace;
|
||||||
|
|
||||||
CacheInfo buildCache;
|
CacheInfo buildCache;
|
||||||
|
|
||||||
CacheInfo launchCache;
|
CacheInfo launchCache;
|
||||||
|
|
@ -243,6 +245,9 @@ public class Image {
|
||||||
if (!CollectionUtils.isEmpty(this.tags)) {
|
if (!CollectionUtils.isEmpty(this.tags)) {
|
||||||
request = request.withTags(this.tags.stream().map(ImageReference::of).toList());
|
request = request.withTags(this.tags.stream().map(ImageReference::of).toList());
|
||||||
}
|
}
|
||||||
|
if (this.buildWorkspace != null) {
|
||||||
|
request = request.withBuildWorkspace(this.buildWorkspace.asCache());
|
||||||
|
}
|
||||||
if (this.buildCache != null) {
|
if (this.buildCache != null) {
|
||||||
request = request.withBuildCache(this.buildCache.asCache());
|
request = request.withBuildCache(this.buildCache.asCache());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,14 @@ class ImageTests {
|
||||||
ImageReference.of("example.com/my-app:0.0.1-SNAPSHOT"), ImageReference.of("example.com/my-app:latest"));
|
ImageReference.of("example.com/my-app:0.0.1-SNAPSHOT"), ImageReference.of("example.com/my-app:latest"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getBuildRequestWhenHasBuildWorkspaceVolumeUsesWorkspace() {
|
||||||
|
Image image = new Image();
|
||||||
|
image.buildWorkspace = CacheInfo.fromVolume(new VolumeCacheInfo("build-work-vol"));
|
||||||
|
BuildRequest request = image.getBuildRequest(createArtifact(), mockApplicationContent());
|
||||||
|
assertThat(request.getBuildWorkspace()).isEqualTo(Cache.volume("build-work-vol"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getBuildRequestWhenHasBuildCacheVolumeUsesCache() {
|
void getBuildRequestWhenHasBuildCacheVolumeUsesCache() {
|
||||||
Image image = new Image();
|
Image image = new Image();
|
||||||
|
|
@ -186,6 +194,14 @@ class ImageTests {
|
||||||
assertThat(request.getLaunchCache()).isEqualTo(Cache.volume("launch-cache-vol"));
|
assertThat(request.getLaunchCache()).isEqualTo(Cache.volume("launch-cache-vol"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getBuildRequestWhenHasBuildWorkspaceBindUsesWorkspace() {
|
||||||
|
Image image = new Image();
|
||||||
|
image.buildWorkspace = CacheInfo.fromBind(new BindCacheInfo("build-work-dir"));
|
||||||
|
BuildRequest request = image.getBuildRequest(createArtifact(), mockApplicationContent());
|
||||||
|
assertThat(request.getBuildWorkspace()).isEqualTo(Cache.bind("build-work-dir"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getBuildRequestWhenHasBuildCacheBindUsesCache() {
|
void getBuildRequestWhenHasBuildCacheBindUsesCache() {
|
||||||
Image image = new Image();
|
Image image = new Image();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue