本文首发于个人博客: https://joemendezckh.github.io/posts/249f9dc1.html
主要是记录参加阿里云docker新人赛 Docker练习场 的过程以及自已遇到的一些坑
使用 java 实现
- 首先, 官方的帮助文档将流程介绍的已经很详细了, 在此不做赘述
- 直接从Java实现写起
如何实现 run.sh 调用我们的函数
- 一个 web 工程, 通过 curl 发送 get 请求调用函数
- 优点: 可以重复调用
- 缺点: 感觉有点跑题, 目的是学习docker, 不是web…
- 直接 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 个工具类
fastjson
和commons-io
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.68</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
- 使用了 2 个工具类
小坑
-
要指定 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在打包的过程中, 没有将
fastjson
和commons-io
打包进去 -
修改 pom 和 手动添加 jar 包都不生效, 最后通过 maven 插件解决
详细分析见: Maven构建可执行的jar包(包含依赖jar包)
此时就可以解决了
<plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <appendAssemblyId>false</appendAssemblyId> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <!-- 此处指定main方法入口的class --> <mainClass>com.joe.tcdata.TaskRun</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>assembly</goal> </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新人赛最大的作用就是熟悉整个 docker 的基本运行流程, 以及基础的知识, 只是一个起步.
继续努力学习!