java 容器 应用,如何为java应用程序构建docker容器

What I want to do is build a docker image for my Java application but the following considerations should be true for most compiled languages.

problem

On my build server I want to produce a docker image for my application as the deliverable. For this I have to compile the application using some build tool (typically Gradle, Maven or Ant) and then add the created JAR file to the docker image. As I want the docker image to just execute the JAR file I will of course start from a base image with Java already installed.

There are three ways of doing this:

let the build tool control the process

In this case my build tool controls the whole process. So it prepares the JAR file and after the JAR is created it calls Docker to create the image. This works as the JAR is created beforehand and Docker can be oblivious of the build process needed to create the JAR.

But my Dockerfile is no longer standalone. It depends on steps to happen outside of Docker for it work. In my Dockerfile I will have a COPY or ADD statement that is supposed to copy the JAR file to the image. This statement will fail when the jar is not created beforehand. So just executing the Dockerfile might not work. This becomes a problem if you want to integrate with services that just build using the present Dockerfile like the auto-build feature on DockerHub.

let Docker control the build

In this case all necessary steps to create the image are added to the Dockerfile so the image can be created by just executing the Docker build.

The main problem with this approach is that there is no way to add to a Dockerfile commands that should be executed outside the docker image being created. This means I have to add my source code and my build tools to the docker image and build my JAR file inside the image. This will result in my image being bigger than it has to be due to all the files added that will be unnecessary at runtime. This will also add extra layers to my image.

Edit:

As @adrian-mouat pointed out if I would add the sources, build the application and deleted the sources in one RUN statement I could avoid adding unnecessary files and layers to the Docker image. This would mean creating some insane chained command.

two separate builds

In this case we split our build in two: first we create the JAR file using our build tool and upload it to a repository (Maven or Ivy repository). We then trigger a separate Docker build that just adds the JAR file from the repository.

conclusion

In my opinion the better way would be letting the build tool control the process. This is will result in a clean docker image and as the image is what we want to deliver this is of importance. To avoid having a potentially not working Dockerfile lying around this should be created as part of the build. So no one would accidentally use it to start a broken build.

But this will not allow me to integrate with DockerHub.

question

Is there another way I am missing?

解决方案

The docker registry hub has a Maven image that can be used to create java containers.

Using this approach the build machine does not need to have either Java or Maven pre-installed, Docker controls the entire build process.

Example

├── Dockerfile

├── pom.xml

└── src

├── main

│   ├── java

│   │   └── org

│   │   └── demo

│   │   └── App.java

│   └── resources

│   └── log4j.properties

└── test

└── java

└── org

└── demo

└── AppTest.java

Container is built as follows:

docker build -t my-maven .

And run as follows:

$ docker run -it --rm my-maven

0 [main] INFO org.demo.App - hello world

Dockerfile

FROM maven:3.3-jdk-8-onbuild

CMD ["java","-jar","/usr/src/app/target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar"]

Update

If you wanted to optimize your container to exclude the source you could create a Dockerfile that only includes the built jar:

FROM java:8

ADD target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar /opt/demo/demo-1.0-SNAPSHOT-jar-with-dependencies.jar

CMD ["java","-jar","/opt/demo/demo-1.0-SNAPSHOT-jar-with-dependencies.jar"]

And build the container in two steps:

docker run -it --rm -w /opt/maven \

-v $PWD:/opt/maven \

-v $HOME/.m2:/root/.m2 \

maven:3.3-jdk-8 \

mvn clean install

docker build -t my-app .

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值