手把手教你Java应用进行Docker化
简介:简介:Docker是一个使用Go语言开发的开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的机器上。
一、了解Docker是什么
1.什么是Docker?
历史:
- 2010 dotCloud PAAS :竞争太大
- 2013 docker开源 :发展不理想,决定开源
- 2014.6 Docker1.0
- 2014.7 C轮 $4000万
- 2015.7 D轮 $9500万
- 至今 Docker 1.13
装应用的容器,可以把任何程序放进docker里;
2.Docker思想
logo鲸鱼装货物,很整齐,能装很多;鲸鱼运输集装箱到超级码头,再分发。
- 集装箱 :如把程序所有相关配置都打包,解决在一个环境能运行,另外一个环境运行出错
- 标准化
- 运输方式 : 哪里需要则需要由小鲸鱼运输,如:把应用使用qq发送,u盘拷贝到目的地
- 存储方式 : 把程序copy到笔记本上,需要记住这个目录。不需要关心存储什么地方,使用命令执行即可
- API接口 : 接口标准化,如tomcat,nginx都有自己的启动方式,使用docker就一种启动方式
- 隔离 :如虚拟机,而docker更轻量化,使用linux rxc技术,达到快速创建销毁,可能1秒就创建好了
3.Docker解决了什么问题?
-
我本地运行没问题!
比如一个java web程序要启动起来需要依赖什么?
- 操作系统
- jdk版本
- tomcat版本
- 配置文件,或则与系统相关的。 只要任意一个出现问题,都有可能运行不起来或则运行结果不对
那么docker就是解决这个问题的,把各个配置打包成集装箱,又小鲸鱼送到服务器上,然后运行;
-
系统好卡,哪个哥们又写死循环了?
公用服务器的时候会出现这种情况,某一个应用占用太多资源,导致另外一个应用崩溃; docker则的隔离机制则会在启动时就限制好了,你这个应用可用最大资源是固定的。不会影响到其他的应用
-
双11来了,服务器撑不住啦!
热点事件的时候,访问流量巨大,平时部署这么多机器就纯粹的浪费人力物力; 那么在热点事件来临之际,就需要运维开启大量的机器来支撑。 docker就是解决这个问题的,只需要动动鼠标,配置配置即可快速扩容
二、走进Docker
1.核心词汇
- 镜像 :集装箱
- 仓库 :超级码头
- 容器 :程序运行的地方
去仓库把镜像拉到本地,用命令把程序运行起来,变成服务器;
Docker - Build, Ship, and Run Any App, Anywhere
build
:构建
镜像ship
:运输
镜像run
:运行
镜像
2.Docker镜像
image :一系列的文件;文件就会有存储到哪里?格式是什么?
联合文件系统(UnionFS) 是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。
简单说:将不同的目录挂载到同一个虚拟目录下;相当于分库分表这种,入口就是一个大表
上图是docker镜像的存储格式,一层一层的,就像集装箱。
- bootfs 操作系统引导
- base image : 具体的linux系统
- image :软件,应用代码
- container : 先忽略
除了 container 都是只读的,这种文件格式就叫镜像、
3.Docker容器
可以先把容器想象成一个虚拟机;整个就是一个文件系统。只有容器这一层是可写的;
可以保证,同一个镜像可以被多个容器运行
有了镜像,把镜像传输到目的地。那么这个仓库就是用来存储镜像的,需要的地方从仓库拉取镜像
那么谁提供仓库呢?
- hub.docker.com // docker官网提供,国内访问国外网速都差于是出现了第三方仓库
- c.163.com // 网易云
- 自己搭建仓库 // 内部使用
4.安装Docker
windows安装
windows10之外: docker-toolbox : 会虚拟一个docker运行环境
windows10 :原生支持
下载地址官网查看即可;https://www.docker.com/products/docker-desktop
macos
新版已经原生支持mac了;上面地址中查看;
macos中安装docker是所有平台中最方便的,直接拖进 application中即完成安装
linxu
- redhat centos:(http://www.imooc.com/article/16448)
- ubuntu
下载地址:
apt-get install -y docker.io
curl -s https://get.docker.com | sh
service docker start
三、Docker初体验
1.第一个实例Hello-world
从仓库拉取一个镜像,命令语法:
docker pull [OPTIONS] name:[TAG]
name: 镜像名称
TAG:镜像版本
查看本机有哪些镜像
docker images [OPTIONS] [REPOSITORY][:TAG]
REPOSITORY: 镜像名称;
后面的可选参数用得比较少,除非很多很多镜像的时候
拉取一个 hello-world 镜像;
docker pull hello-world
镜像运行到容器上
把下载的hello-world运行起来
运行命令:
docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARGS...]
COMMAND: 镜像运行起来的时候要执行什么命令
看到如下信息则标识运行成功了,下面有解释了为了打印这个消息,docker做了4步
运行过程
2.第二个实例 docker运行nginx静态网站
实践前奏:
- 持久化运行的容器
- 前台挂起 & 后台运行
- 进入容器内部
docker pull nginx
先查看本机镜像
运行
docker run nginx
敲完之后,终端阻塞了,这个应该是前台运行的,可以在另开一个终端使用 查看当前正在运行的容器
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3ccaf24ee0e hub.c.163.com/library/nginx "nginx -g 'daemon ..." About a minute ago Up About a minute 80/tcp vibrant_almeida
后台运行直接加 -d参数即可,可以使用 docker run --help
命令查看,其他命令也是一样,也可以使用help
docker run -d nginx
进入容器,
# -it 分配一个伪终端。 29 是容器id部分字符串, bash 是要运行的命令
[root@localhost ~]# docker exec -it 29 bash
root@29dc6a24c527:/# which nginx
/usr/sbin/nginx
# 使用exit可以退出容器;
docker内部网络
- 网络类型 :网络也是一种隔离类型
- bridge : 桥接模式(默认)
- host :与宿主机使用同一个
- none
- 端口映射 :容器内的网络是隔离的,所以需要一种手段来访问到容器内的网络端口
使用端口映射来运行nginx
# -p 端口映射:8080 是宿主机上的端口,80 是容器内的端口
# 运行之后,就可以通过访问宿主机8080端口进行访问容器内的nginx了
# -P 大写P,是把所有端口使用随机端口映射,可以通过docker ps 看到端口映射的详情
docker run -d -p 8080:80 hub.c.163.com/library/nginx
# 查看 8080端口是否ok
netstat -na|grep 8080
3.第三个实例 第一个java web应用
制作自己的镜像
-
Dockerfile : 如何制作镜像,写代码
-
docker build : 构建
-
Jpress:
http://jpress.io/ 下载这个博客应用,然后用这个项目来练手 https://gitee.com/fuhai/jpress/tree/alpha/wars 下载这个
Dockerfile
# 继承一个镜像,这里找一个tomcat,意思是以tomcat为一个基础点
# docker pull hub.c.163.com/library/tomcat:latest
# 先让那个去下载,这里接着写,到时候就不用再下载了
from hub.c.163.com/library/tomcat:latest
# 容器信息
MAINTAINER liuguoguo xxx@163.com
# 把这个war文件copy到某一个地方
# 这里把之前下载的war复制到 tomcat中的一个目录中去
# 可以查看镜像仓库 刚才下载的地方有说明怎么使用的。里面有一个目录就是用来放war包的
COPY jpress-web-newest.war /usr/local/tomcat/webapps
这里我新建了一个目录,把Dockerfile和要打包的war都放在这个目录里面了,执行命令也是在这个目录里面
运行命令:docker build .
[root@localhost dockerdemo]# docker build .
Sending build context to Docker daemon 20.8 MB
Step 1/3 : FROM hub.c.163.com/library/tomcat:latest
---> 72d2be374029
Step 2/3 : MAINTAINER liuguoguo xxx@163.com
---> Using cache
---> af2a0019bc2d
Step 3/3 : COPY jpress-web-newest.war /usr/local/tomcat/webapps
---> 75a573e4e281
Removing intermediate container 9c88b6be1ef3
Successfully built 75a573e4e281
可以看到执行了3个步骤;最后一步是把镜像移动到了 docker中;
查看镜像,发现出现一个 none的镜像;
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 75a573e4e281 54 seconds ago 313 MB
这个是打包的时候没有指定名称和版本;重新编译下
docker build . -t jpress:latest
# 可以使用--help命令查看docker build 的帮助信息
再次查看
[root@localhost dockerdemo]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jpress latest 75a573e4e281 3 minutes ago 313 MB
运行自己的容器
镜像打好了,来运行这个镜像
# 镜像内部端口需要查看tomcat默认开放的端口是什么,因为我们之前没有做任何的修改
docker run -d -p 8080:8080 jpress
# 查看是否已经运行
docker ps
# 查看8080端口是否已经使用
netstat -na|grep 8080
访问地址:http://localhost:8080/ 可以看到tomcat的页面了。
由于默认的tomcatwar 是增加了项目名;所以访问:http://localhost:8080/jpress-web-newest (war包名就是这个,所以项目名就是war包名)
已经打开了,使用该博客打开就有一个引导,需要填写数据库;
这里在docker中运行一个mysql
# -e 是设置环境参数,这个是在镜像描述使用说明里面看到的
# 这样可以设置一个root的用户名和密码
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=jpress hub.c.163.com/library/mysql:latest
st:8080/ 可以看到tomcat的页面了。
由于默认的tomcatwar 是增加了项目名;所以访问:http://localhost:8080/jpress-web-newest (war包名就是这个,所以项目名就是war包名)
已经打开了,使用该博客打开就有一个引导,需要填写数据库;
这里在docker中运行一个mysql