zoukankan      html  css  js  c++  java
  • Docker极简入门:使用Docker运行Java程序

    运行简单的Java程序

    先在当前目录创建App.java文件

    public class App{
        public static void main(String[] args){
            String os = System.getProperty("os.name");
            String osArch = System.getProperty("os.arch");
            String osVersion = System.getProperty("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
    

    REPOSITORYTAG都为<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项目

    这是我的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/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <!-- 这里将影响jar包的名字 -->
      <groupId>org.example</groupId>
      <artifactId>demoapp</artifactId>
      <version>app</version>
    
      <name>demoapp</name>
      <!-- FIXME change it to the project's website -->
      <url>http://www.example.com</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.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 https://maven.apache.org/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 https://maven.apache.org/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>org.example.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 https://maven.apache.org/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
    
    WORKDIR /build/
    # 把本地的pom.xml和src目录复制到镜像的/build目录下
    COPY pom.xml /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 构建时自动执行的命令
  • 相关阅读:
    字体图标
    HBase Shell 常用命令
    Centos7 KVM日常运维
    Centos7 KVM安装部署
    Centos7安装Puppet自动运维
    Centos7安装ansible自动运维
    H3C巡检基本命令
    组播学习
    Centos7下使用LVM给系统硬盘扩容
    python 类中方法总结 --- 实例方法、类方法、静态方法
  • 原文地址:https://www.cnblogs.com/AD-milk/p/15579530.html
Copyright © 2011-2022 走看看