应用的容器化-docker打包spring boot镜像
应用容器化
容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build或release 的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚机轻量、更“透明”,这更便于监控和管理。
制作自己的镜像
选择适合你的方式来生成镜像
-
通过 Dockerfile 来自动编译生成镜像,实现构建镜像的需求。
多用于用户交互较少的时刻,比如软件部署时无需输入任何命令的应用。 -
通过容器内操作,并进行 Commit 来实现打包生成镜像。
用于用户交互较多、安装过程中配置较多的应用。
如何拆分现有的应用,来实现打包。Docker 容器化的应用应当是功能最小化的应用。这里的拆分并不是指将每个软件拆分成为一个容器,而是强调实现功能最小化。
一般来说,你可以将应用拆分成为 2-3 个容器, 2 个容器的情况下,是数据存储和应用程序各自一个容器。对于部分应用,可能还有缓存系统,同样也要单独放置在一个容器内。这样的结构下,在你需要扩容时,就比较容易,根据你的需要,可以随时扩容缓存系统或应用程序。
Dockerfile 打包
Dockerfile 就是声明应用环境和应用本身。Docker 需要更专注于它本身作为容器的技术。完成无状态化应用和写完 Dockerfile 之后,这个程序就可以被打报成 Docker image 了,放到一个 Docker Host 上运行起来就得到了无状态的应用容器,也就完成了把应用装容器的过程。
docker打包springboot项目成镜像
-
相关参考
将springboot jar应用打包成镜像并在docker运行成容器
参考URL: https://blog.****.net/keepd/article/details/80569797
docker打包springboot项目成镜像
参考URL: https://blog.****.net/junmoxi/article/details/80007878
使用 Docker 部署 Springboot 应用
参考: https://blog.****.net/chinrui/article/details/79721366 -
在Spring Boot项目中创建一个Dockerfile
文件格式,官方参考URL:
https://docs.docker.com/engine/reference/builder/#usage
FROM openjdk:8-alpine
VOLUME /tmp
ARG JAR_FILE=target/gs-spring-boot-docker-0.1.0.jar
ADD ${JAR_FILE} app.jar
ENV JAVA_OPTS=""
ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar
应用程序的jar文件(文件名为app.jar)被添加到容器中,执行 ENTRYPOINT
我们增加了一个VOLUME指向”/tmp”,因为那是Spring Boot应用程序为Tomcat创建的默认工作目录。作用是在你的主机”/var/lib/docker”目录下创建一个临时的文件,并且链接到容器中的”/tmp”目录。对于简单程序这一步是可选的,但是对于其他想要真实写入文件系统的Spring Boot应用程序又是必选的。
我们增加了一个指向”/dev/urandom”的Tomcat系统属性来缩小Tomcat的启动时间。
可以看到在左上叫有个运行的标记,很对,这个就是用来在IDEA构建jar包到镜像,然后放到Docker中运行的按钮。
如上图 我们只需要创建对应的Dockerfile文件,IDEA就会提醒上图中的选择供我们操作,我们选择编辑xxx/Dockerfile,填写image tag信息,然后run,然后就如图中下方生成了镜像。
- 使用docker-maven-plugin插件,在pom.xml中配置插件,完成自动化的镜像生成上线。
TODO 未测试
docker-maven-plugin 介绍
在我们持续集成过程中,项目工程一般使用 Maven 编译打包,然后生成镜像,通过镜像上线,能够大大提供上线效率,同时能够快速动态扩容,快速回滚,着实很方便。docker-maven-plugin 插件就是为了帮助我们在Maven工程中,通过简单的配置,自动生成镜像并推送到仓库中。
然后在ternimal中运行 mvn clean package -DskipTests=true docker:build命令,打包项目并构建镜像,命令执行完毕可以看到
IDEA使用Docker插件
【windows 10使用docker运行spring boot】
参考URL: https://www.jianshu.com/p/d7f3215df1b4
【IntelliJ IDEA安装docker插件】可直接参考
参考URL: https://blog.****.net/sealir/article/details/81200662
IDEA中配置及使用Docker
参考URL: https://blog.****.net/jacksonary/article/details/78974344
IDEA Docker插件安装
-
在IntelliJ IDEA中安装Docker integration插件
This plugin lets you download and build Docker images, create and start Docker containers, and carry out other related tasks.
这个插件可以下载构建Docker镜像,创建和启动容器以及执行其它相关任务。 -
安装插件后,需要配置连接docker服务端
从File->Settings->Build,Execution,Deployment->Docker打开配置界面。
点击+号添加一个docker配置,输入Name和Engine API URL,URL是docker服务地址,需要docker开启远程连接功能。 -
添加Docker的菜单窗口
IDEA顶部工具栏的View–>Tool Windows–>Docker
完成点击左下角的小窗口图标放大即可看到Docker的菜单工具栏
插件的基本操作
主要包含了containers和images,里面是一些已经存在的容器和镜像,下面是一些基本操作:
- 拉取镜像
如果要拉取镜像,直接在images上右击pull images然后填写Repository即可。
例如,填写如下 地址,即下载nginxhub.c.163.com/library/nginx
- 创建镜像容器运行
在需要跑的镜像上右击创建容器,这个时候也可看到镜像的ID和Tag,如下图
配置相应的端口绑定等信息即可启动即可,在创建的容器上右击选择inspect可以查看相应容器的详细信息,也可以启动或者停止容器。
至此,我们已经可以使用docker命令,直接把我们生成的spring boot手动利用docker命令打包到docker容器中,并直接运行。
关于2375端口
为了实现集群管理,Docker提供了远程管理接口。Docker Daemon作为守护进程,运行在后台,可以执行发送到管理接口上的Docker命令。
**启动Docker Daemon时,加入-H 0.0.0.0:2375,Docker Daemon就可以接收远端的Docker Client发送的指令。**注意,Docker是把2375端口作为非加密端口暴露出来,一般是用在测试环境中。此时,没有任何加密和认证过程,只要知道Docker主机的IP,任何人都可以管理这台主机上的容器和镜像。
通过远程管理的方式,向Docker主机发送命令。
docker -H 192.168.0.10:2375 info
Linux下开启2375端口
docker 开启2375端口,提供外部访问docker
参考:https://blog.****.net/onlyshenmin/article/details/81069047
docker开启远程访问
参考URL: https://blog.****.net/z_qifa/article/details/74202785
Docker打开TCP管理端口
参考URL: https://blog.****.net/onlyshenmin/article/details/81069047
Docker本身提供了加密的远程管理端口2376,配合CA证书,就能提供TLS连接了。
参考URL: https://blog.****.net/ghostcloud2016/article/details/51539837
Windows开启2375端口
在windows下设置docker直接使用gui界面来设置就可以了
右键启动栏的docker小图标,点击settings>general
设置启用localhost的2375端口来运行docker
Expose daemon on tcp://localhost:2375 without TLS
基础镜像 Commit 生成镜像
除了通过 Dockerfile 来打包生成镜像外,也可以通过 Docker Commit 来生成镜像。通过 Commit 打包的镜像多是由于应用本身在部署时有大量的交互内容,无法通过命令来指定。
容器ID 35f1c2ae1f7e 则
将容器打包成镜像执行命令 docker commit 35f1c2ae1f7e mynewimage就将容器35f1c2ae1f7e打包为新的镜像mynewimage了
Docker镜像大小问题
Docker容器镜像瘦身的三种构建方法整理
https://blog.****.net/limingcai168/article/details/82347485
三个技巧,将Docker镜像体积减小90%
https://blog.****.net/bbwangj/article/details/82178774
基本的构建方式,就是依赖各种资源的传统方式构建,分层较多,一个容器至少在600M左右,但是各方的依赖工具都很全面,对于调试,以及内部操作都 相对简单方便。
Docker 容器应该只包含一个进程以及用于运行这个进程所需的最少的文件,你不需要整个操作系统。
“distroless”镜像只包含应用程序及其运行时依赖项,不包含程序包管理器、shell 以及在标准 Linux 发行版中可以找到的任何其他程序。
这个未包含额外程序的镜像会多小呢?
$ docker images | grep node-distroless
node-distroless 7b4db3b7f1e5 76.7MB
仅仅76.76MB!
比前一个镜像少了600MB!
需要注意的是,我们不应该在生产环境中附加到容器中进行调试,而应依靠正确的日志和监控。
如果我们既希望能调试,又关心尺寸大小,又该怎么办?
使用Alpine作为更小的基础镜像
一个基于musl libc[3]和busybox[4]、面向安全的轻量级Linux发行版。
换言之,它是一个尺寸更小、更安全的Linux发行版。
Alpine基础镜像
Docker系列之(三):Docker微容器Alpine Linux
参考URL: https://www.cnblogs.com/ee900222/p/docker_3.html
Alpine基础镜像是基于muslc的,这是一个C的替代标准库。
但是,多数Linux发行版,比如Ubuntu、Debian及CentOS都是基于glibc的。这两个库照理应该实现了相同的接口。
不过,它们的目标不同:
- glibc最常用,速度更快
- muslc占用空间更少,以安全为核心
在编译应用程序时,多数情况下是使用某个libc来编译的。如果想在其他libc中使用,只能重新编译。
Alpine Linux是一个面向安全的轻型的Linux发行版。
Alpine Linux采用了 musl libc 和 busybox以减小系统的体积和运行时资源消耗。
在保持瘦身的同时,Alpine Linux还提供了自己的包管理工具apk。
关键的是,相比于其他Linux的Docker镜像,它的容量非常小,仅仅只有5MB。
问题点:
-
Alpine Linux使用了musl,可能和其他Linux发行版使用的glibc实现会有些不同。
-
musl实现的DNS服务不会使用resolv.conf文件中的search和domain两个配置,通过DNS来进行服务发现时需要注意。
原生基础镜像非常适合用于测试和开发。
它的尺寸比较大,不过用起来就像你主机上安装的Ubuntu一样。并且,你能访问该操作系统里有的所有二进制程序。
Alpine制作JDK8镜像
- 自己制作
Alpine 3.6 OpenJDK 8 Bug
参考URL: https://mritd.me/2017/09/27/alpine-3.6-openjdk-8-bug/
(未测试)
FROM alpine:edge
LABEL maintainer="mritd <[email protected]>"
ENV JAVA_HOME /usr/lib/jvm/java-1.8-openjdk
ENV PATH $PATH:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin
ENV JAVA_VERSION 8u144
ENV JAVA_ALPINE_VERSION 8.144.01-r0
RUN apk add --update bash curl tar wget ca-certificates unzip \
openjdk8=${JAVA_ALPINE_VERSION} font-adobe-100dpi ttf-dejavu fontconfig \
&& rm -rf /var/cache/apk/* \
CMD ["bash"]
- 使用别人已经制作好的镜像 alpine jdk8
进入阿里云镜像中心https://dev.aliyun.com/search.html
找到JAVA相关,点击进去
This image is officially deprecated in favor of the openjdk image, and will receive no further updates after 2016-12-31 (Dec 31, 2016). Please adjust your usage accordingly.
此映像被正式弃用,而支持openjdk映像,并且在2016-12-31(2016年12月31日)之后将不会接收到进一步的更新。请相应地调整您的使用情况。
说明官方新的java jdk镜像,使用的是openjdk这个关键字镜像。
继续点击进去,进入到openjdk镜像官网
https://hub.docker.com/_/openjdk/?spm=5176.1972344.1.5.cNQc3F
官方对openJdk做了比较详细的说明。
Image Variants
openjdk:<version>
openjdk:<version>-alpine
openjdk:<version>-slim
-
使用默认的镜像。如果你不确认你使用哪个,version后面不加,应该就满足你。它被设计为抛弃式throw away容器(挂载源代码并启动容器以启动应用程序),又可以用作构建其他映像的基础。
你也可以加标签tags jessie, sid, or stretch 。这些是Debian发布的版本,用于声明你用哪个基础镜像。 -
-alpine这个镜像是基于流行的 Alpine Linux项目。使用官方镜像只有5MB大小。
当希望镜像尽可能小时,强烈推荐这个镜像。
为了减少镜像大小,不推荐添加额外工具(如git、bash)包含进镜像。使用这个镜像作为基础,在Docckerfile中添加所需的内容。 -
这个映像安装了OpenJDK -headless的包,因此缺少了许多与UI相关的Java库和默认标签中包含的一些普通包。它只包含运行Java所需的最小包。百度关键字 “java headless”
version 就是你的jdk的版本,8就填8。
根据上面信息,我们使用openjdk-8-jdk-alpine的话,docker 命令应该如下:
docker pull openjdk:8-alpine
这个应该是官方 最精简的 jdk8 docker镜像。
openjdk-8-jdk-alpine容器问题整理
- Docker openjdk-8-jdk-alpine 容器时间与jdk时区不同修改方法
参考URL: https://www.cnblogs.com/solooo/p/7832117.html
未验证测试
TODO 遇到再整理。
基于已有镜像,dockr命令直接打包jar文件到容器中并运行
官方参考URL: https://hub.docker.com/_/openjdk/?spm=5176.1972344.1.5.cNQc3F
SpringBoot | 第十四章:基于Docker的简单部署
https://blog.****.net/qq_42803327/article/details/82150809
基于有时候没有开启远程服务,也可把jar上传至服务器,然后编写脚本进行运行,这里简单示例下,正常部署时,正常是通过jenkins打包,然后编写打包后事件,运行脚本即可。
-v 你宿主机的目录/文件
windows环境下,你使用绝对路径,系统会提醒,讲你用到的盘符共享。(其实就是windows共享给Docker宿主Linux,Docker才能访问,copy它需要的文件给容器中。)
如果你运行Docker在linux主机下,应该不存在此问题。
-w 你容器主机目录/文件(也可以-v中用冒号直接隔开即可)
–name 指定新生成的容器名
docker run -d -p 1234:11111 -v D:\bat\eurekaserver-0.0.1-SNAPSHOT.jar:/usr/eurekaserver-0.0.1-SNAPSHOT.jar --name SpringbootByJar3 openjdk:8-alpine java -server -jar -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=127.0.0.1 /usr/eurekaserver-0.0.1-SNAPSHOT.jar --spring.config.location=eurekaserver.properties
如果需要copy整个目录的文件到容器中呢?
如下 -v 填目录 冒号后面是目标目录,测试通过。
docker run -d -p 1234:11111 -v D:\bat\:/usr/test --name SpringbootByJar3 openjdk:8-alpine java -server -jar -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=127.0.0.1 /usr/test/eurekaserver-0.0.1-SNAPSHOT.jar --spring.config.location=eurekaserver.properties
其实就是把jar拷贝从宿主中拷贝到容器中,然后运行java命令进行启动。和原来的运行jar方式是一样的。
遇到问题整理
- -Dcom.sun.management.jmxremote.port=1332 java启动参数,有这个启动不起来。 提醒1332已被使用。
暂时删除该参数。 - 文件传成功到容器里面了,但是java程序没有启动起来,登进容器可以手动启起来? Error: Unable to access jarfile eurekaserver-0.0.1-SNAPSHOT.jar
IDEA插件断开连接docker demon,重新连接,发现和之前不一样,应该是成功了,spring boot启动有个过程。注意查看容器日志即可。