Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip docker save if docker daemon base image is cached #2049

Merged
merged 17 commits into from
Oct 16, 2019
Merged
1 change: 1 addition & 0 deletions jib-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.

- Local base image layers are now processed in parallel, speeding up builds using large local base images. ([#1913](https://github.com/GoogleContainerTools/jib/issues/1913))
- The base image manifest is no longer pulled from the registry if a digest is provided and the manifest is already cached. ([#1881](https://github.com/GoogleContainerTools/jib/issues/1881))
- Docker daemon base images are now cached more effectively, speeding up builds `DockerDaemonImage` base images. ([#1912](https://github.com/GoogleContainerTools/jib/issues/1912))
TadCordle marked this conversation as resolved.
Show resolved Hide resolved

### Fixed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.google.cloud.tools.jib.cache.CachedLayer;
import com.google.cloud.tools.jib.configuration.BuildConfiguration;
import com.google.cloud.tools.jib.docker.DockerClient;
import com.google.cloud.tools.jib.docker.DockerClient.DockerImageDetails;
import com.google.cloud.tools.jib.docker.json.DockerManifestEntryTemplate;
import com.google.cloud.tools.jib.event.progress.ThrottledAccumulatingConsumer;
import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider;
Expand All @@ -48,6 +49,7 @@
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.DigestException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -103,6 +105,13 @@ static Callable<LocalImage> retrieveDockerDaemonImageStep(
new TimerEventDispatcher(
buildConfiguration.getEventHandlers(),
"Saving " + imageReference + " from Docker daemon")) {
DockerClient.DockerImageDetails dockerImageDetails = dockerClient.inspect(imageReference);
Optional<LocalImage> cachedImage =
getCachedDockerImage(buildConfiguration.getBaseImageLayersCache(), dockerImageDetails);
if (cachedImage.isPresent()) {
return cachedImage.get();
}

Path tarPath = tempDirectoryProvider.newDirectory().resolve("out.tar");
long size = dockerClient.inspect(imageReference).getSize();
try (ProgressEventDispatcher dockerProgress =
Expand Down Expand Up @@ -133,6 +142,39 @@ static Callable<LocalImage> retrieveTarImageStep(
buildConfiguration, executorService, tarPath, progressEventDispatcherFactory);
}

private static Optional<LocalImage> getCachedDockerImage(
Cache cache, DockerImageDetails dockerImageDetails)
throws DigestException, IOException, CacheCorruptedException, LayerCountMismatchException,
BadContainerConfigurationFormatException {
V22ManifestTemplate v22Manifest = new V22ManifestTemplate();
List<PreparedLayer> cachedLayers = new ArrayList<>();

// Get config
Optional<ContainerConfigurationTemplate> cachedConfig =
cache.retrieveLocalConfig(dockerImageDetails.getImageId());
if (!cachedConfig.isPresent()) {
return Optional.empty();
}

// Get layers
for (DescriptorDigest diffId : dockerImageDetails.getDiffIds()) {
Optional<CachedLayer> cachedLayer = cache.retrieveTarLayer(diffId);
if (!cachedLayer.isPresent()) {
return Optional.empty();
}
CachedLayer layer = cachedLayer.get();
cachedLayers.add(new PreparedLayer.Builder(layer).build());
v22Manifest.addLayer(layer.getSize(), layer.getDigest());
}

// Create manifest
ContainerConfigurationTemplate config = cachedConfig.get();
BlobDescriptor configDescriptor = Blobs.from(config).writeTo(ByteStreams.nullOutputStream());
TadCordle marked this conversation as resolved.
Show resolved Hide resolved
v22Manifest.setContainerConfiguration(configDescriptor.getSize(), configDescriptor.getDigest());
Image image = JsonToImageTranslator.toImage(v22Manifest, config);
return Optional.of(new LocalImage(image, cachedLayers));
}

@VisibleForTesting
static LocalImage cacheDockerImageTar(
BuildConfiguration buildConfiguration,
Expand All @@ -156,10 +198,12 @@ static LocalImage cacheDockerImageTar(
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
.readValue(manifestStream, DockerManifestEntryTemplate[].class)[0];
manifestStream.close();

Path configPath = destination.resolve(loadManifest.getConfig());
ContainerConfigurationTemplate configurationTemplate =
JsonTemplateMapper.readJsonFromFile(
destination.resolve(loadManifest.getConfig()),
ContainerConfigurationTemplate.class);
JsonTemplateMapper.readJsonFromFile(configPath, ContainerConfigurationTemplate.class);
BlobDescriptor originalConfigDescriptor =
Blobs.from(configPath).writeTo(ByteStreams.nullOutputStream());

List<String> layerFiles = loadManifest.getLayerFiles();
if (configurationTemplate.getLayerCount() != layerFiles.size()) {
Expand All @@ -170,6 +214,9 @@ static LocalImage cacheDockerImageTar(
+ configurationTemplate.getLayerCount()
+ " layers");
}
buildConfiguration
.getBaseImageLayersCache()
.writeLocalConfig(originalConfigDescriptor.getDigest(), configurationTemplate);

// Check the first layer to see if the layers are compressed already. 'docker save' output
// is uncompressed, but a jib-built tar has compressed layers.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public CachedLayer writeTarLayer(DescriptorDigest diffId, Blob compressedBlob)
* @param containerConfiguration the container configuration
* @throws IOException if an I/O exception occurs
*/
void writeLocalConfig(
public void writeLocalConfig(
DescriptorDigest imageId, ContainerConfigurationTemplate containerConfiguration)
throws IOException {
cacheStorageWriter.writeLocalConfig(imageId, containerConfiguration);
Expand Down
1 change: 1 addition & 0 deletions jib-gradle-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.

- Local base image layers are now processed in parallel, speeding up builds using large local base images. ([#1913](https://github.com/GoogleContainerTools/jib/issues/1913))
- The base image manifest is no longer pulled from the registry if a digest is provided and the manifest is already cached. ([#1881](https://github.com/GoogleContainerTools/jib/issues/1881))
- Docker daemon base images are now cached more effectively, speeding up builds `docker://` base images. ([#1912](https://github.com/GoogleContainerTools/jib/issues/1912))

### Fixed

Expand Down
1 change: 1 addition & 0 deletions jib-maven-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.

- Local base image layers are now processed in parallel, speeding up builds using large local base images. ([#1913](https://github.com/GoogleContainerTools/jib/issues/1913))
- The base image manifest is no longer pulled from the registry if a digest is provided and the manifest is already cached. ([#1881](https://github.com/GoogleContainerTools/jib/issues/1881))
- Docker daemon base images are now cached more effectively, speeding up builds `docker://` base images. ([#1912](https://github.com/GoogleContainerTools/jib/issues/1912))

### Fixed

Expand Down