Skip to content

Commit

Permalink
#334 : Add <arg> to BuildConfiguration for Docker args support
Browse files Browse the repository at this point in the history
This is based on the work done in #409 (thanks @	balazsmaria !) and allows the usage of ARG in external Dockerfiles.
Documentation and external property config hanlder has been updated, too.
  • Loading branch information
rhuss committed Apr 4, 2016
1 parent 8e1c7c9 commit ffe8a21
Show file tree
Hide file tree
Showing 16 changed files with 65 additions and 66 deletions.
1 change: 1 addition & 0 deletions doc/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Be more conservative when no "warnings" are returned on create (#407)
- Fix parsing of timestamps with numeric timezone (#410)
- Validate image names to fit Docker conventions (#423, #419)
- Add support for builds args in external Dockerfiles (#334)

* **0.14.2**
- Introduce a mode `try` for `<cleanup>` so that an image gets removed if not being still used.
Expand Down
8 changes: 6 additions & 2 deletions doc/manual/docker-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ of an image configuration. The available subelements are
* **entryPoint** An entrypoint allows you to configure a container that will run as an executable.
See [Start-up Arguments](#startup-arguments) for details.
* **env** holds environments as described in
[Setting Environment Variables and Labels](#setting-environment-variables-and-labels).
[Setting Environment Variables and Labels](#setting-environment-variables-and-labels).
* **args** is Map specifying the value of [Docker build args](https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables-build-arg)
which should be used when building the image with an external Dockerfile which uses build arguments.
The key-value syntax is the same as when defining Maven properties (or `labels` or `env`).
This argument is ignored when no external Dockerfile is used.
* **from** specifies 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.
Expand All @@ -33,7 +37,7 @@ of an image configuration. The available subelements are
* **runCmds** specifies commands to be run during the build process. It contains **run** elements
which are passed to bash. The run commands are inserted right after the assembly and after **workdir** in to the
Dockerfile. This tag is not to be confused with the `<run>` section for this image which specifies the runtime
behaviour when starting containers.
behaviour when starting containers.
* **optimise** if set to true then it will compress all the `runCmds` into a single RUN directive so that only one image layer is created.
* **compression** is the compression mode how the build archive is transmitted to the docker daemon (`docker:build`) and how
docker build archives are attached to this build as sources (`docker:source`). The value can be `none` (default),
Expand Down
18 changes: 10 additions & 8 deletions doc/manual/external-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ up from the following properties, which correspond to corresponding
values in the `<build>` and `<run>` sections.

* **docker.alias** Alias name
* **docker.args.BUILDVAR** Set the value of a build variable. The syntax is the same as for
specifying environment variables (see below).
* **docker.assembly.baseDir** Directory name for the exported artifacts as
described in an assembly (which is `/maven` by default).
* **docker.assembly.descriptor** Path to the assembly descriptor when
Expand All @@ -52,16 +54,14 @@ values in the `<build>` and `<run>` sections.
when creating the assembly archive
* **docker.assembly.dockerFileDir** specifies a directory containing an external Dockerfile
that will be used to create the image
* **docker.cleanup** Cleanup dangling (untagged) images after each build
(including any containers created from them). Default is `try` (which wont fail the build if removing fails),
other possible values are `none` (no cleanup) or `remove` (remove but fail if unsuccessful)
* **docker.nocache** Don't use Docker's build cache.This can be overwritten by setting a
system property `docker.nocache` when running Maven.
* **docker.optimise** if set to true then it will compress all the `runCmds` into a single RUN directive so that only
one image layer is created.
* **docker.bind.idx** Sets a list of paths to bind/expose in the container
* **docker.capAdd.idx** List of kernel capabilities to add to the container
* **docker.capDrop.idx** List of kernel capabilities to remove from the container
* **docker.cleanup** Cleanup dangling (untagged) images after each build
(including any containers created from them). Default is `try` (which wont fail the build if removing fails),
other possible values are `none` (no cleanup) or `remove` (remove but fail if unsuccessful)
* **docker.cmd** Command to execute. This is used both when
running a container and as default command when creating an image.
* **docker.domainname** Container domain name
Expand All @@ -75,13 +75,13 @@ one image layer is created.
be provided. This environment is used both for building images and
running containers. The value cannot be empty but can contain Maven property names which are
resolved before the Dockerfile is created
* **docker.labels.LABEL** Sets a label which works similarly like setting environment variables.
* **docker.envPropertyFile** specifies the path to a property file whose properties are
used as environment variables. The environment variables takes precedence over any other environment
variables specified.
* **docker.extraHosts.idx** List of `host:ip` to add to `/etc/hosts`
* **docker.from** Base image for building an image
* **docker.hostname** Container hostname
* **docker.labels.LABEL** Sets a label which works similarly like setting environment variables.
* **docker.log.enabled** Use logging (default: `true`)
* **docker.log.prefix** Output prefix
* **docker.log.color** ANSI color to use for the prefix
Expand All @@ -95,10 +95,13 @@ one image layer is created.
indexes sorted and the all non-numeric indexes in arbitrary order).
For example `<docker.links.1>db</docker.links.1>` specifies a link
to the image with alias 'db'.
* **docker.maintainer** defines the maintainer's email as used when building an image
* **docker.memory** Container memory (in bytes)
* **docker.memorySwap** Total memory (swap + memory) `-1` to disable swap
* **docker.name** Image name
* **docker.namingStrategy** Container naming (either `none` or `alias`)
* **docker.optimise** if set to true then it will compress all the `runCmds` into a single RUN directive so that only
one image layer is created.
* **docker.portPropertyFile** specifies a path to a port mapping used
when starting a container.
* **docker.ports.idx** Sets a port mapping. For example
Expand All @@ -111,10 +114,9 @@ one image layer is created.
* **docker.registry** Registry to use for pushing images.
* **docker.restartPolicy.name** Container restart policy
* **docker.restartPolicy.retry** Max restrart retries if `on-failure` used
* **docker.tags.idx** defines a list of tags to apply to a built image
* **docker.user** Container user
* **docker.volumes.idx** defines a list of volumes to expose when building an image
* **docker.tags.idx** defines a list of tags to apply to a built image
* **docker.maintainer** defines the maintainer's email as used when building an image
* **docker.volumesFrom.idx** defines a list of image aliases from which
the volumes should be mounted of the container. The list semantics
is the same as for links (see above). For examples
Expand Down
9 changes: 6 additions & 3 deletions samples/data-jolokia-demo/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

<groupId>io.fabric8</groupId>
<artifactId>docker-jolokia-demo</artifactId>
<version>0.14.2</version>
<version>0.14.3-SNAPSHOT</version>

<url>http://www.jolokia.org</url>

Expand Down Expand Up @@ -397,16 +397,19 @@
<assembly>
<dockerFileDir>demo</dockerFileDir>
</assembly>
<args>
<deploymentDir>maven</deploymentDir>
</args>
</build>
<run>
<ports>
<port>jolokia.port:8080</port>
</ports>
<wait>
<!-- The plugin waits until this URL is reachable via HTTP ... -->
<wait>
<http>
<url>http://${docker.host.address}:${jolokia.port}/jolokia</url>
</wait>
</http>
<time>10000</time>
</wait>
</run>
Expand Down
5 changes: 3 additions & 2 deletions samples/data-jolokia-demo/src/main/docker/demo/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
FROM consol/tomcat-7.0:latest
ADD jolokia.war /maven/
ADD jolokia-it.war /maven/
ARG deploymentDir
ADD jolokia.war /${deploymentDir}/
ADD jolokia-it.war /${deploymentDir}/
Binary file modified samples/data-jolokia-demo/src/main/docker/demo/jolokia-it.war
Binary file not shown.
Binary file modified samples/data-jolokia-demo/src/main/docker/demo/jolokia.war
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -66,40 +66,7 @@ protected void buildImage(ServiceHub hub, ImageConfiguration imageConfig)
autoPullBaseImage(hub, imageConfig);

MojoParameters params = createMojoParameters();
hub.getBuildService().buildImage(imageConfig, params, checkForNocache(imageConfig), addBuildArgs(imageConfig));
}

private Map<String, String> addBuildArgs(ImageConfiguration imageConfig) {
Properties properties = project.getProperties();
Properties systemProperties = System.getProperties();
Map<String, String> buildArgsFromProject = addBuildArgsFromProperties(imageConfig, properties);
Map<String, String> buildArgsFromSystem = addBuildArgsFromProperties(imageConfig, systemProperties);
buildArgsFromProject.putAll(buildArgsFromSystem);
return buildArgsFromProject;
}

private Map<String, String> addBuildArgsFromProperties(ImageConfiguration imageConfig, Properties properties) {
String argPrefix = "docker.arg.";
String imageArgPrefix = "docker.iarg.";
String aliasPrefix = imageArgPrefix + imageConfig.getAlias() + "." ;
String namePrefix = imageArgPrefix + imageConfig.getName() + "." ;
Map<String, String> buildArgs = new HashMap<>();
for(Object keyObj : properties.keySet()){
String key = (String)keyObj;
String argKey;
if (key.startsWith(argPrefix)){
argKey = key.replace(argPrefix, "");
}else if (key.startsWith(aliasPrefix)){
argKey = key.replace(aliasPrefix, "");
}else if(key.startsWith(namePrefix)){
argKey = key.replace(namePrefix, "");
}else{
continue;
}
buildArgs.put(argKey, properties.getProperty(key));
log.debug(String.format("Build args set %s", buildArgs));
}
return buildArgs;
hub.getBuildService().buildImage(imageConfig, params, checkForNocache(imageConfig));
}

private void autoPullBaseImage(ServiceHub hub, ImageConfiguration imageConfig)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ void copyArchive(String containerId, File archive, String targetPath)
* @param dockerArchive from which the docker image should be build
* @param forceRemove whether to remove intermediate containers
* @param noCache whether to use cache when building the image
* @param buildArgs buildArgs to add then building the image
* @param buildArgs buildArgs to add then building the image. Can be <code>null</code> for no build args.
* @throws DockerAccessException if docker host reports an error during building of an image
*/
void buildImage(String image, File dockerArchive, boolean forceRemove, boolean noCache,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public String buildImage(String image, boolean forceRemove, boolean noCache, Map
.p("t", image)
.p(forceRemove ? "forcerm" : "rm", true)
.p("nocache", noCache);
if (!buildArgs.isEmpty()) {
if (buildArgs != null && !buildArgs.isEmpty()) {
urlBuilder.p("buildargs", new JSONObject(buildArgs).toString());
}
return urlBuilder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,29 @@ public class BuildImageConfiguration {
private boolean optimise = false;

/**
* @paramter
* @parameter
*/
private List<String> volumes;

/**
* @paramter
* @parameter
*/
private List<String> tags;

/**
* @parameter
*/
private Map<String,String> env;
private Map<String, String> env;

/**
* @parameter
*/
private Map<String, String> labels;

/**
* @parameter
*/
private Map<String,String> labels;
private Map<String, String> args;

/**
* @parameter
Expand Down Expand Up @@ -187,6 +192,10 @@ public List<String> getRunCmds() {
return runCmds;
}

public Map<String, String> getArgs() {
return args;
}

public static class Builder {
private final BuildImageConfiguration config = new BuildImageConfiguration();

Expand Down Expand Up @@ -244,6 +253,11 @@ public Builder env(Map<String, String> env) {
return this;
}

public Builder args(Map<String, String> args) {
config.args = args;
return this;
}

public Builder labels(Map<String, String> labels) {
config.labels = labels;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
public enum ConfigKey {

ALIAS,
ARG,
ARGS,
ASSEMBLY_BASEDIR("assembly.baseDir"),
ASSEMBLY_DESCRIPTOR("assembly.descriptor"),
ASSEMBLY_DESCRIPTOR_REF("assembly.descriptorRef"),
Expand All @@ -45,41 +45,40 @@ public enum ConfigKey {
DNS_SEARCH,
ENTRYPOINT,
ENV,
LABELS,
ENV_PROPERTY_FILE,
EXTRA_HOSTS,
FROM,
HOSTNAME,
LABELS,
LINKS,
LOG_ENABLED("log.enabled"),
LOG_PREFIX("log.prefix"),
LOG_DATE("log.date"),
LOG_COLOR("log.color"),
LOG_DRIVER_NAME("log.driver.name"),
LOG_DRIVER_OPTS("log.driver.opts"),
MAINTAINER,
MEMORY,
MEMORY_SWAP,
NAME,
NAMING_STRATEGY,
NET,
PORT_PROPERTY_FILE,
PORTS,
RUN,
POST_START("wait.exec.postStart"),
PRE_STOP("wait.exec.preStop"),
PRIVILEGED,
REGISTRY,
RESTART_POLICY_NAME("restartPolicy.name"),
RESTART_POLICY_RETRY("restartPolicy.retry"),
RUN,
SKIP_BUILD("skip.build"),
SKIP_RUN("skip.run"),
TAGS,
USER,
VOLUMES,
TAGS,
MAINTAINER,
WORKDIR,
VOLUMES_FROM,
WAIT_LOG("wait.log"),
POST_START("wait.exec.postStart"),
PRE_STOP("wait.exec.preStop"),
WAIT_TIME("wait.time"),
WAIT_URL("wait.url"),
WAIT_HTTP_URL("wait.http.url"),
Expand All @@ -92,6 +91,7 @@ public enum ConfigKey {
WATCH_INTERVAL("watch.interval"),
WATCH_MODE("watch.mode"),
WATCH_POSTGOAL("watch.postGoal"),
WORKDIR,
WORKING_DIR;

ConfigKey() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ private BuildImageConfiguration extractBuildConfiguration(String prefix, Propert
.entryPoint(withPrefix(prefix, ENTRYPOINT, properties))
.assembly(extractAssembly(prefix, properties))
.env(mapWithPrefix(prefix, ENV, properties))
.args(mapWithPrefix(prefix, ARGS, properties))
.labels(mapWithPrefix(prefix,LABELS,properties))
.ports(extractPortValues(prefix, properties))
.runCmds(extractRunCommands(prefix,properties))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class BuildService {
* @throws DockerAccessException
* @throws MojoExecutionException
*/
public void buildImage(ImageConfiguration imageConfig, MojoParameters params, boolean noCache, Map<String, String> buildArgs)
public void buildImage(ImageConfiguration imageConfig, MojoParameters params, boolean noCache)
throws DockerAccessException, MojoExecutionException {

String imageName = imageConfig.getName();
Expand All @@ -56,7 +56,7 @@ public void buildImage(ImageConfiguration imageConfig, MojoParameters params, bo
String newImageId =
doBuildImage(imageName, dockerArchive,
cleanupMode.isRemove(),
noCache, buildArgs);
noCache, buildConfig.getArgs());
log.info(imageConfig.getDescription() + ": Built image " + newImageId);

if (oldImageId != null && !oldImageId.equals(newImageId)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ private void validateBuildConfiguration(BuildImageConfiguration buildConfig) {

validateEnv(buildConfig.getEnv());
validateLabels(buildConfig.getLabels());
validateArgs(buildConfig.getArgs());
/*
* validate only the descriptor is required and defaults are all used, 'testAssembly' validates
* all options can be set
Expand All @@ -224,6 +225,10 @@ private void validateBuildConfiguration(BuildImageConfiguration buildConfig) {
assertFalse(assemblyConfig.isIgnorePermissions());
}

private void validateArgs(Map<String, String> args) {
assertEquals("http://proxy",args.get("PROXY"));
}

private void validateLabels(Map<String, String> labels) {
assertEquals("Hello\"World",labels.get("com.acme.label"));
}
Expand Down Expand Up @@ -320,6 +325,7 @@ private String[] getTestData() {
k(ConfigKey.DOMAINNAME), "domain.com",
k(ConfigKey.ENTRYPOINT), "entrypoint.sh",
k(ConfigKey.ENV) + ".HOME", "/Users/roland",
k(ConfigKey.ARGS) + ".PROXY", "http://proxy",
k(ConfigKey.LABELS) + ".com.acme.label", "Hello\"World",
k(ConfigKey.ENV_PROPERTY_FILE), "/tmp/envProps.txt",
k(ConfigKey.EXTRA_HOSTS) + ".1", "localhost:127.0.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,6 @@ private void whenBuildImage(boolean cleanup, boolean nocache) throws DockerAcces
when(docker.removeImage(oldImageId)).thenReturn(true);
}

buildService.buildImage(imageConfig, params, nocache, Collections.<String, String>emptyMap());
buildService.buildImage(imageConfig, params, nocache);
}
}

0 comments on commit ffe8a21

Please sign in to comment.