Docker部署java项目(Dockerfile方式)

一、前言

Docker一个是一个应用容器引擎,帮助我们减少大量的运维成本,它可以:

  • web应用的自动化打包和发布;
  • 自动化测试和持续集成、发布;
  • 在服务型环境中部署和调整数据库或其他的后台应用;
  • 从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。思想:集装箱、标准化(运输方式、存储方式、API接口)、隔离

    Docker的具体介绍就不在多说了,官网、百度百科等有非常多的介绍.
    接下来我将从SpringCloud的服务部署带你走进Docker》》》

最终要达到的目的

搭建好Docker环境,准备好ServerA(服务层)、ServerB(客服端层)、EurekaServer(注册中)以及在Mysql、Mongodb、redis等等涉及到的应用
最终要实现的一个容器关系图(画的很搓,欢迎吐槽).
在这里插入图片描述

二、准备Docker

在进入正题之前先了解下几个名词:

  • Docker服务端Docker客户端:其中docker服务端是一个服务进程,管理着所有的容器。docker客户端则扮演着docker服务端的远程控制器,可以用来控制docker的服务端进程。大部分情况下,docker服务端和客户端运行在一台机器上;
  • Docker容器:可以理解为在沙盒中运行的进程。这个沙盒包含了该进程运行所必须的资源,包括文件系统、系统类库、shell 环境等等。但这个沙盒默认是不会运行任何程序的。你需要在沙盒中运行一个进程来启动某一个容器。这个进程是该容器的唯一进程,所以当该进程结束的时候,容器也会完全的停止;
  • Docker镜像:相当于安装包,每一个应用程序都是在一个隔离的容器中运行,因此每一个应用程序当作一个容器;
  • Docker仓库:存放镜像用。
    安装Docker,菜鸟教程有详细的安装过程,涵盖了centos、macos、ubunte、window操作系统的安装过程,这里不细讲了,具体如下几条命令(centos7)。
#确保 yum 包更新到最新
sudo yum update

#安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

#设置yum源
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

#安装docker
sudo yum install docker-ce

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

需要注意一下系统环境(uname -r
docker环境要求:

  • 需要Linux3.8以上内核;
  • 64位CPU架构的计算机;
  • 内核至少支持其中一种存储驱动:Device Manager(默认); AUFS; vfs; btrfs;
  • 内核必须支持并开启cgroup和namespace功能

关于docker服务的一些命令:

  • 启动docker: systemctl start docker
  • 守护进程重启:sudo systemctl daemon-reload
  • 重启docker服务:systemctl restart docker
  • 重启docker服务: sudo service docker restart
  • 关闭docker: service docker stop
  • 关闭docker: systemctl stop docker

三、Docker安装Mysql、Redis、Mongo

1.安装Mysql

1.1 通过search搜索镜像:

语法: docker search [OPTIONS] TERM

搜索mysql镜像:

docker search mysql

 
 
  • 1

docker search
通常第一个就是我们想要的镜像.

1.2 通过pull拉起镜像

找到了想要的镜像,那么可以通过pull将镜像下载到本地仓库

语法: docker pull [OPTIONS] NAME[:TAG|@DIGEST]

拉取mysql镜像:

docker pull mysql

 
 
  • 1

docker pull
等待下载完成即可,在没有指定版本号情况下,docker默认拉起docker远程仓库中版本最新的镜像.

1.3 通过images查看镜像

语法: docker images [OPTIONS] [REPOSITORY[:TAG]]

显示所有本地镜像:

docker images

 
 
  • 1

docker images
可以看到本地所有已有的镜像,随着镜像越来越多,可以通过docker images mysql来精确搜索本地是否有mysql镜像.

1.4 通过run启动镜像

语法: docker run [OPTIONS] IMAGE [COMMAND] [ARG…]

其中有非常多的参数,可以通过docker run --help来查看具体参数说明
启动mysql镜像:

docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=asd123asd --name mysql -d mysql

 
 
  • 1

docker run
在执行完后,该镜像便在一个隔离的容器中执行,docker会为每一个容器分配一个ID,该ID作为唯一标志.
上面语法中-p用来做端口映射,-e 用来做参数配置,--name为容器其一个别名,-d让应用在后台运行

1.5 通过ps查看docker中的进程

语法:docker ps [OPTIONS]

显示所有运行中的容器:

docker ps

 
 
  • 1

docker ps
当前显示的是正在运行中的容器,我们也可以通过在后面加一个-a参数查看所有容器
所有镜容器

1.6 通过start/stop/restart来对容器进行启动、停止、重启

语法: docker start|stop|restart [OPTIONS] CONTAINER [CONTAINER…]

docker启动|停止|重启mysql容器:

docker start|stop|restart mysql (或者容器ID)

 
 
  • 1

1.7 远程连接

启动好mysql容器,使用Navicate客服端连接刚才我们启动的mysql试试,如果是本地直接连接,如果是远程,请使用可访问服务器的IP进行访问。
连接的时候你会发现如下错误:
Authentication plugin ‘caching_sha2_password’ cannot be loaded: dlopen(/usr/local/mysql/lib/plugin/caching_sha2_password.so, 2): image not found
在这里插入图片描述
大概意思: 授权插件‘caching_sha2_password’不能被加载,也就是不能对身份验证.
MySQL8.0采用了新的更安全的验证方式,用客户端连接比如navicate,会提示客户端连接caching-sha2-password,是由于客户端不支持这种插件,可以通过如下方式进行修改:
首先我们可以在docker中通过以下命令进行连接

docker exec -it mysql mysql -uroot -pasd123asd

 
 
  • 1

或者
先进入容器(每个容器相当于系统环境,你可要在上面使用linux的基础命令)

docker exec -ti xxx(容器id) /bin/bash

 
 
  • 1

容器内,连接数据库

 mysql -u root -pasd123asd

 
 
  • 1

查看用户信息

select host,user,plugin,authentication_string from mysql.user;

 
 
  • 1

在这里插入图片描述
备注:host为 % 表示不限制ip localhost表示本机使用 plugin非mysql_native_password 则需要修改密码
重新设置一下密码

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'asd123asd'

 
 
  • 1

在这里插入图片描述
此时再重新连接就OK了

1.8 删库跑路

你想删库吗,你想跑路吗?那么可以使用rm命令删除容器以及rmi删除镜像
删除容器:

语法: docker rm [OPTIONS] CONTAINER [CONTAINER…]

在删除容器之前首先先停止运行的容器,否则会出现如下错误
Error response from daemon: You cannot remove a running container 77d983b1b76987b045ba96258f05865591db5c472772213c59ddff2f9597f3b7. Stop the container before attempting removal or force remove

删除mysql容器:

docker rm mysql(或容器ID)

 
 
  • 1

删除镜像:

语法: docker rmi [OPTIONS] IMAGE [IMAGE…]

删除镜像也一样需要先删除相关的容器再删除镜像
删除mysql镜像:

docker rmi mysql(或镜像ID)

 
 
  • 1

2.安装Redis/Mongo

具体不再细说了,基本上和Mysql安装过程差不多
两步搞定(redis):
docker pull redis
docker run -p 6379:6379 --name redis -d redis
两步搞定(mongo):
docker pull mongo
docker run -p 27017:27017 --name mongo -d mongo

四、将Jar包制作成镜像

第一部分讲述了镜像的搜索到最终在容器中运行镜像,通常镜像仓库中不会有我们自己开发应用,因此我们需要将运行的应用制作成镜像,再将其运行于容器中.
我们可以通过Dockerfile构建镜像,也可以手工制作Docker镜像,但过于烦锁,效率低,这里不再赘述.

1.Dockerfile

在开始制作镜像之前需要先了解一下Dockerfile文件.
Dockerfile 是一个对镜像进行描述的文本文件,其内容包含四个部分: 基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令.
简单的说就是告诉Docker,在制作镜像过程中需要怎么做,比如需要java环境,需要制作的应用在哪,应用的启动命令是怎样的等等信息。
一些Dockerfile的部分指令:
基础镜像信息: FROM
维护者信息:MAINTAINER
镜像操作指令: RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等
容器启动时执行指令:CMD、ENTRYPOINT
具体内容详见官方文档:https://docs.docker.com/engine/reference/builder/

2.为Eureka_server编写Dockerfile文件

准备好要制作成镜像的应用,这里以本人在项目开发过程中的一个Eureka服务为例子,应用包名为:eureka_server.jar
创建一个Dockerfile(touch Dockerfile)文件与eureka_server.jar放在同一个文件夹下,如下所示:
Dockerfile
编辑Dockerfile(vim Dockerfile)

FROM java:alpine
ADD eureka_server.jar eureka_server.jar
EXPOSE 9990
ENTRYPOINT ["java","-jar","/eureka_server.jar","--spring.profiles.active=prod"]

 
 
  • 1
  • 2
  • 3
  • 4

大概描述了这样一件事:以java:alpine为镜像基础,将eureka_server.jar文件复制到容器中的eureka_server.jar文件,并在容器内部使用端口9990运行程序,并在容器启动时以java -jar /eureka_server.jar --spring.profiles.active=prod的命令启动应用.
这简短的语法,可以很好的描述该镜像.

3.通过build命令制作镜像

语法: docker build [OPTIONS] PATH | URL | -

eureka应用制作成镜像:

docker build -t eureka .

 
 
  • 1

制作成镜像
-t给镜像命名为eureka,.代表将当前目录下所有文件构建到镜像中.
我们通过images查看下制作好的镜像,并运行看看.

docker run -p 9990:9990 --name eureka eureka

 
 
  • 1

上面启动命令没有-d命令意味着你会在控制台中看到eureka服务的启动过程,和我们在Idea中打印的启动日志一致.等待启动完成即可.
看看效果http://xxxx:9990 看到如下eureka的页面,意味着大功告成.
eureka服务

五、解决容器之间通信问题

以同样的方式,我们启动了ServerA和ServerB. 你会发现如一些问题
问题一: 注册中心中没有看到ServerA和ServerB
问题二: 注册中心都有ServerA和ServerB,可就是调不通
问题三: 互相之间都调通了,可数据库有连不上了.
等等问题,其实这些问题都归结于容器间通信问题,要知道docker中容器之间是相互隔离的
接下来给出一些解决方案和一些注意点.
当你的服务配置eureka使用本地的ip时,虽然注册中心注册成功了,却无法两个应用正常通信.
将会出现Caused by: java.net.UnknownHostException: 0b1659dd7e1d 异常.
解决办法:
使用--link来连接两个容器
下面以上层服务lsgclient(ServerB)和下层服务lsgbase(ServerA)为例子.
首先我们将作为eureka客服端的lsgclient和lsgbase的yaml配置文件中eureka的地址进行修改

eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka-server:9990/eureka/

 
 
  • 1
  • 2
  • 3
  • 4

其中eureka-server为的eureka服务容器名.
启动lsgbase服务(该服务需要连接redis、mariadb、eureka-server),那么可以通过–link连接其它容器
启动服务:

docker run --name lsgbase -p 8010:8010 -p 8888:8888 --link redis --link mariadb:mysql --link eureka-server  lsgbase

 
 
  • 1

看日志打印是否成功
日志打印是否成功

Eureka是否注册成功
Eureka是否注册成功

紧接着我们打开另一个窗口,或者上面在启动是加个-d 参数进行后台启动.
启动lsgclient服务(该服务需要连接lsgbase、eureka-server)

docker run --name lsgclient -p 80:80 -p 8889:8889 --link redis --link eureka-server --link lsgbase -d  lsgclient

 
 
  • 1

看日志打印是否成功
在这里插入图片描述
再看下Eureka看看情况,最后访问下服务,一切ok并且日志不要没有出现UnknownHostException异常,好得很。

注意:这里除了需要link eureka-server外,还需要link lsgbase否则依然报UnknownHostException错误.

好了基本上大功告成了.

六、痛点总结

对以上部署过程的痛点整理:
痛点1:当项目有所改动,每次都要打包上传、还得构建镜像,真是太麻烦了.
痛点2: 在运行进行时如果你的client层所连接的服务有几十个其它服务,那得一个一个link过去吧,那太痛苦了

针对以上痛点,将在下篇文章进行分享

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值