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

Add filtering #777

Merged
merged 3 commits into from
May 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion samples/dockerfile/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@
<relativePath>../pom.xml</relativePath>
</parent>


<artifactId>dockerfile</artifactId>
<version>0.20-SNAPSHOT</version>
<packaging>war</packaging>
<name>dmp-sample-dockerfile</name>

<properties>
<file>welcome.txt</file>
<base>jetty</base>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
Expand Down Expand Up @@ -52,6 +56,7 @@
<name>fabric8:dmp-sample-dockerfile</name>
<alias>dockerfile</alias>
<build>
<filter>@</filter>
<dockerFileDir>${project.basedir}/src/main/docker</dockerFileDir>
<assembly>
<descriptorRef>rootWar</descriptorRef>
Expand Down
6 changes: 3 additions & 3 deletions samples/dockerfile/src/main/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Sample Dockerfile for use with the Docker file mode
FROM jetty
FROM @base@

ENV SAMPLE_BUILD_MODE=dockerfile
LABEL PROJECT_NAME=hello-world

# Arbitrary files can be added
ADD welcome.txt /
ADD @file@ /

# In maven/ the files as specified in the <assembly> section is stored
# and need to be added manually
COPY maven/ /var/lib/jetty/webapps/

EXPOSE 8080
EXPOSE 8080
1 change: 1 addition & 0 deletions samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<module>custom-net</module>
<module>volume</module>
<module>properties</module>
<module>dockerfile</module>
<module>dockerignore</module>
<module>docker-compose</module>
<module>data-jolokia</module>
Expand Down
16 changes: 14 additions & 2 deletions src/main/asciidoc/inc/build/_configuration.adoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

All build relevant configuration is contained in the `<build>` section
of an image configuration. In addition to `<dockerFileDir>` and
`<dockerFile>` the following configuration options are available:
of an image configuration. The following configuration options are supported:

[[config-image-build]]
.Build configuration (<<config-image, <image> >>)
Expand Down Expand Up @@ -32,12 +31,25 @@ https://docs.docker.com/engine/reference/api/docker_remote_api_v1.24/#build-imag
| *compression*
| The compression mode how the build archive is transmitted to the docker daemon (`{plugin}:build`) and how docker build archives are attached to this build as sources (`{plugin}:source`). The value can be `none` (default), `gzip` or `bzip2`.

| *dockerFile*
| Path to a `Dockerfile` which also triggers _Dockerfile mode_. See <<external-dockerfile, External Dockerfile>> for details.

| *dockerFileDir*
| Path to a directory holding a `Dockerfile` and switch on _Dockerfile mode_. See <<external-dockerfile, External Dockerfile>> for details.


| *dockerArchive*
| Path to a saved image archive which is then imported. See <<external-dockerfile, Docker archive>> for details.

| <<misc-startup, *entryPoint*>>
| An entrypoint allows you to configure a container that will run as an executable. See <<misc-startup,Startup Arguments>> for details.

| <<misc-env, *env*>>
| The environments as described in <<misc-env,Setting Environment Variables and Labels>>.

| *filter*
| Enable and set the delimiters for property replacements. By default properties in the format `${..}` are replaced with Maven properties. You can switch off property replacement by setting this property to `false`. When using a single char like `@` then this is used as a delimiter (e.g `@...@`). See <<build-filtering, Filtering>> for more details.

| [[build-config-from]]*from*
| The base image which should be used for this image. If not given this default to `busybox:latest` and is suitable for a pure data image.
ifeval::["{plugin}" == "fabric8"]
Expand Down
24 changes: 19 additions & 5 deletions src/main/asciidoc/inc/build/_overview.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Alternatively an external Dockerfile template or Docker archive can be used. Thi

All paths can be either absolute or relative paths (except when both `dockerFileDir` and `dockerFile` are provided in which case `dockerFile` must not be absolute). A relative path is looked up in `${project.basedir}/src/main/docker` by default. You can make it easily an absolute path by using `${project.basedir}` in your configuration.

.Adding assemblies in Dockerfile mode
Any additional files located in the `dockerFileDir` directory will also be added to the build context as well.
You can also use an assembly if specified in an <<build-assembly,assembly configuration>>.
However you need to add the files on your own in the Dockerfile with an `ADD` or `COPY` command.
Expand All @@ -38,14 +39,26 @@ If this directory contains a `.maven-dockerinclude` file, then it is used for in

Except for the <<build-assembly,assembly configuration>> all other configuration options are ignored for now.

****
For the future it is planned to introduce special keywords like `DMP_ADD_ASSEMBLY` which can be used in the Dockerfile template to placing the configuration resulting from the additional configuration.
****
[[build-filtering]]
.Filtering
fabric8-maven-plugin filters given Dockerfile with Maven properties, much like the `maven-resource-plugin` does. Filtering is enabled by default and can be switched off with a build config `<filter>false</filter>`. Properties which we want to replace are specified with the `${..}` syntax.
Only properties which are set in the Maven build are replaced, all other remain untouched.

The following example uses a Dockerfile in the directory
`src/main/docker/demo`:
This partial replacement means that you can easily mix it with Docker build arguments and environment variable reference, but you need to be careful.
If you want to be more explicit about the property delimiter to clearly separate Docker properties and Maven properties you can redefine the delimiter.
In general, the `filter` option can be specified the same way as delimiters in the resource plugin.
In particular, if this configuration contains a * then the parts left, and right of the asterisks are used as delimiters.

For example, the default `<filter>${*}</filter>` parse Maven properties in the format that we know.
If you specify a single character for `<filter>` then this delimiter is taken for both, the start and the end.
E.g a `<filter>@</filter>` triggers on parameters in the format `@...@`, much like in the `maven-invoker-plugin`.
Use something like this if you want to clearly separate from Docker builds args.
Property replacement works for Dockerfile only.
For replacing other data in associated files targeted for the Docker image, please use the maven-resource-plugin to copy them over before.

.Example
The following example uses a Dockerfile in the directory
`src/main/docker/demo` and replaces all properties in the format `@property@` within the Dockerfile.
[source,xml]
----
<plugin>
Expand All @@ -55,6 +68,7 @@ The following example uses a Dockerfile in the directory
<name>user/demo</name>
<build>
<dockerFileDir>demo</dockerFileDir>
<filter>@</filter>
</build>
</image>
</images>
Expand Down
3 changes: 3 additions & 0 deletions src/main/asciidoc/inc/external/_property_configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ when a `docker.from` or a `docker.fromExt` is set.
| *docker.extraHosts.idx*
| List of `host:ip` to add to `/etc/hosts`

| *docker.filter*
| Enable and set the delimiters for property replacements. By default properties in the format `${..}` are replaced with Maven properties. You can switch off property replacement by setting this property to `false`. When using a single char like `@` then this is used as a delimiter (e.g `@...@`). See <<build-filtering, Filtering>> for more details.

| *docker.from*
| Base image for building an image. Must be set when an image is created (or `fromExt`)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package io.fabric8.maven.docker.assembly;

import java.io.*;
import java.util.*;

import io.fabric8.maven.docker.config.*;
import io.fabric8.maven.docker.util.EnvUtil;
import io.fabric8.maven.docker.util.Logger;
import io.fabric8.maven.docker.util.MojoParameters;
import io.fabric8.maven.docker.util.*;
import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Build;
import org.apache.maven.plugin.MojoExecutionException;
Expand All @@ -28,12 +30,6 @@
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/**
* Tool for creating a docker image tar ball including a Dockerfile for building
Expand All @@ -52,6 +48,7 @@ public class DockerAssemblyManager {
public static final String DOCKER_IGNORE = ".maven-dockerignore";
public static final String DOCKER_EXCLUDE = ".maven-dockerexclude";
public static final String DOCKER_INCLUDE = ".maven-dockerinclude";
public static final String DOCKERFILE_NAME = "Dockerfile";

@Requirement
private AssemblyArchiver assemblyArchiver;
Expand Down Expand Up @@ -97,15 +94,17 @@ public File createDockerTarArchive(String imageName, MojoParameters params, Buil
buildConfig.getDockerFile() + "\" (resolved to \"" + dockerFile + "\") doesn't exist");
}

verifyGivenDockerfile(dockerFile, buildConfig, log);

verifyGivenDockerfile(dockerFile, buildConfig, params.getProject(), log);
final File interpolatedDockerFile = interpolateDockerfile(dockerFile, buildDirs, params.getProject().getProperties(), buildConfig.getFilter());
// User dedicated Dockerfile from extra directory
customizer = new ArchiverCustomizer() {
@Override
public TarArchiver customize(TarArchiver archiver) throws IOException {
DefaultFileSet fileSet = DefaultFileSet.fileSet(dockerFile.getParentFile());
addDockerIgnoreIfPresent(fileSet);
excludeDockerfile(fileSet, dockerFile);
archiver.addFileSet(fileSet);
archiver.addFile(interpolatedDockerFile, DOCKERFILE_NAME);
return archiver;
}
};
Expand All @@ -114,11 +113,11 @@ public TarArchiver customize(TarArchiver archiver) throws IOException {
DockerFileBuilder builder = createDockerFileBuilder(buildConfig, assemblyConfig);
builder.write(buildDirs.getOutputDirectory());
// Add own Dockerfile
final File dockerFile = new File(buildDirs.getOutputDirectory(),"Dockerfile");
final File dockerFile = new File(buildDirs.getOutputDirectory(), DOCKERFILE_NAME);
customizer = new ArchiverCustomizer() {
@Override
public TarArchiver customize(TarArchiver archiver) throws IOException {
archiver.addFile(dockerFile, "Dockerfile");
archiver.addFile(dockerFile, DOCKERFILE_NAME);
return archiver;
}
};
Expand All @@ -135,12 +134,45 @@ public TarArchiver customize(TarArchiver archiver) throws IOException {
return createBuildTarBall(buildDirs, customizer, assemblyConfig, buildConfig.getCompression());

} catch (IOException e) {
throw new MojoExecutionException(String.format("Cannot create Dockerfile in %s", buildDirs.getOutputDirectory()), e);
throw new MojoExecutionException(String.format("Cannot create %s in %s", DOCKERFILE_NAME, buildDirs.getOutputDirectory()), e);
}
}

private void excludeDockerfile(DefaultFileSet fileSet, File dockerFile) {
ArrayList<String> excludes =
fileSet.getExcludes() != null ?
new ArrayList<>(Arrays.asList(fileSet.getExcludes())) :
new ArrayList<String>();
excludes.add(dockerFile.getName());
fileSet.setExcludes(excludes.toArray(new String[0]));
}

private File interpolateDockerfile(File dockerFile, BuildDirs params, Properties properties, String filter) throws IOException {
File targetDockerfile = new File(params.getOutputDirectory() + "/Dockerfile");
String dockerFileInterpolated =
DockerFileUtil.interpolate(dockerFile, properties, filter);
try (Writer writer = new FileWriter(targetDockerfile)) {
IOUtils.write(dockerFileInterpolated, writer);
}
return targetDockerfile;
}

private void verifyGivenDockerfile(File dockerFile, BuildImageConfiguration buildConfig, Logger log) {
// TODO: Add a warning if the Dockerfile does not contain an 'COPY' or 'ADD' for the assembly files
private void verifyGivenDockerfile(File dockerFile, BuildImageConfiguration buildConfig, MavenProject project, Logger log) throws IOException {
AssemblyConfiguration assemblyConfig = buildConfig.getAssemblyConfiguration();
if (assemblyConfig != null) {
String name = assemblyConfig.getName();
for (String keyword : new String[] { "ADD", "COPY" }) {
List<String[]> lines = DockerFileUtil.extractLines(dockerFile, keyword, project.getProperties(), buildConfig.getFilter());
for (String[] line : lines) {
// contains an ADD/COPY ... targetDir .... All good.
if (!line[0].startsWith("#") && line.length > 1 && line[1].contains(name)) {
return;
}
}
}
log.warn("Dockerfile %s does not contain an ADD or COPY directive to include assembly created at %s. Ignoring assembly.",
dockerFile.getPath(), name);
}
}

/**
Expand Down
Loading