Docker极简⼊门:使⽤Docker运⾏Java程序
运⾏简单的Java程序
先在当前⽬录创建App.java⽂件
public class App{
public static void main(String[] args){
String os = Property("os.name");
String osArch = Property("os.arch");
String osVersion = Property("os.version");
System.out.println(os);
System.out.println(osArch);
System.out.println(osVersion);
}
}
然后创建Dockerfile
## 设置基础镜像
FROM openjdk:8
## 设置进⼊容器时的⼯作⽬录
WORKDIR /root/app
## 将本地⽬录复制进容器⽬录中
COPY App.java /root/app
## 镜像制作时执⾏的命令
RUN javac App.java
## 容器启动时执⾏的命令
ENTRYPOINT java App
准备⼯作做好之后在当前⽬录输⼊命令
docker build .
.是指明Dockerfile⽂件在哪个路径之下,因为我们是在当前路径下创建的,所以只需要填写.就好。
build完成之后运⾏命令:
docker images
## 你的输出可能会像这样
REPOSITORY  TAG      IMAGE ID      CREATED      SIZE
<none>      <none>    2045f43c5e88  6 hours ago  526MB
REPOSITORY 和TAG都为<none>,这是因为刚刚在编写Dockerfile时没有指定它们。
之后的段落⾥会解决这个问题,对于这个简单的项⽬,我们只需要IMAGE ID就够了。
现在根据镜像启动容器,运⾏命令:
## 偷懒的话可以只打IMAGE ID的前三位
## 这个IMAGE ID要根据你实际build出来的镜像进⾏修改
## 请务必运⾏前⼀条命令docker images,到对应的ID
docker run 2045f43c5e88
输出如下:
Linux
amd64
5.4.72-microsoft-standard-WSL2
这段Java程序的作⽤就是输出当前操作系统的环境,根据输出可以知道博主是在WSL2上运⾏docker的。
FROM alpine
WORKDIR /root/app
COPY App.java /root/app
RUN apk add openjdk8
## 设置环境变量
ENV JAVA_HOME /usr/lib/jvm/java-1.8-openjdk
ENV PATH $PATH:$JAVA_HOME/bin
RUN javac App.java
ENTRYPOINT java App
为了便于区别两次构建出的不同镜像,我们给之前的镜像打上tag
使⽤命令:
docker tag 2045 myapp:1.0
在build时可以使⽤-t来为镜像打tag
docker build . -t myapp:2.0
再次运⾏命令
docker images
REPOSITORY  TAG            IMAGE ID      CREATED        SIZE
myapp        1.0            2045f43c5e88  12 hours ago  526MB
myapp        2.0            0545999c0fc0  25 hours ago  131MB
可以看到两个镜像已经被分别打上了tag,不过值得注意的是tag为1.0的镜像体积要⽐2.0的⼤,这是为什么?
直接将openjdk作为基础镜像会包含所有的Java语⾔编译⼯具和库。
多阶段构建镜像
其实运⾏Java程序只需要jre就⾏,我们没有必要使⽤jdk作为基础镜像。但把程序打包成jar包,然后再交给docker的⽅式太⿇烦了。有没有办法实现编译、打包、运⾏⼀体化呢?
当然是有的,简单修改⼀下Dockerfile就可以了
先基于Maven镜像⽣成jar包,最后运⾏在jre镜像中,同时删除已经⽤不到的Maven镜像
⾸先创建⼀个maven项⽬
这是我的l⽂件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 这⾥将影响jar包的名字 -->
<groupId&le</groupId>
<artifactId>demoapp</artifactId>
<version>app</version>
<name>demoapp</name>
<!-- FIXME change it to the project's website -->
<url>ample</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mavenpiler.source>1.8</mavenpiler.source>
<mavenpiler.target>1.8</mavenpiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see /ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see /ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->        <plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<!-- 指定mainClass,不指定可能导致jar包运⾏不成功 -->
<manifest>
<addClasspath>true</addClasspath>
<useUniqueVersions>false</useUniqueVersions>
<classpathPrefix>lib/</classpathPrefix>
<mainClass&le.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see /ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
然后在项⽬的根⽬录下创建Dockerfile⽂件
## build stage
FROM maven:3.8.3-jdk-8 AS MAVEN_BUILD
docker进入容器WORKDIR /build/
# 把本地的l和src⽬录复制到镜像的/build⽬录下
l /build/
COPY src /build/src/
# 执⾏打包命令
RUN mvn package
## run s
FROM openjdk:8-jre-alpine
# 设置⼯作⽬录在镜像的 /app ⽬录下
WORKDIR /app
# 将第⼀阶段⽣成的jar包添加到第⼆阶段的容器中
COPY --from=MAVEN_BUILD /build/target/demoapp-app.jar /app/
# 运⾏jar包
ENTRYPOINT java -jar demoapp-app.jar
REPOSITORY  TAG            IMAGE ID      CREATED            SIZE
<none>      <none>        770d75ab38d7  7 seconds ago    84.9MB
最后⽣成的镜像⼤⼩要⽐之前的500MB⼩了很多
Dockerfile常⽤命令
命令描述
FROM基础镜像
MAINTAINER维护者信息
ADD添加⽂件到镜像(⾃动解压)
COPY添加⽂件到镜像(不解压)
USER设置运⾏RUN指令的⽤户
ENV设置环境变量
RUN镜像制作时执⾏的命令
ENTRYPOINT容器启动时执⾏的命令(⽆法被覆盖)
CMD容器启动时执⾏的命令(多条CMD只执⾏最后⼀条)EXPOSE声明要打开的端⼝(实际还是要docker run -p port1:port2 才⾏) VOLUME⽬录映射
ONBUILD构建时⾃动执⾏的命令

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。