阿里云Docker新人赛

本文首发于个人博客: https://joemendezckh.github.io/posts/249f9dc1.html
主要是记录参加阿里云docker新人赛 Docker练习场 的过程以及自已遇到的一些坑
使用 java 实现

  • 首先, 官方的帮助文档将流程介绍的已经很详细了, 在此不做赘述
  • 直接从Java实现写起

如何实现 run.sh 调用我们的函数

  1. 一个 web 工程, 通过 curl 发送 get 请求调用函数
    • 优点: 可以重复调用
    • 缺点: 感觉有点跑题, 目的是学习docker, 不是web…
  2. 直接 main 函数, 打成jar包后直接运行
    • 简单粗暴

综上: 我选择了方案 2 (中间有个小坑)

新建一个 maven 工程

  • 编写实现功能的代码

    public static final String NUM_LIST = "/tcdata/num_list.csv";
    public static final String PATH = "result.json";
    
    public static void main(String[] args) {
    
        File resultFile = new File(PATH);
        File numFile = new File(NUM_LIST);
        try {
            if (!resultFile.exists()) {
                resultFile.createNewFile();
            }
            
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("Q1", "Hello world");
            final List<String> list = FileUtils.readLines(numFile, "UTF-8");
            
            final ArrayList<Integer> integers = new ArrayList<>(10);
            
            list.forEach(num -> integers.add(Integer.parseInt(num)));
            int sum = integers.stream().mapToInt(num -> num).sum();
    
            final int[] result = integers.stream()
                .sorted(Comparator.comparing(Integer::intValue).reversed())
                .mapToInt(n -> n).limit(10).toArray();
    
            jsonObject.put("Q2", sum);
            jsonObject.put("Q3", result);
    
            FileOutputStream fileOutputStream = new FileOutputStream(resultFile);
            fileOutputStream.write(jsonObject.toJSONString().getBytes());
    
            System.out.println("success");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("failed");
        }
    }
    
    • 使用了 2 个工具类 fastjsoncommons-io
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>fastjsonartifactId>
        <version>1.2.68version>
    dependency>
    <dependency>
        <groupId>commons-iogroupId>
        <artifactId>commons-ioartifactId>
        <version>2.6version>
    dependency>
    

小坑

  • 要指定 java -jar 运行的主类名, 方可执行

  • 直接运行是可以的, 但是直接打包再在本地运行jar包的话, 会抛异常

    Exception in thread "main" java.lang.NoClassDefFoundError: com/alibaba/fastjson/JSONObject
            at com.joe.tcdata.TaskRun.main(TaskRun.java:13)
    Caused by: java.lang.ClassNotFoundException: com.alibaba.fastjson.JSONObject
            at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
            at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
            ... 1 more
    
    • 这是因为maven在打包的过程中, 没有将 fastjsoncommons-io打包进去

    • 修改 pom 和 手动添加 jar 包都不生效, 最后通过 maven 插件解决

      详细分析见: Maven构建可执行的jar包(包含依赖jar包)

      此时就可以解决了

    <plugin>
        <artifactId>maven-assembly-pluginartifactId>
        <configuration>
            <appendAssemblyId>falseappendAssemblyId>
            <descriptorRefs>
                <descriptorRef>jar-with-dependenciesdescriptorRef>
            descriptorRefs>
            <archive>
                <manifest>
                    
                    <mainClass>com.joe.tcdata.TaskRunmainClass>
                manifest>
            archive>
        configuration>
        <executions>
            <execution>
                <id>make-assemblyid>
                <phase>packagephase>
                <goals>
                    <goal>assemblygoal>
                goals>
            execution>
        executions>
    plugin>
    

编写run.sh

#!/bin/sh
java -jar tcdata-1.0.0.jar > tcdata.log

编写Dockerfile

FROM            registry.cn-shanghai.aliyuncs.com/tcc-public/java:jdk_13.0.2
MAINTAINER      作者<作者邮箱>
# 添加当前文件夹下所有内容(包括 jar包和 run.sh) 到 container 的 / 目录
ADD 		. /
WORKDIR 	/
CMD 		["sh", "run.sh"]
  • 注意:

    /tcdata/num_list.csv 该文件在提交回答的时候, 会自动生成, 不需要我们自己编写

    但是在build 好镜像后, 是不存在这个目录的, 所以 build 好的镜像是不能执行的

    也就是说, 需要提前在本地测试好 jar 包没有问题, 这样提交后出现错误才是 docker 方面的问题

推送到自己的仓库

这一步可以看官方的指导, 很详细

登录阿里云Docker Registry

$ sudo docker login --username=用户名 registry.cn-shanghai.aliyuncs.com

用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。

从Registry中拉取镜像

$ sudo docker pull registry.cn-shanghai.aliyuncs.com/用户名/仓库名:[镜像版本号]

将镜像推送到Registry

$ sudo docker login --username=用户名 registry.cn-shanghai.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/用户名/仓库名:[镜像版本号]
$ sudo docker push registry.cn-shanghai.aliyuncs.com/用户名/仓库名:[镜像版本号]

提交回答

  • 建议将该仓库设置为公有仓库, 这样比较省事, 不然要写用户名和密码, 可能出错
    阿里云Docker新人赛_第1张图片

小结

这个 docker新人赛最大的作用就是熟悉整个 docker 的基本运行流程, 以及基础的知识, 只是一个起步.

继续努力学习!

你可能感兴趣的:(实践)