diff --git a/README.md b/README.md index 1e8df58e..4aad9472 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,31 @@ parent POM) in order for the `docker-info` type to be supported: ``` +### Clean images from Docker host after the build + +You can use the `rmi` goal (from `docker rmi`, a.k.a. `docker image +remove`) to clean up the project's image on the Docker host, so that +the storage on the host doesn't fill up. This is especially useful if +you deploy tagged images to a Docker registry from a build host where +you don't need the image anymore after the build. As with `docker +rmi`, the `dockerfile.rmi.force` option must be set to `true` when +removing tagged images. + +Set up the configuration like this to have Docker images cleaned when +executing `mvn clean`: + +```xml + + clean + + rmi + + + true + + +``` + ## Use other Docker tools that rely on Dockerfiles Your project(s) look like so: @@ -287,6 +312,7 @@ You can pass options to maven to disable the docker goals. | dockerfile.build.skip | Disables the build goal; it becomes a no-op. | | dockerfile.tag.skip | Disables the tag goal; it becomes a no-op. | | dockerfile.push.skip | Disables the push goal; it becomes a no-op. | +| dockerfile.rmi.skip | Disables the rmi goal; it becomes a no-op. | For example to skip the entire dockerfile plugin: ``` diff --git a/plugin/src/it/clean-empty-project/Dockerfile b/plugin/src/it/clean-empty-project/Dockerfile new file mode 100644 index 00000000..c1dbf151 --- /dev/null +++ b/plugin/src/it/clean-empty-project/Dockerfile @@ -0,0 +1,2 @@ +FROM scratch +MAINTAINER David Flemström \ No newline at end of file diff --git a/plugin/src/it/clean-empty-project/invoker.properties b/plugin/src/it/clean-empty-project/invoker.properties new file mode 100644 index 00000000..f2bf5e72 --- /dev/null +++ b/plugin/src/it/clean-empty-project/invoker.properties @@ -0,0 +1,21 @@ +### +# -/-/- +# Dockerfile Maven Plugin +# %% +# Copyright (C) 2015 - 2016 Spotify AB +# %% +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# -\-\- +### + +invoker.goals=clean diff --git a/plugin/src/it/clean-empty-project/pom.xml b/plugin/src/it/clean-empty-project/pom.xml new file mode 100644 index 00000000..5a133220 --- /dev/null +++ b/plugin/src/it/clean-empty-project/pom.xml @@ -0,0 +1,56 @@ + + + + + 4.0.0 + + com.spotify.it + clean-empty-project + 1.0-SNAPSHOT + + A simple IT verifying that the project can be cleaned before building anything. + + + UTF-8 + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + clean + + rmi + + + true + + + + + + + diff --git a/plugin/src/it/remove-tagged-image/Dockerfile b/plugin/src/it/remove-tagged-image/Dockerfile new file mode 100644 index 00000000..c1dbf151 --- /dev/null +++ b/plugin/src/it/remove-tagged-image/Dockerfile @@ -0,0 +1,2 @@ +FROM scratch +MAINTAINER David Flemström \ No newline at end of file diff --git a/plugin/src/it/remove-tagged-image/invoker.properties b/plugin/src/it/remove-tagged-image/invoker.properties new file mode 100644 index 00000000..53c0bbb6 --- /dev/null +++ b/plugin/src/it/remove-tagged-image/invoker.properties @@ -0,0 +1,22 @@ +### +# -/-/- +# Dockerfile Maven Plugin +# %% +# Copyright (C) 2015 - 2016 Spotify AB +# %% +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# -\-\- +### + +invoker.goals=package +invoker.goals.2=clean diff --git a/plugin/src/it/remove-tagged-image/pom.xml b/plugin/src/it/remove-tagged-image/pom.xml new file mode 100644 index 00000000..22ec2135 --- /dev/null +++ b/plugin/src/it/remove-tagged-image/pom.xml @@ -0,0 +1,65 @@ + + + + + 4.0.0 + + com.spotify.it + remove-tagged-image + 1.0-SNAPSHOT + + A simple IT verifying that tagged image IDs will can be removed. + + + UTF-8 + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + default + + build + + + test/remove-tagged-image + + + + clean + + rmi + + + true + + + + + + + diff --git a/plugin/src/main/java/com/spotify/plugin/dockerfile/RemoveImageMojo.java b/plugin/src/main/java/com/spotify/plugin/dockerfile/RemoveImageMojo.java new file mode 100644 index 00000000..2949cc7c --- /dev/null +++ b/plugin/src/main/java/com/spotify/plugin/dockerfile/RemoveImageMojo.java @@ -0,0 +1,89 @@ +/*- + * -\-\- + * Dockerfile Maven Plugin + * -- + * Copyright (C) 2016 Spotify AB + * -- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * -/-/- + */ + +package com.spotify.plugin.dockerfile; + +import com.spotify.docker.client.DockerClient; +import com.spotify.docker.client.exceptions.DockerException; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +@Mojo(name = "rmi", + defaultPhase = LifecyclePhase.PRE_CLEAN, + requiresProject = true, + threadSafe = true) +public class RemoveImageMojo extends AbstractDockerMojo { + + /** + * Whether to force removal of the image. + */ + @Parameter(property = "dockerfile.rmi.force", defaultValue = "false") + private boolean forceRemove; + + /** + * Whether to delete untagged parents. + */ + @Parameter(property = "dockerfile.rmi.prune", defaultValue = "true") + private boolean prune; + + /** + * Disables the tag goal; it becomes a no-op. + */ + @Parameter(property = "dockerfile.rmi.skip", defaultValue = "false") + private boolean skipTag; + + @Override + protected void execute(DockerClient dockerClient) + throws MojoExecutionException, MojoFailureException { + final Log log = getLog(); + + if (skipTag) { + log.info("Skipping execution because 'dockerfile.rmi.skip' is set"); + return; + } + + final String imageId = readMetadata(Metadata.IMAGE_ID); + if (imageId == null) { + log.info("No Docker image was built: Nothing to remove."); + return; + } + + final StringBuilder messageBuilder = new StringBuilder(); + messageBuilder.append("Removing image "); + messageBuilder.append(imageId); + if (forceRemove) { + messageBuilder.append(" with all tags"); + } + if (prune) { + messageBuilder.append(", deleting untagged parents"); + } + log.info(messageBuilder.toString()); + + try { + dockerClient.removeImage(imageId, forceRemove, !prune); + } catch (DockerException | InterruptedException e) { + throw new MojoExecutionException("Could not remove Docker image", e); + } + } +}