Docker构建Java项目运行容器学习笔记一

基础学习资料

Docker比较完整和详细的指令  https://yeasy.gitbooks.io/docker_practice/network/port_mapping.html

Dockerfile 中的 CMD 与 ENTRYPOINT区别详细说明,建议看完通篇文章后再看 https://www.cnblogs.com/sparkdev/p/8461576.html

官方文档https://docs.docker.com/engine/reference/builder/

docker的定位,它本质上是一个轻量级的虚拟机,但是实际应用中说是 进程的容器工具 更贴切。创建一个容器当做虚拟系统来使用,然后再里面部署多个应用程序,不是docker推荐的用法。因为docker的主要优点是如下两点

轻量级的资源隔离

简洁一致的部署环境

为了尽量发挥优点,所以应该每个容器运行一个应用,一般是只有一个进程,单一功能。比如证券交易系统有资金、交易、用户系统,各对应一个项目,应该部署到不同的容器。一个应用如果有多个进程,尽量分开部署到不同容器实例。如果应用要部署一个网关nginx做反向代理,部署到应用的容器里还勉强合理。

接着要理解docker的重要概念

镜像和容器

镜像和容器的关系类似于虚拟机(比如VM或Virtual Box)的系统镜像和系统实例,镜像是容器的构建基础,容器是镜像的实例。基于镜像建立容器后可以做很多定制化的修改,而且也可以把修改后的容器再保存为新的镜像。

有两种方式可以部署一个有自己的程序的docker容器,首先我们先做一些基础操作

准备工作

首先根据上面的第一个资料链接安装好docker,这部分不详述。

然后通过docker search openjdk指令搜索openjdk的公开镜像,取第一个star最多的

接着通过 docker pull openjdk:8 将jdk版本为8的openjdk镜像拉取到本地

通过指令docker images 可以查看到是否已经拉取到镜像

第一种方法

直接将项目文件放在镜像里,然后每次构建带有最新项目文件的新的镜像,并根据镜像建立新的容器。

下面通过Dockerfile构建定制镜像,新建一个目录,新建名为Dockerfile的文件,写入定制化配置

示例:

FROM openjdk:8

ENV TZ=Asia/Shanghai

COPY distribute-all.zip /home/

RUN cd /home/ && unzip distribute-all.zip

EXPOSE 28080 9001

WORKDIR /home/distribute/

CMD java -cp ./classes:./lib/*:$JAVA_HOME/lib/tools.jar:./test-classes com.dd.http.server.WebServer --config config-test.json --env test distribute > /dev/null 2>&1

FROM指的是基于什么镜像做配置,官方已经有很多基础镜像,包括redis、mysql、jdk、openjdk,我们基于这些镜像作进一步的定制化即可。

ENV 一行是配置时区为上海

Run是在镜像里执行指令,比如一些前置的指令建立文件夹,安装工具等。比如用RUN apt-get update和RUN apt-get-y install vim可以安装vim到镜像里

COPY 是将主机目录里的文件复制到镜像中

EXPOSE 是声明镜像后期需要暴露的端口,仅仅起到声明作用

WORKDIR 设定后续指令工作目录,因为镜像构建配置这里的指令都是无状态的,无法继承前一条指令的状态如执行目录

CMD 设定启动指令,有两种方式,shell方式,如CMD top -a ;以及 exec方式,如CMD  ["top”,”-a”] 。两者区别是最终在容器执行的指令为 /bin/sh -c top -a 和 top -a。其中前者会导致sh才是容器的1号进程。

然后通过build指令构建镜像,下面指令最后的点号是根据本目录进行构建的意思

docker build -t distribute-img .

执行后通过docker images 发现得到了一个名为distribute-img的镜像,如果是执行成功,执行过程中会有一些中间容器生成,并被删掉,如果完全成功只会有镜像不会有中间容器被留下来。

通过镜像创建并启动容器

docker run -d -p 28080:28080 -p 9001:9001 distribute-img

启动成功后通过dockercontainer ls -a可以看到一个容器正在运行。这个容器的IMAGE是distribute-img ,command是 "/bin/sh -c 'java -c…”,STATUS 是 Up xxx seconds,PORTS映射关系是0.0.0.0:9001->9001/tcp, 0.0.0.0:28080->28080/tcp。注意这个容器的配置方式会使得pid1 是sh而不是Java进程。

如果修改为如下的写法,pid 1就会是java进程,住下这中用法指令的参数里不能有 $JAVA_HOME 这种环境变量,因为是没办法识别的。而且指令参数要划分的很细,是实际使用时如果将”cp部分写成”-cp ./classes:./lib/*:/docker-java-home/lib/tools.jar:./test-classes",进程是不能正常起来的。

CMD ["java","-cp","./classes:./lib/*:/docker-java-home/lib/tools.jar:./test-classes","com.dd.http.server.WebServer","--config","config-test.json","--env","test","distribute","> /dev/null","2>&1"]

第二种方法(有本地日志以及文件产生的推荐此种方式)

项目文件放在镜像和容器外。

具体做法是在宿主机新建一个目录,然后用run新建和启动容器时将这个目录挂载为数据卷。

首先修改第一种方法中的Dockerfile改为如下

FROM openjdk:8

ENV TZ=Asia/Shanghai

EXPOSE 28080 9001

WORKDIR /home/volume/distribute/

CMD java -cp ./classes:./lib/*:$JAVA_HOME/lib/tools.jar:./test-classes com.dd.http.server.WebServer --config config-test.json --env test distribute > /dev/null 2>&1

主要是去除了移动程序文件进入镜像并解压的操作

然后通过build指令构建镜像

docker build -t distribute-img-volume1 .

通过镜像创建并启动容器,注意在这个步骤绑定了外部目录作为数据盘

docker run -d -p 28080:28080 -p 9001:9001  --mount type=bind,source=/Users/workandstudy/14_docker/01_distribute_volume1/volume,target=/home/volume distribute-img-volume1

应用就运行起来了,可以通过docker container ls -a查看

这个时候在宿主机或者容器里操作这个文件夹,任何变更都可以实时双向体现。

数据卷还有一种建立方式,就是先建立一个独立的docker数据卷,然后在docker run指令挂载到新建的容器,这种方式比较复杂,在建立独立数据卷部分以后再做探讨。

上述操作用到的主要指令

搜索公版镜像,如搜索openjdk的公版镜像

docker search openjdk

查看容器列表

docker container ls -a

查看容器的操作日志

docker logs -t --since="2018-02-08T13:23:37" --until "2018-02-09T12:23:37” CONTAINER_ID

docker logs -t --since="2018-02-08T13:23:37" CONTAINER_ID

启动已有容器

docker container start CONTAINER_ID

对于不做修改直接建立容器无法持续运行的镜像比如openjdk,可以通过如下指令建立容器观察其结构,openjdk:8是镜像的名字版本

docker run -it openjdk:8  /bin/bash

已经启动的容器直接进入容器的shell

docker exec -it CONTAINER_ID bash

查看数据卷列表

docker volume ls

Java程序的资源控制

docker run指令建立启动容器时可以通过 --cpus 1 -m 1G 控制cpu和内存资源,但是容器里的jvm在10之前还是会只感知到宿主机的资源限制,所以需要jdk10之前要做一些额外的jvm配置参数。详细资料如下

http://www.concurrent.work/docker/java/jvm/gc/pitfalls-about-running-java-inside-container/

建立独立数据卷

建立数据卷时用下面的命令构建一个数据卷,但这个指令无法指定数据卷的挂载位置,不太好用。

docker volume create distribute_volume1

用下面的指令查看数据卷信息,发现有个配置是 "Mountpoint": "/var/lib/docker/volumes/distribute_volume1/_data”,但这个目录无法在宿主机直接访问,不存在,即是数据卷挂在到机器中并且在里面建立了文件还是没东西,后面需要进一步了解这种用法

docker volume inspect distribute_volume1

总结

以上是Docker的本地用法,两种方式里面,如果程序是无状态的,推荐使用第一种方式,每次修改后重新构建镜像发布;而程序会产生本地日志和文件的,推荐用第二种方法。Docker的使用对开发和运维人员工作量有一定增加,很多无docker时很简单的操作会麻烦很多。它优势在于大规模分布式部署和管理应用,隔离应用并管理资源使用。Docker实际使用中还需要有一些额外工具的辅助,比如Kubernetes或者Docker Compose等快速分部署的工具,在后续的文章中再做详细介绍。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容