Docker構(gòu)建Java項(xiàng)目運(yùn)行容器學(xué)習(xí)筆記一

基礎(chǔ)學(xué)習(xí)資料

Docker比較完整和詳細(xì)的指令? https://yeasy.gitbooks.io/docker_practice/network/port_mapping.html

Dockerfile 中的 CMD 與 ENTRYPOINT區(qū)別詳細(xì)說(shuō)明,建議看完通篇文章后再看 https://www.cnblogs.com/sparkdev/p/8461576.html

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

docker的定位,它本質(zhì)上是一個(gè)輕量級(jí)的虛擬機(jī),但是實(shí)際應(yīng)用中說(shuō)是 進(jìn)程的容器工具 更貼切。創(chuàng)建一個(gè)容器當(dāng)做虛擬系統(tǒng)來(lái)使用,然后再里面部署多個(gè)應(yīng)用程序,不是docker推薦的用法。因?yàn)閐ocker的主要優(yōu)點(diǎn)是如下兩點(diǎn)

輕量級(jí)的資源隔離

簡(jiǎn)潔一致的部署環(huán)境

為了盡量發(fā)揮優(yōu)點(diǎn),所以應(yīng)該每個(gè)容器運(yùn)行一個(gè)應(yīng)用,一般是只有一個(gè)進(jìn)程,單一功能。比如證券交易系統(tǒng)有資金、交易、用戶系統(tǒng),各對(duì)應(yīng)一個(gè)項(xiàng)目,應(yīng)該部署到不同的容器。一個(gè)應(yīng)用如果有多個(gè)進(jìn)程,盡量分開(kāi)部署到不同容器實(shí)例。如果應(yīng)用要部署一個(gè)網(wǎng)關(guān)nginx做反向代理,部署到應(yīng)用的容器里還勉強(qiáng)合理。

接著要理解docker的重要概念

鏡像和容器

鏡像和容器的關(guān)系類似于虛擬機(jī)(比如VM或Virtual Box)的系統(tǒng)鏡像和系統(tǒng)實(shí)例,鏡像是容器的構(gòu)建基礎(chǔ),容器是鏡像的實(shí)例?;阽R像建立容器后可以做很多定制化的修改,而且也可以把修改后的容器再保存為新的鏡像。

有兩種方式可以部署一個(gè)有自己的程序的docker容器,首先我們先做一些基礎(chǔ)操作

準(zhǔn)備工作

首先根據(jù)上面的第一個(gè)資料鏈接安裝好docker,這部分不詳述。

然后通過(guò)docker search openjdk指令搜索openjdk的公開(kāi)鏡像,取第一個(gè)star最多的

接著通過(guò) docker pull openjdk:8 將jdk版本為8的openjdk鏡像拉取到本地

通過(guò)指令docker images 可以查看到是否已經(jīng)拉取到鏡像

第一種方法

直接將項(xiàng)目文件放在鏡像里,然后每次構(gòu)建帶有最新項(xiàng)目文件的新的鏡像,并根據(jù)鏡像建立新的容器。

下面通過(guò)Dockerfile構(gòu)建定制鏡像,新建一個(gè)目錄,新建名為Dockerfile的文件,寫(xiě)入定制化配置

示例:

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指的是基于什么鏡像做配置,官方已經(jīng)有很多基礎(chǔ)鏡像,包括redis、mysql、jdk、openjdk,我們基于這些鏡像作進(jìn)一步的定制化即可。

ENV 一行是配置時(shí)區(qū)為上海

Run是在鏡像里執(zhí)行指令,比如一些前置的指令建立文件夾,安裝工具等。比如用RUN apt-get update和RUN apt-get-y install vim可以安裝vim到鏡像里

COPY 是將主機(jī)目錄里的文件復(fù)制到鏡像中

EXPOSE 是聲明鏡像后期需要暴露的端口,僅僅起到聲明作用

WORKDIR 設(shè)定后續(xù)指令工作目錄,因?yàn)殓R像構(gòu)建配置這里的指令都是無(wú)狀態(tài)的,無(wú)法繼承前一條指令的狀態(tài)如執(zhí)行目錄

CMD 設(shè)定啟動(dòng)指令,有兩種方式,shell方式,如CMD top -a ;以及 exec方式,如CMD? ["top”,”-a”] 。兩者區(qū)別是最終在容器執(zhí)行的指令為 /bin/sh -c top -a 和 top -a。其中前者會(huì)導(dǎo)致sh才是容器的1號(hào)進(jìn)程。

然后通過(guò)build指令構(gòu)建鏡像,下面指令最后的點(diǎn)號(hào)是根據(jù)本目錄進(jìn)行構(gòu)建的意思

docker build -t distribute-img .

執(zhí)行后通過(guò)docker images 發(fā)現(xiàn)得到了一個(gè)名為distribute-img的鏡像,如果是執(zhí)行成功,執(zhí)行過(guò)程中會(huì)有一些中間容器生成,并被刪掉,如果完全成功只會(huì)有鏡像不會(huì)有中間容器被留下來(lái)。

通過(guò)鏡像創(chuàng)建并啟動(dòng)容器

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

啟動(dòng)成功后通過(guò)dockercontainer ls -a可以看到一個(gè)容器正在運(yùn)行。這個(gè)容器的IMAGE是distribute-img ,command是 "/bin/sh -c 'java -c…”,STATUS 是 Up xxx seconds,PORTS映射關(guān)系是0.0.0.0:9001->9001/tcp, 0.0.0.0:28080->28080/tcp。注意這個(gè)容器的配置方式會(huì)使得pid1 是sh而不是Java進(jìn)程。

如果修改為如下的寫(xiě)法,pid 1就會(huì)是java進(jìn)程,住下這中用法指令的參數(shù)里不能有 $JAVA_HOME 這種環(huán)境變量,因?yàn)槭菦](méi)辦法識(shí)別的。而且指令參數(shù)要?jiǎng)澐值暮芗?xì),是實(shí)際使用時(shí)如果將”cp部分寫(xiě)成”-cp ./classes:./lib/*:/docker-java-home/lib/tools.jar:./test-classes",進(jìn)程是不能正常起來(lái)的。

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"]

第二種方法(有本地日志以及文件產(chǎn)生的推薦此種方式)

項(xiàng)目文件放在鏡像和容器外。

具體做法是在宿主機(jī)新建一個(gè)目錄,然后用run新建和啟動(dòng)容器時(shí)將這個(gè)目錄掛載為數(shù)據(jù)卷。

首先修改第一種方法中的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

主要是去除了移動(dòng)程序文件進(jìn)入鏡像并解壓的操作

然后通過(guò)build指令構(gòu)建鏡像

docker build -t distribute-img-volume1 .

通過(guò)鏡像創(chuàng)建并啟動(dòng)容器,注意在這個(gè)步驟綁定了外部目錄作為數(shù)據(jù)盤(pán)

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

應(yīng)用就運(yùn)行起來(lái)了,可以通過(guò)docker container ls -a查看

這個(gè)時(shí)候在宿主機(jī)或者容器里操作這個(gè)文件夾,任何變更都可以實(shí)時(shí)雙向體現(xiàn)。

數(shù)據(jù)卷還有一種建立方式,就是先建立一個(gè)獨(dú)立的docker數(shù)據(jù)卷,然后在docker run指令掛載到新建的容器,這種方式比較復(fù)雜,在建立獨(dú)立數(shù)據(jù)卷部分以后再做探討。

上述操作用到的主要指令

搜索公版鏡像,如搜索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

啟動(dòng)已有容器

docker container start CONTAINER_ID

對(duì)于不做修改直接建立容器無(wú)法持續(xù)運(yùn)行的鏡像比如openjdk,可以通過(guò)如下指令建立容器觀察其結(jié)構(gòu),openjdk:8是鏡像的名字版本

docker run -it openjdk:8? /bin/bash

已經(jīng)啟動(dòng)的容器直接進(jìn)入容器的shell

docker exec -it CONTAINER_ID bash

查看數(shù)據(jù)卷列表

docker volume ls

Java程序的資源控制

docker run指令建立啟動(dòng)容器時(shí)可以通過(guò) --cpus 1 -m 1G 控制cpu和內(nèi)存資源,但是容器里的jvm在10之前還是會(huì)只感知到宿主機(jī)的資源限制,所以需要jdk10之前要做一些額外的jvm配置參數(shù)。詳細(xì)資料如下

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

建立獨(dú)立數(shù)據(jù)卷

建立數(shù)據(jù)卷時(shí)用下面的命令構(gòu)建一個(gè)數(shù)據(jù)卷,但這個(gè)指令無(wú)法指定數(shù)據(jù)卷的掛載位置,不太好用。

docker volume create distribute_volume1

用下面的指令查看數(shù)據(jù)卷信息,發(fā)現(xiàn)有個(gè)配置是 "Mountpoint": "/var/lib/docker/volumes/distribute_volume1/_data”,但這個(gè)目錄無(wú)法在宿主機(jī)直接訪問(wèn),不存在,即是數(shù)據(jù)卷掛在到機(jī)器中并且在里面建立了文件還是沒(méi)東西,后面需要進(jìn)一步了解這種用法

docker volume inspect distribute_volume1

總結(jié)

以上是Docker的本地用法,兩種方式里面,如果程序是無(wú)狀態(tài)的,推薦使用第一種方式,每次修改后重新構(gòu)建鏡像發(fā)布;而程序會(huì)產(chǎn)生本地日志和文件的,推薦用第二種方法。Docker的使用對(duì)開(kāi)發(fā)和運(yùn)維人員工作量有一定增加,很多無(wú)docker時(shí)很簡(jiǎn)單的操作會(huì)麻煩很多。它優(yōu)勢(shì)在于大規(guī)模分布式部署和管理應(yīng)用,隔離應(yīng)用并管理資源使用。Docker實(shí)際使用中還需要有一些額外工具的輔助,比如Kubernetes或者Docker Compose等快速分部署的工具,在后續(xù)的文章中再做詳細(xì)介紹。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容