Docker环境搭建1: 使用Docker搭建JavaWeb环境
  • 作者:ZJWave
  • 分类:
  • 发表:2019-01-11 22:21
  • 围观:1021
  • 评论:0

1.前言

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

先来看一下传统虚拟化技术的体系架构:

可见,我们在宿主机的操作系统上,可安装了多个虚拟机,而在每个虚拟机中,通过虚拟化技术,实现了一个虚拟操作系统,随后,就可以在该虚拟操作系统上,安装自己所需的应用程序了。这一切看似非常简单,但其中的技术细节是相当高深莫测的,大神级人物都不一定说得清楚。

凡是使用过虚拟机的同学,应该都知道,启动虚拟机就像启动一台计算机,初始化过程是相当慢的,我们需要等很久,才能看到登录界面。一旦虚拟机启动以后,就可以与宿主机建立网络连接,确保虚拟机与宿主机之间是互联互通的。不同的虚拟机之间却是相互隔离的,也就是说,彼此并不知道对方的存在,但每个虚拟机占用的都是宿主机的硬件与网络资源。

我们再来对比一下 Docker 技术的体系架构:

可见,在宿主机的操作系统上,有一个 Docker 服务在运行(或者称为“Docker 引擎”),在此服务上,我们可开启多个 Docker 容器,而每个 Docker 容器中可运行自己所需的应用程序,Docker 容器之间也是相互隔离的,同样地,都是占用的宿主机的硬件与网络资源。

Docker 容器相对于虚拟机而言,除了在技术实现上完全不一样以外,启动速度较虚拟机而言有本质的飞跃,启动一个容器只在眨眼瞬间。不管是虚拟机还是 Docker 容器,它们都是为了隔离应用程序的运行环境,节省我们的硬件资源,为我们开发人员提供福利。

我们再来看看 Docker 的 Logo:

很明显,这是一只鲸鱼,它托着许多集装箱。我们可以把宿主机可当做这只鲸鱼,把相互隔离的容器可看成集装箱,每个集装箱中都包含自己的应用程序。这 Logo 简直的太形象了!

需要强调的是,笔者并非否定虚拟化技术,而是想通过本文让更多的读者了解如何使用 Docker 技术,让大家知道除了虚拟化技术以外,还有另一种替代技术,也能让应用程序隔离起来。

2.开始搭建

操作系统

Linux CentOS 7.4 ,必须是64位系统以上,其他Linux系统同理。

安装Docker

通过rpm即可安装 Docker 软件:

Docker官网在国内已可以直接打开,所有关于Docker的资料均可以前去官网查找:https://www.docker.com

rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
yum -y install docker-io

命令行显示complete表示安装完成。

可使用以下命令,查看 Docker 是否安装成功:

docker version

若输出了 Docker 的版本号,则说明安装成功了,可通过以下命令启动 Docker 服务:

service docker start

一旦 Docker 服务启动完毕,我们下面就可以开始使用 Docker 了。

下载镜像

直接输入以下命令从官网将Docker镜像下载到本机,

如果想下载其他Linux系统的话需将参数替换为相应系统 
可前往 hub.docker.com/_/centos 在搜索栏中输入系统名称搜索对应命令行,也可通过 
docker search centos 搜索所有可下载的centos镜像

docker search centos
docker pull centos

下载完成后使用以下命令查看本机Docker镜像

docker images

如果看到以上输出,说明可以使用“docker.io/centos”这个镜像了,或将其称为仓库(Repository),该镜像有一个名为“latest”的标签(Tag),此外还有一个随机生成的名为“1e1148e4cc2c”的镜像 ID。此外,我们可以看到该镜像只有 202 MB,非常小巧,而不像虚拟机的镜像文件那样庞大。

现在镜像已经有了,我们下面就需要使用该镜像,来启动容器。

启动容器

容器是在镜像的基础上来运行的,一旦容器启动了,我们就可以登录到容器中,安装自己所需的软件或应用程序。既然镜像已经下载到本地,那么如何才能启动容器呢?

只需使用以下命令即可启动容器:

docker run -i -t -v /usr/local/docker/repos/:/zjwave/repos/ 1e1148e4cc2c /bin/bash

这条命令比较长,我们稍微分解一下,其实包含以下三个部分:

docker run <相关参数> <镜像 ID> <初始命令>

其中,相关参数包括:

  • -i:表示以“交互模式”运行容器
  • -t:表示容器启动后会进入其命令行
  • -v:表示需要将本地哪个目录挂载到容器中,格式:-v <宿主机目录>:<容器目录>

假设我们的所有安装程序都放在了宿主机的/usr/local/docker/repos/目录下,现在需要将其挂载到容器的/zjwave/repos/目录下。

需要说明的是,不一定要使用“镜像 ID”,也可以使用“仓库名:标签名”,例如:docker.io/centos:latest

初始命令表示一旦容器启动,需要运行的命令,此时使用“/bin/bash”,表示什么也不做,只需进入命令行即可。

运行完此命令后可以看到宿主机名称已经换成了镜像ID,说明此时已经处于Docker容器当中。

安装JAVA环境

执行exit先退出Docker容器

exit

查看已创建的Docker容器

docker ps -a

我这里已创建了两个Docker容器,可以通过STATUS看到两个Docker容器处于退出状态。

根据CONTAINER_ID启动Docker容器

docker start 79b9cd9b7ebf

下载jdk8和tomcat并拷贝到linux上的/tmp/java_temp文件夹下

Docker容器中文件与本机文件交互方式有两种

1.通过指定的宿主机共享文件夹方式

刚才创建容器时已为容器指定与宿主机交互文件的文件夹目录

docker run -i -t -v /usr/local/docker/repos/:/zjwave/repos/ 1e1148e4cc2c /bin/bash

为容器指定的宿主机文件夹 :  /usr/local/docker/repos/ , 此时该文件夹下所有文件都可进入Docker容器后在/zjwave/repos/目录下找到

只需将压缩包拷贝至宿主机对应文件夹即可。

cd /tmp/java_temp/
cp apache-tomcat-8.5.35.tar.gz  jdk-8u191-linux-x64.tar.gz /usr/local/docker/repos/

2.通过Docker命令直接拷贝文件到Docker容器中

拷贝/tmp/java_temp目录到Docker容器的/tmp/目录下

docker cp /tmp/java_temp/ 79b9cd9b7ebf:/tmp/

通过CONTAINER_ID再次进入正在运行中的docker容器

docker attach 79b9cd9b7ebf

本文选择第二种文件拷贝方式,下面的过程均在容器内部进行,与你本机无关。

再次进入Docker容器后cd到刚才拷贝文件的目标目录,可以看到拷贝过来的两个tar包

cd /tmp/java_temp/

解压两个压缩包并重命名,为了容器尽可能占用硬盘空间更小,再把解压过后的压缩包删除

tar -zxf apache-tomcat-8.5.35.tar.gz -C .
tar -zxf jdk-8u191-linux-x64.tar.gz -C .
mv jdk1.8.0_191/ jdk/
mv apache-tomcat-8.5.35 tomcat/
ls
rm -rf apache-tomcat-8.5.35.tar.gz
rm -rf jdk-8u191-linux-x64.tar.gz

 

将jdk和tomcat移动到/usr/local 文件夹下

mv jdk /usr/local/
mv tomcat /usr/local/
cd /usr/local/

设置环境变量

在profile文件中插入如下配置:

vi /etc/profile

# set java environment
export JAVA_HOME=/usr/local/jdk
export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib
export PATH=$JAVA_HOME/bin:$PATH
 

重载profile文件,查看java是否安装成功

source /etc/profile
java -version

编写运行脚本

编写一个运行脚本,当启动容器时,运行该脚本,启动 Tomcat,具体过程如下:

首先,创建运行脚本:

vi /root/run.sh

然后,编辑脚本内容如下:

#!/bin/bash
source /etc/profile
sh /usr/local/tomcat/bin/catalina.sh run

为运行脚本添加执行权限

chmod u+x /root/run.sh

退出容器

exit

查看所有容器

docker ps -a

创建JAVA_WEB容器

使用以下命令,根据某个“CONTAINER_ID”来创建一个新的镜像:

docker commit 79b9cd9b7ebf zjwave/javaweb:0.1

该容器的 ID 是“79b9cd9b7ebf”,所创建的镜像名是“zjwave/javaweb:0.1”,随后可使用镜像来启动 Java Web 容器

使用命令查看刚才创建好的镜像

docker images


可见,此时已经看到了最新创建的镜像“zjwave/javaweb:0.1”,其镜像 ID 是“f69a68ced5c1”。正如上面所描述的那样,可以通过“镜像名”或“镜像 ID”来启动容器,与上次启动容器不同的是,现在不再进入容器的命令行,而是直接启动容器内部的 Tomcat 服务。此时,需要使用以下命令:

docker run -d -p 58080:8080 --name javaweb zjwave/javaweb:0.1 /root/run.sh

稍作解释:

  • -d:表示以“守护模式”执行/root/run.sh脚本,此时 Tomcat 控制台不会出现在输出终端上。
  • -p:表示宿主机与容器的端口映射,此时将容器内部的 8080 端口映射为宿主机的 58080 端口,这样就向外界暴露了 58080 端口,可通过 Docker 网桥来访问容器内部的 8080 端口了。
  • --name:表示容器名称,用一个有意义的名称命名即可。

关于 Docker 网桥的内容,需要补充说明一下。实际上 Docker 在宿主机与容器之间,搭建了一座网络通信的桥梁,我们可通过宿主机 IP 地址与端口号来映射容器内部的 IP 地址与端口号,

在一系列参数后面的是“镜像名”或“镜像 ID”,怎么方便就怎么来。最后是“初始命令”,它是上面编写的运行脚本,里面封装了加载环境变量并启动 Tomcat 服务的命令。

当运行以上命令后,会立即输出一长串“容器 ID”,我们可通过docker ps命令来查看当前正在运行的容器。

3.通过浏览器访问Docker容器中的JavaWeb服务器

在浏览器中,输入以下地址,即可访问 Tomcat 首页:

http://zjwave.com:58080/

注意:这里使用的是宿主机的 IP 地址,与对外暴露的端口号 58080,它映射容器内部的端口号 8080。

若无法访问,请查看本机防火墙是否放行了58080端口,修改iptables文件,添加放行端口

vim /etc/sysconfig/iptables

将以下参数添加到iptables中

#docker container
-A INPUT -p tcp -m state --state NEW -m tcp --dport 58080:59443 -j ACCEPT

service iptables start

 

 

4.小结

通过本文,我们了解了 Docker 是什么?它与虚拟机的差别在哪里?以及如何安装 Docker?如何下载 Docker 镜像?如何运行 Docker 容器?如何在容器内安装应用程序?如何在容器上创建镜像?如何以服务的方式启动容器?这一切看似简单,但操作也是相当繁琐的,不过熟能生巧,需要不断地操练。

除了这种手工生成 Docker 镜像的方式以外,还有一种像是写代码一样,可以自动地创建 Docker 镜像的方式。只需要我们编写一个 Dockerfile 文件,随后使用docker build命令即可完成以上所有的手工操作。

作为sandbox(沙箱)大概是container(容器)的最基本想法了 - 轻量级的隔离机制, 快速重建和销毁, 占用资源少。用docker在开发者的单机环境下模拟分布式软件部署和调试,可谓又快又好。

在docker的网站上提到了docker的典型场景:

  • Automating the packaging and deployment of applications(使应用的打包与部署自动化)

  • Creation of lightweight, private PAAS environments(创建轻量、私密的PAAS环境)

  • Automated testing and continuous integration/deployment(实现自动化测试和持续的集成/部署)

  • Deploying and scaling web apps, databases and backend services(部署与扩展webapp、数据库和后台服务)

 

Docker在本质上是一个附加系统。使用文件系统的不同层构建一个应用是有可能的。每个组件被添加到之前已经创建的组件之上,可以比作为一个文件系统更明智。分层架构带来另一方面的效率提升,当你重建存在变化的Docker镜像时,不需要重建整个Docker镜像,只需要重建变化的部分。

可能更为重要的是,Docker旨在用于弹性计算。每个Docker实例的运营生命周期有限,实例数量根据需求增减。在一个管理适度的系统中,这些实例生而平等,不再需要时便各自消亡了。

针对Docker环境存在的不足,意味着在开始部署Docker前需要考虑如下几个问题。首先,Docker实例是无状态的。这意味着它们不应该承载任何交易数据,所有数据应该保存在数据库服务器中。

其次,开发Docker实例并不像创建一台虚拟机、添加应用然后克隆那样简单。为成功创建并使用Docker基础设施,管理员需要对系统管理的各个方面有一个全面的理解。

转载请注明原文链接:ZJ-Wave

发表评论:

共有 0 条评论

Top