Skip to content
This repository has been archived by the owner on Mar 31, 2022. It is now read-only.

Pass Maven properties as ENV values in Dockerfile #20

Closed
chrsoo opened this issue Jun 6, 2017 · 18 comments
Closed

Pass Maven properties as ENV values in Dockerfile #20

chrsoo opened this issue Jun 6, 2017 · 18 comments
Labels

Comments

@chrsoo
Copy link

chrsoo commented Jun 6, 2017

Hi,

I need to pass artifactId, groupId and other Maven properties as ENV values in the Dockerfile.

With Maven filtering I would expect the following to work after proper configuration of the Maven plugin:

ENV ARTIFACT_ID=@artifactId@ GROUP_ID=@groupId@

Would it be possible to add support for Maven filtering or is there another way I can achieve this?

As a work-around I suppose I could copy the docker file from somewhere to the project root with filtering enabled but this seems like a roundabout way to do it.

@jdmarble
Copy link

I'd prefer a way to filter the Dockerfile directly, but as a workaround, I copy with filtering.

My src/main/docker/Dockerfile:

FROM anapsix/alpine-java
ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/${project.artifactId}/${project.build.finalName}.jar"]
ADD ${project.build.finalName}.jar /usr/share/${project.artifactId}/${project.build.finalName}.jar

Relevant portion of the pom.xml:

<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.0.2</version>
    <executions>
        <execution>
            <id>filter-dockerfile</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}</outputDirectory>
                <resources>
                    <resource>
                        <directory>src/main/docker</directory>
                        <filtering>true</filtering>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.3.0</version>
    <executions>
        <execution>
            <id>default</id>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <contextDirectory>${project.build.directory}</contextDirectory>
    </configuration>
</plugin>

@bcopy
Copy link

bcopy commented Jun 29, 2017

Okay, I'm all for a more integrated experience but I cannot find any examples of how to inject maven properties and dependency info, as well as applying profiles into a Docker file (which was very easy with docker-maven-plugin).

Injecting a single maven property with copy-resources + filtering is okay for small stuff but I imagine it could get tiring.

Any hints as to the best practices to apply ?

@freesoft
Copy link
Contributor

freesoft commented Jul 1, 2017

From the answer https://stackoverflow.com/questions/23521889/how-to-get-maven-groupid-artifactid-project-version-to-the-command-line, you can get groupId and artifactId, and feed it into Dockerfile either using ARG or ENV.. could be an alternative workaround for now.

Just curious though, what's going to be the use case for this feature request?

@chrsoo
Copy link
Author

chrsoo commented Jul 1, 2017

@freesoft: in my bootstrap shell script I retrieve the configuration of my microservice from a web service. As the configuration is dependant on the GAV of my JAR file I need to somehow pass these parameters during the build phase of my Docker image.

Another related usecase is what @jdmarble illustrated in the comment above: you might want to place the jar, its configuration, log files etc in a structure that depends on which JAR you are adding.

This is useful where you have a Docker volume that is shared between multiple containers and want to avoid overwriting the files of the shared folder structure. Think having separate log files for all your Microservices.

@mattnworb
Copy link
Member

@bcopy

Injecting a single maven property with copy-resources + filtering is okay for small stuff but I imagine it could get tiring.

I believe all maven properties (as well as system properties and other things) are available when filtering via the resources plugin. Or do you mean it would be tiring if you want to inject things that are not already maven properties?

@chrsoo
Copy link
Author

chrsoo commented Jul 5, 2017

It requires additional boilerplate configuration that unnecessarily weighs down the plugin configuration.

I think filtering should be enabled per default with an option to disable filtering or optionally change the filter token.

Something like:

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.3.0</version>
    <executions>
        <execution>
            <id>default</id>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <contextDirectory>${project.build.directory}</contextDirectory>
        <!-- default value -->
        <filter>true</filter>
        <filterToken>@</filterToken>
    </configuration>
</plugin>

@arikkfir
Copy link

arikkfir commented Jul 6, 2017

👍 would be very useful for us as well.
I'm hoping to perhaps whip up a patch for this on the weekend if anyone is interested. Will post here with a pull request once ready.

@mattnworb
Copy link
Member

I believe the custom build args added in #41 should make this easier, as you can now pass things as ARGs to Dockerfile. Does this solve the need?

@chrsoo
Copy link
Author

chrsoo commented Jul 23, 2017

@freesoft I think I missed your point on using ARG's for building from your comment above.
@mattnworb I believe you would be able to do...

<configuration>
  <buildArgs>
    <artifactId>${project.artifactId}</artifactId>
    <groupId>${project.groupId}</groupId>
  </buildArgs>
</configuration>

... and then in the Dockerfile...

ARG artifactId
ARG groupId
ENV ARTIFACT_ID=${artifactId} GROUP_ID=${groupId}

This is in my opinion the better solution as it does not require any additional placeholders or preprocessing of the Dockerfile.

Also I like that the standard ARG mechanism explicitly enumerates all parameters required for the build and that the image can be created without Maven.

Closing as I believe this removes the need for filtering.

@chrsoo chrsoo closed this as completed Jul 23, 2017
@bcopy
Copy link

bcopy commented Aug 6, 2017

@chrsoo I agree that being able to build without maven is a plus, but at the very least, the plugin should provide some built-in build arguments (with or without a configurable prefix).
For instance, the build arguments and corresponding maven properties could be populated automatically

artifactId
groupId
etc...

because I honestly feel that this plug-in just intends to ignore any maven benefits and adds a really unnecessary layer for docker file handling. Using a good old templating engine and some Maven generated properties file would be less cumbersome than this approach (and still be maven independent).

@chrsoo
Copy link
Author

chrsoo commented Aug 6, 2017

@bcopy Well... They way I see it there is a simple, standard way to parameterise the Docker build and this resolves the basic case of customising a generic Dockerfile for a specific artifact.

Adding a full blown templateing engine and pre-processing would just increase the temptation to make overly complex Dockerfile templates using conditionals, import of file fragments, ... and this seems to be an anti-feature to me. Especially given the project goals which explicitly starts over on a blank page after bad experiences with a solution that was too complex.

To me there is still a lot of added value as I use the plugin to render the same basic Dockerfile for highly standardised Microservices. The only that really change are the artifact names that governs locations of log files, configuration files etc. This together with including build output as the content of the Docker image goes a long way.

This said I agree it would be nice to get even easier access to all Maven properties. You could imagine an approach that if the Dockerfile lists a build arg it would automatically use any matching Maven property, if it exists. This is what you meant, right?

@ALL what do you say about adding support for a configuration entry such as

<configuration>
  <!--
    Any Maven property prefixed with the value of 'buildArgPrefix' is matched against Dockerfile
    ENV build args. If there is a match between the property name (without the prefix) it
    is supplied as an argument to the Docker build. E.g. with the prefix 'project.' the standard 
    Maven property 'project.artifactId' would be used as a build argument for the Dockerfile
    entry

      ENV artifactId

  -->    
  <buildArgPrefix>project.</buildArgPrefix>
</configuration>

It would make some sense to make this configuration parameter multivalued to allow different hierarchies of Maven properties to be used as build args as I think there might be an issue with ENV variables containing dots...

@chrsoo chrsoo reopened this Aug 6, 2017
@bcopy
Copy link

bcopy commented Aug 6, 2017 via email

@stale
Copy link

stale bot commented Sep 24, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Sep 24, 2018
@chrsoo
Copy link
Author

chrsoo commented Sep 26, 2018

(Adding comment to prevent automatic closure by the stale bot)

This feature request is still relevant, please consider for implementation!

@stale stale bot removed the stale label Sep 26, 2018
@stale
Copy link

stale bot commented Nov 25, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Nov 25, 2018
@chrsoo
Copy link
Author

chrsoo commented Nov 27, 2018

ping

@stale stale bot removed the stale label Nov 27, 2018
@rafael-yure
Copy link

This would be very useful for my use case as well. I'm going to use the filtering workaround until then.

@stale
Copy link

stale bot commented Feb 9, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Feb 9, 2019
@stale stale bot closed this as completed Feb 16, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

7 participants