前言

简单记录一下docker打包jar部署的几种方式,避免以后忘记,不过这种手动的方式应用应该不多!
现在微服务大多数采用集群部署方式,使用k8s或者swarm配合docker+jenkins等实现自动化部署集群及动态扩展等,后面再慢慢写相关的吧。没有服务器资源演示,懒得弄

使用Dockerfile手动打包jar

简单打包运行

docker安装和使用基础看这里:manjaro安装docker及基本命令(dokcer系列一)
我这里就用前几天写的SpringCloudAlibabaDemo做演示吧,需要演示工程的看这里:SpringCloudAlibaba项目搭建nacos+gateway
user模块已久打包成jar了,如下:
在这里插入图片描述
把jar上传到你的服务器,我这里就在本机演示,直接cp到/opt/java_app_docker目录下
在这里插入图片描述
在相同目录下创建Dockerfile
sudo vim Dockerfile
然后输入:

# 拉取jdk8作为基础镜像
FROM java:8
# 作者
MAINTAINER zbdemo <zbdemo@163.com>
# 添加jar到镜像并命名为user.jar
ADD user-0.0.1-SNAPSHOT.jar user.jar
# 镜像启动后暴露的端口
EXPOSE 8001
# jar运行命令,参数使用逗号隔开
ENTRYPOINT ["java","-jar","user.jar"]

然后使用docker命令打包:
docker build -t user .
user表示镜像名称
最后的.表示Dockerfile在当前目录
打包完成后使用docker images查看镜像
在这里插入图片描述
使用docker run命令创建并运行容器:
docker run -d --name user -p 8001:8001 user
命令解释如下:

命令功能
docker run创建并启动容器
–name指定一个容器名称
-d后台运行容器,并返回容器ID
-p指定端口
user需要启动的镜像(名称+版本)不指定版本默认最新版本
符号左边为宿主机,右边为容器空间

启动完成,查看启动日志:
docker logs -f -t user
jar日志启动成功,查看容器:
docker ps
在这里插入图片描述
访问一下,测试效果:
localhost:8001/hello/hello
在这里插入图片描述
没错,手动docker打包jar镜像并运行完成了,但是这样搞就显得有点呆,还不如直接java -jar运行呢!操作这么麻烦,每次更新还要删除容器,删除镜像重新创建,而且日志文件等重要信息也会丢失!当然如果你使用jenkins等shell自动化的工具当我没说

进化:可复用容器

首先停止并删除刚刚创建的容器和镜像
停止容器:
docker stop user
删除容器:
docker rm user
删除镜像:
docker rmi user

修改Dockerfile文件
sudo vim Dockerfile
修改后内容如下(给jar安排了一个目录,方便挂载到宿主机):

# 拉取jdk8作为基础镜像
FROM java:8
# 作者
MAINTAINER zbdemo <zbdemo@163.com>
# 添加jar到镜像并命名为user.jar
ADD user-0.0.1-SNAPSHOT.jar /app/user.jar
# 镜像启动后暴露的端口
EXPOSE 8001
# jar运行命令,参数使用逗号隔开
ENTRYPOINT ["java","-jar","/app/user.jar"]

然后在/opt/java_app_docker文件夹下面创建jar挂载目录
sudo mkdir app

把你的jar包cp一份到宿主机/opt/java_app_docker/app目录下并改名为user.jar 这里一定要在app目录下存放你的jar,不然容器启动会失败,找不到jar
在这里插入图片描述
打包镜像-创建并运行容器
打包镜像:
docker build -t user .
创建并运行容器:
docker run -d --name user -p 8001:8001 -v /opt/java_app_docker/app:/app user
命令解释如下:

命令功能
docker run创建并启动容器
–name指定一个容器名称
-d后台运行容器,并返回容器ID
-p指定端口
user需要启动的镜像(名称+版本)不指定版本默认最新版本
-v挂载目录到宿主机
符号左边为宿主机,右边为容器空间

这样的方式启动完成之后,更新服务时只需要更换宿主机/opt/java_app_docker/app目录下的jar包,然后重启容器即可实现更新,省略了每次更新删除打包创建等过程

究极进化:jdk镜像直接创建可复用容器

上面的方式在单应用情况下是可行的,但是如果我是微服务架构呢?比如现在我要部署我的gateway网关服务,是不是还要重新走一遍流程?很呆!!!!!
首先停止并删除刚刚创建的容器和镜像
停止容器:
docker stop user
删除容器:
docker rm user
删除镜像:
docker rmi user
查看jdk版本
docker images
在这里插入图片描述
我这里是openjdk8
创建并运行容器(直接基于jdk镜像创建容器):
docker run -d --name user -p 8001:8001 -v /opt/java_app_docker/app:/app java:8 /usr/bin/java -jar /app/user.jar
或者(启动方式取决于jdk版本)
docker run -d --name user -p 8001:8001 -v /opt/java_app_docker/app:/app openjdk:8 java -jar /app/user.jar

命令解释如下:

命令功能
docker run创建并启动容器
–name指定一个容器名称
-d后台运行容器,并返回容器ID
-p指定端口
-v挂载目录到宿主机
java:8需要启动的镜像(名称+版本)不指定版本默认最新版本
/usr/bin/java -jar /app/user.jarjar启动命令及jar所在位置,因为创建的容器挂在了宿主机/opt/java_app_docker/app目录,所以里面映射了我们上面放进去的user.jar
符号左边为宿主机,右边为容器空间

这样的方式省略了创建Dockerfile并把jar打包成镜像的操作,无论多少个服务,只要有jdk镜像,一条命令搞定!比如现在我需要增加gateway服务,那就把gateway.jar放在任意目录下,直接执行:
docker run -d --name user -p ${任意外部端口}😒{任意容器端口} -v ${你的gateway.jar存放目录}:/${任意容器内目录名称} java:8 /usr/bin/java -jar /${任意容器内目录名称}/gateway.jar
这种方式也是直接替换挂载目录下jar,然后docker restart 容器ID or 名称 就行

超究极进化:maven插件打包(不推荐)

为什么不推荐呢?首先是maven插件直接打包docker镜像的方式污染工程,反正就很奇怪的感觉,其次你的项目是要发布生产环境的,直接打包镜像给运维,太卷了吧?
所以综上所属,我就简单介绍下
pom添加docker打包方式

<!--docker 镜像插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.2.2</version>
                <configuration>
                    <imageName>${project.artifactId}</imageName>
                    <dockerDirectory>src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>

创建Dockerfile文件
在这里插入图片描述
内容如下:

# 基础镜像使用java
FROM java:8
# 作者
MAINTAINER zbdemo
# 将jar包添加到容器中并更名为app.jar
ADD gateway-0.0.1-SNAPSHOT.jar gateway.jar
EXPOSE 8000
ENTRYPOINT ["java","-jar","gateway.jar"]

命令方式
打包:
mvn package -Dmaven.test.skip=true docker:build


本机docker
保存镜像到本地docker:
docker save -o /gateway.jar gateway
查看镜像:
docker images
创建并运行容器:
docker run --name gateway -p 8000:8000 -d gateway


服务器docker
或者上传到服务器:
scp /gateway.jar root@ip:/opt/app
加载镜像:
docker load </opt/app/gateway.jar
查看镜像:
docker images
创建并运行容器:
docker run --name gateway -p 8000:8000 -d gateway.tar


或者这样
打包
在这里插入图片描述
推送
在这里插入图片描述

无聊的进化:maven打包自动推送镜像到指定服务器(不推荐,研发环境随便玩)

准备工作
开启服务器的docker远程访问权限:自行百度?反正我不想这样玩

pom修改如下:

<!--docker 镜像插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.2.2</version>
                <configuration>
                    <imageName>${project.artifactId}</imageName>
                    <dockerDirectory>src/main/docker</dockerDirectory>
                    <!-- docker容器地址 -->
                    <dockerHost>http://192.168.101.1:2375</dockerHost>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

打包:
mvn package -Dmaven.test.skip=true docker:build
或者
在这里插入图片描述
完成!!!!!!!!!!!!!!!!!!!!!!去服务器docker images看一下应该有了

关于docker容器启动后注册到nacos的ip是docker容器ip问题!

1.可以在docker run的时候加 –network=host 参数解决(主机网络模式),这个时候我们无需-p 80:80指定服务端口运行,因为–network=host模式会使用服务本身启用的端口。
2.容器创建启动时动态指定ip和端口:-Dspring.cloud.nacos.discovery.ip=xx -Dspring.cloud.nacos.discovery.port=xxx
或者在yaml配置文件配置:

spring:
  cloud:
    nacos:
      discovery:
        ip: xx
        port: xx

总结

后面两种maven插件打包镜像的方式都不推荐,反正不要太卷了,哈哈!虽然在dev或者test环境用起来可能真的爽,但是你确定要手动吗?后续应该会写jenkins+k8s或者jenkins+swarm集群部署,你会发现你所谓的爽不过如此!!说这么多干啥呢,反正主要是写给自己看的
差点忘了,感谢大佬,参考地址:地址1地址2

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐