Reputation: 221
I'm using spotify's docker-maven-plugin for building a docker image. More exactly this one:
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
My development machine has a Windows 7, so I'm running docker machine with version docker-machine version 0.9.0, build 15fd4c7
Docker version is this
Client:
Version: 1.13.1
API version: 1.26
Go version: go1.7.5
Git commit: 092cba3
Built: Wed Feb 8 08:47:51 2017
OS/Arch: windows/amd64
Server:
Version: 17.03.0-ce
API version: 1.26 (minimum version 1.12)
Go version: go1.7.5
Git commit: 3a232c8
Built: Tue Feb 28 07:52:04 2017
OS/Arch: linux/amd64
Experimental: false
My application uses a certificate which I want to prepare in advance and include in the image.
If I build the Docker image directly using Docker cli it works, the keystore file with the certificate is transferred correctly.
If I build the Docker image using the spotify maven plugin, the keystore file will be corrupted. A comparison shows that it is much larger in size, a comparison of its content (hexdump) looks like it has been sprinkled (I don't know how to say it better) with extra bytes.
I've created a small example which shows the behavior: Project structure:
-src
|-main
| |-docker
| |-binaries
| | |-example.jks
| |-Dockerfile
|-pom.xml
Create example.jks like this (using keytool from openjdk 8)
keytool -genkey -keyalg RSA -alias selfsigned -keystore example.jks -storepass password -keypass password -validity 18250 -keysize 2048 -dname "CN=Unknown, OU=Example, O=Example, L=Example, ST=Unknown, C=US"
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>smallbinary</artifactId>
<name>Small binary problem</name>
<version>1.0</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<resources>
<resource>
<!--
| Enable resource filtering pre dockerfile build calls.
-->
<directory>src/main/docker</directory>
<targetPath>${project.build.directory}/docker-derived</targetPath>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<executions>
<execution>
<id>build-image</id>
<phase>compile</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>${project.artifactId}</imageName>
<dockerDirectory>${project.build.directory}/docker-derived</dockerDirectory>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin><!-- Triggers the Docker build configured within the plugin management. -->
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Dockerfile
FROM openjdk:8-jre-alpine
COPY binaries/* /opt/service/
CMD ["keytool", "-list", "-keystore", "/opt/service/example.jks", "-storepass", "password"]
Output if built directly per docker build .
and run by docker run [imagename]
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
selfsigned, Apr 3, 2017, PrivateKeyEntry,
Certificate fingerprint (SHA1): 07:56:26:66:16:82:DD:BF:6A:61:4B:94:E8:67:69:F8:77:36:5C:6D
And sadly the output when built with maven:
keytool error: java.io.IOException: Invalid keystore format
In other contexts, when copying larger binaries like jars, wars, ears or zip archives I haven't encountered any difficulties. But this one just doesn't seem to work.
My current workaround is to create the certificate directly during image build via a RUN
command in the Dockerfile.
Is there anything I am missing?
P.S. I experience the same issues on my linux Ubuntu 16.04 LTS laptop.
Upvotes: 1
Views: 463
Reputation: 221
The problem is caused by the resource filtering which is activated in my example (and in my production code as well). That I learned from My Technical Life which again links to a stackoverflow question jar file gets corrupted while building with maven
The offending code is this:
<resource>
<!--
| Enable resource filtering pre dockerfile build calls.
-->
<directory>src/main/docker</directory>
<targetPath>${project.build.directory}/docker-derived</targetPath>
<-- The next line breaks my binary-->
<filtering>true</filtering>
</resource>
Removing <filtering>true</filtering>
or explicitly setting it to false
fixes my example code and creates a working Docker image.
What to do if you need filtering, like I do because I refer to project versions in my production code Dockerfile and want Maven to replace some tokens?
The solution is to change the project structure a bit and separate filterable and non-filterable resources.
I changed the folder structure as follows:
-src
|-main
| |-docker
| |-Dockerfile
|-resources
| |-binaries
| |-example.jks
|-pom.xml
And changed the resource section of my example like this:
<resources>
<resource>
<!--
| Enable resource filtering pre dockerfile build calls for non binaries.
-->
<directory>src/main/docker</directory>
<targetPath>${project.build.directory}/docker-derived</targetPath>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources/binaries</directory>
<targetPath>${project.build.directory}/docker-derived/binaries</targetPath>
</resource>
</resources>
And then it works like a charm. Sorry for doubting the spotify plugin!
Upvotes: 3