如何怎么使用java开发工具Docker 进行Java 开发

查看: 1739|回复: 0
持续集成:Docker、Maven、Java
主题帖子积分
本帖最后由 xuanxufeng 于
17:02 编辑
问题导读
1.如何使用Maven构建Docker镜像?
2.每一个docker镜像是否有有它自己的Maven模块?
3.你认为什么是Dockerfile?
在Alooma【一个Java公司】,我们非常非常非常喜爱Docker。真的, 我们想完全容器化我们的应用。 虽然容器化应用有非常多的好处,但在这里,我并不是要说服你用Docker。我们只是认为你和我们一样喜欢这东西。
接下来,让我们谈谈Alooma是如何在生产环境使用Docker来精简开发流程并快速push代码的。
Docker允许你把基础架构当作代码一样来对待。这个代码就是你的Dockerfile。像其它代码一样,我们想要使用一个紧密的改变-&提交-&构建-&测试的周期(一个完整的持续集成解决方案)。为了实现这个目标,我们需要构建一个流畅的DevOps流水线。让我们把目标分解为更加详细的需求:在版本控制系统中管理Dockerfile在CI服务器上为每个commit构建Docker镜像上传构件并打标签(这个构件要能够简单的部署)
我们的工作流
我们的DevOps流水线围绕GitHub、Jenkins和Maven构建。下面是它的工作流程:GitHub将repo的每一个push通知给JenkinsJenkins触发一个Maven buildMaven 构建所有的东西,包括Docker镜像最后,Maven会把镜像推送到私有的Docker Registry。
这个工作流的好处是它允许我们能够很容易的为每个发布版本打标签(所有的commit都被构建并且在我们的Docker Registry中准备好了)。然后我们可以非常容易地通过pull和run这些Docker镜像进行部署。事实上这个部署过程是非常简单的,我们通过发送一个命令给我们信任的Slack机器人:”Aloominion”(关于我们的机器人朋友的更多情况将在未来的文章中发表)开始这个过程。你可能对这个工作流中的其他元素非常熟悉,因为它们都很常见。所以,让我们来深入了解如何使用Maven构建Docker镜像。
深入Docker 构建
Alooma是一个Java公司。我们已经使用Maven作为我们构建流水线的中心工具,所以很自然的想到把构建Docker的过程也加入到我们的Maven构建过程中去。
当搜索和Docker交互的Maven插件时,出现了3个选项。我们选择使用Spotify的maven-docker-plugin —— 虽然rhus的和alexec的同名插件看起来也是一个不错的选择。
另一个我们的构建计划依赖的Maven插件是maven-git-commit-id-plugin。我们使用这个插件,所以我们的Docker镜像能使用git的commit ID来打标签 —— 这在部署过程中非常有帮助,我们可以了解运行的是哪个版本。
给我看代码!
每一个docker镜像有它自己的Maven模块(所有上面提到的docker-maven 插件在一个模块一个Dockerfile时都能顺利地工作)
让我们从Spotify插件的一个简单配置开始:
[Bash shell] 纯文本查看 复制代码&plugin&
&groupId&com.spotify&/groupId&
&artifactId&docker-maven-plugin&/artifactId&
&dockerDirectory&${project.basedir}&/dockerDirectory&
&imageName&alooma/${project.artifactId}&/imageName&
&/configuration&
我们看到这里我们把插件的build目标和Maven的package阶段绑定,我们也指导它去在我们模块的根目录下来寻找Dockerfile(使用DockerDirectory 元素来指定),我们还把镜像名称用它的构件Id来命名(用”alloma/”做前缀)。
我们注意到的第一件事情是这个镜像没有被push到任何地方,我们可以通过加入&pushImage&true&/pushImage&到配置中来解决这个问题。
但是现在这个镜像会被push到默认的Docker Hub Registry上。糟糕。
为了解决这个问题,我们定义了一个新的Maven属性&docker.registry&docker-registry.alooma.io:5000/&/docker.registry&并且把镜像名称imageName改为${docker.registry}alooma/${project.artifactId}。 你可能会想,“为什么需要为Docker Registry设置一个属性?”, 你是对的!但是有这个属性可以使我们在Regsitry URL改变的时候能够更方便的修改。
有一个更重要的事情我们还没有处理——我们想让每一个镜像用它的git commit ID来打标签。这可以通过改变imageName为${docker.registry}alooma/${project.artifactId}:${mit.id.abbrev}来实现。
${mit.id.abbrev}属性是通过我上面提到的maven-git-commit-id-plugin插件来实现的。
所以,现在我们的插件配置看起来像下面这样:
[Bash shell] 纯文本查看 复制代码&artifactId&docker-maven-plugin&/artifactId&
&dockerDirectory&${project.basedir}&/dockerDirectory&
&imageName&
${docker.registry}alooma/${project.artifactId}:${mit.id.abbrev}
&/imageName&
&pushImage&true&/pushImage&
&/configuration&
我们的下一个挑战是在我们的pom.xml中表达我们的Dockerfile的依赖。一些我们的Docker镜像在构建时使用了 FROM 其它的Docker 镜像作为基础镜像(也在同一个构建周期中构建)。例如,我们的webgate镜像(是我们的机遇Tomcat的WebApp)基于我们的base镜像(包含Java 8、更新到最新的 apt-get、等等)。
这些镜像在同一个构建过程中构建意味着我们不能简单的使用FROM docker-registry.alooma.io/alooma/base:some-tag因为我们需要这个标签编程当前构建的标签(即 git commit ID)。
为了在Dockerfile中获得这些属性,我们使用了Maven的resource filtering功能。这在一个资源文件中替换Maven 的属性。
[Bash shell] 纯文本查看 复制代码&resource&
&directory&${project.basedir}&/directory&
&filtering&true&/filtering&
&includes&
&include&**/Dockerfile&/include&
&/includes&
&/resource&
在Dockerfile的内部我们有一个这样的FROM:
[Bash shell] 纯文本查看 复制代码FROM ${docker.registry}alooma/base:${mit.id.abbrevs}
一些更多的事情…….我们需要的是我们的配置来找到正确的Dockerfile(过滤过之后的),这可以在target/classes文件夹内找到,所以我们把dockerDirectory改为${project.build.directory}/classes。
这意味着现在我们的配置文件长这样:
[Bash shell] 纯文本查看 复制代码&resources&
&resource&
&directory&${project.basedir}&/directory&
&filtering&true&/filtering&
&includes&
&include&**/Dockerfile&/include&
&/includes&
&/resource&
&/resources&
&pluginManagement&
&imageName&
${docker.registry}alooma/${project.artifactId}:${mit.id.abbrev}
&/imageName&
&/configuration&
&/plugins&
&/pluginManagement&
此外,我们还要添加base构件作为webgate模块的一个Maven依赖来保证正确的Maven构建顺序。
但是我们还有另一个挑战:我们如何把我们编译和打包了的源文件添加到我们的Docker镜像中呢?我们的Dockerfile依赖于很多其它文件,它们通过ADD或COPY命令插入。[你可以在这里()读到更多的关于Dockerfile的指导。]
为了让这些文件可以被获取,我们需要使用插件配置的resources标签。
[Bash shell] 纯文本查看 复制代码&resources&
&resource&
&targetPath&/&/targetPath&
&directory&${project.basedir}&/directory&
&excludes&
&exclude&target/**/*&/exclude&
&exclude&pom.xml&/exclude&
&exclude&*.iml&/exclude&
&/excludes&
&/resource&
&/resources&
注意到我们排除了一些文件。
记住这个resources标签不应该和通常的Maven resources标签弄混,看看下面的例子,它来自于我们的pom.xml的一部分:
[Bash shell] 纯文本查看 复制代码&resources&
&resource&
&includes&
&include&**/Dockerfile&/include&
&/includes&
&groupId&com.spotify&/groupId&
&artifactId&docker-maven-plugin&/artifactId&
&version&0.2.3&/version&
&/plugins&
&/pluginManagement&
前一个添加在我们想添加一些静态资源到镜像时工作,但是如果我们想要添加一个在同一个构建中构建的构件时需要更多的调整。
例如,我们的webgate Docker镜像包含了我们的webgate.war,这是由另一个模块构建的。
为了添加这个war作为资源,我们首先必须把它作为我们的Maven依赖加进来,然后使用maven-dependency-plugin插件的copy目标来把它加到我们当前的构建目录中。
[Bash shell] 纯文本查看 复制代码&plugin&
&groupId&org.apache.maven.plugins&/groupId&
&groupId&com.alooma&/groupId&
&artifactId&webgate&/artifactId&
&version&${project.parent.version}&/version&
&type&war&/type&
&outputDirectory&${project.build.directory}&/outputDirectory&
&destFileName&webgate.war&/destFileName&
现在这允许我们简单的把这个文件加到Docker插件的resources中去。
[Bash shell] 纯文本查看 复制代码&resources&
&include&**/Dockerfile&/include&
&/includes&
&groupId&com.spotify&/groupId&
&artifactId&docker-maven-plugin&/artifactId&
&version&0.2.3&/version&
&executions&
&/executions&
&/plugins&
&/pluginManagement&
我们需要做的最后一件事情是让我们的CI服务器(Jenkins)真的将镜像push到Docker Registry上。请记住本地构件默认是不会push镜像的。
为了push这些镜像,我们改变我们的&pushImage&标签的值从true变为${push.image}属性,这默认是被设置为false,并且只会在CI服务器上设置为true。
译注:这里的意思是,由于开发人员也要在本地构建然后测试之后才会提交,而测试的镜像不应该被提交到Registry,所以&pushImage&应该使用一个属性,默认为false,在CI服务器上覆盖为true在构建后去push镜像。
这就完成了!让我们看一下最终的代码:
[Bash shell] 纯文本查看 复制代码&resources&
&resource&
&directory&${project.basedir}&/directory&
&filtering&true&/filtering&
&includes&
&include&**/Dockerfile&/include&
&/includes&
&/resource&
&/resources&
&pluginManagement&
&groupId&com.spotify&/groupId&
&artifactId&docker-maven-plugin&/artifactId&
&version&0.2.3&/version&
&executions&
&execution&
&phase&package&/phase&
&goal&build&/goal&
&/execution&
&/executions&
&configuration&
&dockerDirectory&${project.build.directory}/classes&/dockerDirectory&
&pushImage&${push.image}&/pushImage&
&!-- true when Jenkins builds, false otherwise --&
&imageName&
${docker.registry}alooma/${project.artifactId}:${mit.id.abbrev}
&/imageName&
&resources&
&resource&
&targetPath&/&/targetPath&
&directory&${project.basedir}&/directory&
&excludes&
&exclude&target/**/*&/exclude&
&exclude&pom.xml&/exclude&
&exclude&*.iml&/exclude&
&/excludes&
&/resource&
&rescource&
&targetPath&/&/targetPath&
&directory&${project.build.directory}&/directory&
&include&webgate.war&/include&
&/rescource&
&/resources&
&/configuration&
&/plugins&
&/pluginManagement&
这个过程有两个能够提高你的构建和部署的性能的改进地方:让你的基础的机器镜像(在EC2的例子下是AMI)包含一些你的Docker镜像的基础版本。这样会使得docker pull只去pull那些改变了的层,即增量(相对于整个镜像来说要小得多)。在Docker Registry的前端放一个Redis缓存。这可以缓存标签和元数据,减少和真实存储(在我们的例子下是S3)的回环。
我们现在已经使用这个构建过程一段时间了,并且对它非常满意。然而仍然有提高的空间,如果你有任何关于让这个过程更加流畅的建议,我很乐意在评论中听到你的想法。
站长推荐 /6
about云|新出视频,openstack零基础入门,解决你ping不通外网难题
云计算hadoop视频大全(新增 yarn、flume|storm、hadoop一套视频
视频资料大优惠
大数据零基础由入门到实战
阶段1:hadoop零基础入门基础篇
阶段2:hadoop2入门
阶段3:大数据非hadoop系列课程
阶段4:项目实战篇
阶段5:大数据高级系列应用课程
阶段6:工作实用系列教程
等待验证会员请验证邮箱
新手获取积分方法
Powered by当前位置: →
Docker应用实践:一个简单的Java EE&Docker示例
学习Docker的最好办法就是迅速在工作中应用它,本文作者使用Docker部署了一个Java EE应用,非常简单和方便。需要注意的是,由于作者写作时本地网络有问题,所以Dockerfile中很多的资源都没有从网络下载,你再实践时,可以尝试修改。学习快乐 :)
本文中,我们将会把Java EE和Docker结合,具体内容如下:
创建、构建并运行一个Docker镜像;通过镜像启动一个Wildfly服务器,并部署了一个JavaEE示例应用;展示一些常用的Docker命令;启动多个容器,并让同一应用运行于不同端口。
在这里我不再介绍Docker,因为已经有太多的介绍性的文章。写本文之前,我阅读了如下教程:
Docker用户指南;使用Docker镜像;Docker终极指南(译者注:已翻译);Arun Gupta的技术技巧:#39、#57、#61和#65。
要完成本教程,你需要:
有一个运行于宿主机上的Docker后台进程安装Docker后,在etcdefaultdocker文件中添加一行:DOCKER_OPTS=&-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock此后重启机器并尝试运行这个命令:docker -H tcp://127.0.0.1:2375 &version,输出应该类似这样的:Docker version 1.4.1, build 5bc2ff8一个Wildfly 8.2.0的安装程序(解压后的);jdk-8u25-linux-x64.tar.gz文件。(/technetwork/java/javase/downloads/index.html)下载 car-service.war。(/rmpestano/javaee-docker-sample/blob/master/java_ee/car-service.war)下载 Dockerfile。(/rmpestano/javaee-docker-sample/blob/master/java_ee/Dockerfile)
创建Docker镜像
Docker镜像展现/描述了容器本身。由于我的网络带宽有限(手机3G),在这里我使用本机资源创建了一个镜像。因此,这个镜像只有在包含如下文件的目录下构建才能使用:
wildfly-8.2.0.Final:应用服务器car-service.war:要部署的应用Dockerfile:描述容器的文件jdk-8u25-linux-x64.tar.gz:要在容器里安装的java版本
注意:不推荐在Docker容器中使用本地资源,因为只有当所有文件都存在时镜像才可以正常构建。最好的办法是从头安装所有东西并下载必要的文件。
这是Dockerfile的内容:
FROM ubuntu MAINTAINER Rafael Pestano && setup WildFly COPY wildfly-8.2.0.Final /opt/wildfly install example app on wildfy COPY car-service.war /opt/wildfly/standalone/deployments/ setup Java RUN mkdir /opt/java COPY jdk-8u25-linux-x64.tar.gz /opt/java/ change dir to Java installation dir WORKDIR /opt/java/ RUN tar -zxf jdk-8u25-linux-x64.tar.gz setup environment variables RUN update-alternatives --install /usr/bin/javac javac /opt/java/jdk1.8.0_25/bin/javac 100 RUN update-alternatives --install /usr/bin/java java /opt/java/jdk1.8.0_25/bin/java 100 RUN update-alternatives --display java RUN java -version Expose the ports we're interested in EXPOSE
Set the default command to run on boot This will boot WildFly in the standalone mode and bind to all interface CMD [&/opt/wildfly/bin/standalone.sh&, &-c&, &standalone-full.xml&, &-b&, &0.0.0.0&]
镜像继承自Ubuntu&&一个安装了Ubuntu操作系统的镜像。Docker安装教程中就安装了Ubuntu镜像。
接着,我们将服务器复制到容器的/opt/wildfly目录。COPY是Dockerfile的一个指令。我们可以在这里找到所有命令。
我们随后将应用的war包复制到服务器中:
COPY car-service.war /opt/wildfly/standalone/deployments/。
然后,我们将Java解压安装到容器的/opt/java目录并设置一些环境变量。最好的办法是使用apt-get,不过这要求有互联网接入,而我写作时不具备这个条件。我使用RUN命令来执行java -version,(如果Java正确安装的话)它将在镜像构建时打印版本号。
之后,我使用EXPOSE 来告诉Docker容器要暴露的端口号。容器其实是镜像的实例,运行镜像(docker run)时,我们可以指定允许宿主访问的端口。
最后,我们指定了默认命令:CMD [&/opt/wildfly/bin/standalone.sh&, &-c&, &standalone-full.xml&, &-b&, &0.0.0.0&]。每次容器启动时都会运行这个命令。
在描述完镜像之后,我们需要构建它。在包含Dockerfile的父目录运行以下命令:
docker -H tcp://127.0.0.1:2375 build -t javaee_sample java_ee/ -H参数指定了Docker后台地址(使用TCP与后台通讯);build是命令本身;-t指定了用于识别镜像的标签名称(这里是javaee_sample);java_ee/是包含用于描述镜像的Dockerfile的目录。
上述命令的输出如下:
然后我们可以通过列出镜像命令(译者注:docker images命令)来确认刚创建的镜像:docker -H tcp://127.0.0.1:2375 images:
使用这一命令启动容器:
docker -H tcp://127.0.0.1:2375 run -p
javaee_sample -p指定容器端口到主机端口的映射;run是命令本身;javaee_sample是镜像名。
容器启动过程中会输出Wildfly启动日志,这是因为我们将其设置为初始命令(CMD Dockerfile命令):
运行多个容器
我们可以实例化多个容器,因为它们的端口在宿主上不会发生冲突。我将再启动两个容器并将8080端口分别暴露为:
docker -H tcp://127.0.0.1:2375 run -p
javaee_sample docker -H tcp://127.0.0.1:2375 run -p
javaee_sample
要列出启动的容器,我们可以使用命令:docker -H tcp://127.0.0.1:2375 ps,这是输出结果:
rmpestano@rmpestano-ubuntu:~/docker /images$ docker -H tcp://127.0.0.1:2375 ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7b javaee_sample:latest &/opt/wildfly/bin/st 27 seconds ago Up 27 seconds 9990/tcp, 0.0.0.0:/tcp suspicious_lovelace d javaee_sample:latest &/opt/wildfly/bin/st 28 seconds ago Up 28 seconds 9990/tcp, 0.0.0.0:/tcp loving_hopper 96e58eb65126 javaee_sample:latest &/opt/wildfly/bin/st 42 seconds ago Up 42 seconds 9990/tcp, 0.0.0.0:/tcp clever_cori
现在我们可以在浏览器中同时访问这三个应用:
你可以通过容器的ID或名字来停止容器:
docker -H tcp://127.0.0.1:2375 stop suspicious_lovelace
记住,在容器删除时所有数据将消失。请使用Docker卷来持久化数据。
原文链接:/article/146
关注官方微信
扫一扫分享本文到朋友圈
联系我们:
&(发送邮件时,请把#换成@)
投稿信箱:
&(发送邮件时,请把#换成@)
企业网版权所有当前访客身份:游客 [
学习 o 讨论 o 总结 o 分享
:引用来自“幻影浪子”的评论 引用来自“黄勇”的...
:引用来自“黄勇”的评论 引用来自“明明没办法”...
:引用来自“明明没办法”的评论能请问下这种框架的...
:能请问下这种框架的编写是基于哪个通信协议?是R...
:引用来自“jiahuawalden”的评论勇哥,这几天一直...
:引用来自“silence-try”的评论求助大神,我执行...
:求助大神,我执行第六步时[ERROR] Nexus Staging...
:学习了,
:package cn.him.dyna.proxy2; import java.lang....
今日访问:17
昨日访问:826
本周访问:1778
本月访问:2825
所有访问:260071
使用 Docker 搭建 Java Web 运行环境
发表于1年前( 00:06)&&
阅读(15513)&|&评论()
0人收藏此文章,
Docker 是 2014 年最为火爆的技术之一,几乎所有的程序员都听说过它。Docker 是一种“轻量级”容器技术,它几乎动摇了传统虚拟化技术的地位,现在国内外已经有越来越多的公司开始逐步使用 Docker 来替换现有的虚拟化平台了。作为一名 Java 程序员,我们是时候一起把 Docker 学起来了!
本文会对虚拟化技术与 Docker 容器技术做一个对比,然后引出一些 Docker 的名词术语,比如:容器、镜像等,随后将使用 Docker 搭建一个 Java Web 运行环境,最后将对本文做一个总结。
我们先来回顾一下传统虚拟化技术的体系架构:
![虚拟化技术][1]
可见,我们在宿主机的操作系统上,可安装了多个虚拟机,而在每个虚拟机中,通过虚拟化技术,实现了一个虚拟操作系统,随后,就可以在该虚拟操作系统上,安装自己所需的应用程序了。这一切看似非常简单,但其中的技术细节是相当高深莫测的,大神级人物都不一定说得清楚。
凡是使用过虚拟机的同学,应该都知道,启动虚拟机就像启动一台计算机,初始化过程是相当慢的,我们需要等很久,才能看到登录界面。一旦虚拟机启动以后,就可以与宿主机建立网络连接,确保虚拟机与宿主机之间是互联互通的。不同的虚拟机之间却是相互隔离的,也就是说,彼此并不知道对方的存在,但每个虚拟机占用的都是宿主机的硬件与网络资源。
我们再来对比一下 Docker 技术的体系架构吧:
![Docker 技术][2]
可见,在宿主机的操作系统上,有一个 Docker 服务在运行(或者称为“Docker 引擎”),在此服务上,我们可开启多个 Docker 容器,而每个 Docker 容器中可运行自己所需的应用程序,Docker 容器之间也是相互隔离的,同样地,都是占用的宿主机的硬件与网络资源。
Docker 容器相对于虚拟机而言,除了在技术实现上完全不一样以外,启动速度较虚拟机而言有本质的飞跃,启动一个容器只在眨眼瞬间。不管是虚拟机还是 Docker 容器,它们都是为了隔离应用程序的运行环境,节省我们的硬件资源,为我们开发人员提供福利。
我们再来看看 Docker 的 Logo 吧:
![Docker Logo][3]
很明显,这是一只鲸鱼,它托着许多集装箱。我们可以把宿主机可当做这只鲸鱼,把相互隔离的容器可看成集装箱,每个集装箱中都包含自己的应用程序。这 Logo 简直的太形象了!
& 需要强调的是,笔者并非否定虚拟化技术,而是想通过本文让更多的读者了解如何使用 Docker 技术,让大家知道除了虚拟化技术以外,还有另一种替代技术,也能让应用程序隔离起来。
下面,我们将结合一个 Java Web 应用的部署过程,来描述如何“烹饪”Docker 这份美味佳肴。您准备好了吗?我们现在就开始!
## 前提条件
首先,您要准备一个 CentOS 的操作系统,虚拟机也行。总之,可以通过 Linux 客户端工具访问到 CentOS 操作系统就行。
需要说明的是,Ubuntu 或其它 Linux 操作系统也能玩 Docker,只不过本文选择了以 CentOS 为例,仅此而已。
CentOS 具体要求如下:
1. 必须是 64 位操作系统
2. 建议内核在 3.8 以上
通过以下命令查看您的 CentOS 内核:
如果执行以上命令后,输出的内核版本号低于 3.8,请参考下面的方法来来升级您的 Linux 内核。
对于 CentOS 6.5 而言,内核版本默认是 2.6。首先,可通过以下命令安装最新内核:
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -ivh http://www.elrepo.org/elrepo-release-6-5.el6.elrepo.noarch.rpm
yum -y --enablerepo=elrepo-kernel install kernel-lt
随后,编辑以下配置文件:
vi /etc/grub.conf
将`default=1`修改为`default=0`。
最后,通过`reboot`命令重启操作系统。
重启后如果不出意外的话,再次查看内核,您的 CentOS 内核将会显示为 3.10。
如果到这里,您和我们所期望的结果是一致的。恭喜您!下面我们就一起来安装 Docker 了。
## 安装 Docker
只需通过以下命令即可安装 Docker 软件:
rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
yum -y install docker-io
可使用以下命令,查看 Docker 是否安装成功:
docker version
若输出了 Docker 的版本号,则说明安装成功,我们下面就可以开始使用 Docker 了。
可通过以下命令启动 Docker 服务:
service docker start
就像曾经安装软件一样,我们首先需要有一张刻录了该软件的光盘,如果您使用的是虚拟光驱,那么就需要运行一种名为“镜像”的文件,通过它来安装软件。在 Docker 的世界里,也有一个名为“镜像”的东西,已经安装我们所需的操作系统,我们一般成为“Docker 镜像”,本文简称“镜像”。
那么问题来了,我们从哪里下载镜像呢?
[Docker 官网][4] 确实已经提供了所有的镜像下载地址,可惜在国内却是无法访问的。幸好国内好心人提供了一个 [Docker 中文网][5],在该网站上可以下载我们所需的 Docker 镜像。
## 下载镜像
我们不妨还是以 CentOS 为例,通过以下步骤,下载一个 CentOS 的镜像。
首先,访问 Docker 中文网,在首页中搜索名为“centos”的镜像,在搜索的结果中,有一个“官方镜像”,它就是我们所需的。
然后,进入 CentOS 官方镜像页面,在“Pull this repository”输入框中,有一段命令,把它复制下来,在自己的命令行上运行该命令,随后将立即下载该镜像。
最后,使用以下命令查看本地所有的镜像:
docker images
当下载完成后,您应该会看到:
REPOSITORY
VIRTUAL /docker/centos
7 weeks ago
如果看到以上输出,说明您可以使用“/docker/centos”这个镜像了,或将其称为仓库(Repository),该镜像有一个名为“centos6”的标签(Tag),此外还有一个名为“25c ”的镜像 ID(可能您所看到的镜像 ID 与此处的不一致,那是正常现象,因为这个数字是随机生成的)。此外,我们可以看到该镜像只有 215.8 MB,非常小巧,而不像虚拟机的镜像文件那样庞大。
现在镜像已经有了,我们下面就需要使用该镜像,来启动容器。
## 启动容器
容器是在镜像的基础上来运行的,一旦容器启动了,我们就可以登录到容器中,安装自己所需的软件或应用程序。既然镜像已经下载到本地,那么如何才能启动容器呢?
只需使用以下命令即可启动容器:
docker run -i -t -v /root/software/:/mnt/software/ 25c /bin/bash
这条命令比较长,我们稍微分解一下,其实包含以下三个部分:
docker run &相关参数& &镜像 ID& &初始命令&
其中,相关参数包括:
- `-i`:表示以“交互模式”运行容器
- `-t`:表示容器启动后会进入其命令行
- `-v`:表示需要将本地哪个目录挂载到容器中,格式:-v &宿主机目录&:&容器目录&
假设我们的所有安装程序都放在了宿主机的`/root/software/`目录下,现在需要将其挂载到容器的`/mnt/software/`目录下。
需要说明的是,不一定要使用“镜像 ID”,也可以使用“仓库名:标签名”,例如:/docker/centos:centos6。
初始命令表示一旦容器启动,需要运行的命令,此时使用“/bin/bash”,表示什么也不做,只需进入命令行即可。
## 安装相关软件
为了搭建 Java Web 运行环境,我们需要安装 JDK 与 Tomcat,下面的过程均在容器内部进行。我们不妨选择`/opt/`目录作为安装目录,首先需要通过`cd /opt/`命令进入该目录。
### 安装 JDK
首先,解压 JDK 程序包:
tar -zxf /mnt/software/jdk-7u67-linux-x64.tar.gz -C .
然后,重命名 JDK 目录:
mv jdk1.7.0_67/ jdk/
### 安装 Tomcat
首先,解压 Tomcat 程序包:
tar -zxf /mnt/software/apache-tomcat-7.0.55.tar.gz -C .
然后,重命名 Tomcat 目录:
mv apache-tomcat-7.0.55/ tomcat/
## 设置环境变量
首先,编辑`.bashrc`文件
vi ~/.bashrc
然后,在该文件末尾添加如下配置:
export JAVA_HOME=/opt/jdk
export PATH=$PATH:$JAVA_HOME
最后,需要使用`source`命令,让环境变量生效:
source ~/.bashrc
## 编写运行脚本
我们需要编写一个运行脚本,当启动容器时,运行该脚本,启动 Tomcat,具体过程如下:
首先,创建运行脚本:
vi /root/run.sh
然后,编辑脚本内容如下:
#!/bin/bash
source ~/.bashrc
sh /opt/tomcat/bin/catalina.sh run
注意:这里必须先加载环境变量,然后使用 Tomcat 的运行脚本来启动 Tomcat 服务。
最后,为运行脚本添加执行权限:
chmod u+x /root/run.sh
## 退出容器
当以上步骤全部完成后,可使用`exit`命令,退出容器。
随后,可使用如下命令查看正在运行的容器:
此时,您应该看不到任何正在运行的程序,因为刚才已经使用`exit`命令退出的容器,此时容器处于停止状态,可使用如下命令查看所有容器:
docker ps -a
输出如下内容:
CONTAINER ID
57c312bbaad1
/docker/centos:centos6
"/bin/bash"
27 minutes ago
Exited (0) 19 seconds ago
naughty_goldstine
记住以上`CONTAINER ID`(容器 ID),随后我们将通过该容器,创建一个可运行 Java Web 的镜像。
## 创建 Java Web 镜像
使用以下命令,根据某个“容器 ID”来创建一个新的“镜像”:
docker commit 57c312bbaad1 huangyong/javaweb:0.1
该容器的 ID 是“57c312bbaad1”,所创建的镜像名是“huangyong/javaweb:0.1”,随后可使用镜像来启动 Java Web 容器。
## 启动 Java Web 容器
有必要首先使用`docker images`命令,查看当前所有的镜像:
REPOSITORY
VIRTUAL SIZE
huangyong/javaweb
fc826a4706af
38 seconds ago
562.8 /docker/centos
7 weeks ago
可见,此时已经看到了最新创建的镜像“huangyong/javaweb:0.1”,其镜像 ID 是“fc826a4706af”。正如上面所描述的那样,我们可以通过“镜像名”或“镜像 ID”来启动容器,与上次启动容器不同的是,我们现在不再进入容器的命令行,而是直接启动容器内部的 Tomcat 服务。此时,需要使用以下命令:
docker run -d -p
--name javaweb huangyong/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`命令来查看当前正在运行的容器。
CONTAINER ID
huangyong/javaweb:0.1
"/root/run.sh"
4 seconds ago
Up 3 seconds
0.0.0.0:5/tcp
在浏览器中,输入以下地址,即可访问 Tomcat 首页:
http://192.168.65.132:58080/
注意:这里使用的是宿主机的 IP 地址,与对外暴露的端口号 58080,它映射容器内部的端口号 8080。
通过本文,我们了解了 Docker 是什么?它与虚拟机的差别在哪里?以及如何安装 Docker?如何下载 Docker 镜像?如何运行 Docker 容器?如何在容器内安装应用程序?如何在容器上创建镜像?如何以服务的方式启动容器?这一切看似简单,但操作也是相当繁琐的,不过熟能生巧,需要我们不断地操练。
除了这种手工生成 Docker 镜像的方式以外,还有一种更像是写代码一样,可以自动地创建 Docker 镜像的方式。只需要我们编写一个 Dockerfile 文件,随后使用`docker build`命令即可完成以上所有的手工操作。
不必过于惊讶,一切尽在不言中……
[1]: http://static.oschina.net/uploads/space/5043_3uki_223750.png
[2]: http://static.oschina.net/uploads/space/0029_lF4d_223750.png
[3]: http://static.oschina.net/uploads/space/2554_x9aG_223750.png
更多开发者职位上
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读}

我要回帖

更多关于 docker java 开发环境 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信