學(xué)習(xí)Docker 已經(jīng)一周了,大致的學(xué)會(huì)了怎么創(chuàng)建鏡像倍奢、創(chuàng)建容器朴上、運(yùn)行容器等,做個(gè)總結(jié)卒煞。
容器
什么是鏡像痪宰?
在知道什么是容器前,先理解下什么是鏡像。
下面這段是使用翻譯工具從官方文檔翻譯過來的內(nèi)容
映像是一個(gè)只讀模板衣撬,其中包含創(chuàng)建 Docker 容器的說明乖订。通常,一個(gè)圖像基于另一個(gè)圖像具练,并帶有一些額外的自定義乍构。例如,您可以基于該映像構(gòu)建一個(gè)映像ubuntu 扛点,但安裝 Apache Web 服務(wù)器和您的應(yīng)用程序哥遮,以及使您的應(yīng)用程序運(yùn)行所需的配置詳細(xì)信息。
您可以創(chuàng)建自己的圖像占键,也可以只使用其他人創(chuàng)建并在注冊(cè)表中發(fā)布的圖像昔善。要構(gòu)建您自己的鏡像,您需要使用簡單的語法創(chuàng)建一個(gè)Dockerfile 畔乙,用于定義創(chuàng)建和運(yùn)行鏡像所需的步驟。Dockerfile 中的每條指令都會(huì)在映像中創(chuàng)建一個(gè)層翩概。當(dāng)您更改 Dockerfile 并重建映像時(shí)牲距,僅重建那些已更改的層。與其他虛擬化技術(shù)相比钥庇,這是使映像如此輕量牍鞠、小巧和快速的部分原因。
這里面有一段話要記住 “一個(gè)圖像基于另一個(gè)圖像评姨,并帶有一些額外的自定義难述。”, 在后面創(chuàng)建鏡像時(shí)吐句,編寫Dockerfile 文件的第一句話 FROM xxx
就是這個(gè)的解釋胁后。
因?yàn)閯?chuàng)建鏡像時(shí)是要基于另外一個(gè)鏡像來創(chuàng)建的,這里的 xxx 可以是 centos:7 或者其他的自己本機(jī)/docker hub 上存在的鏡像嗦枢。
如果你本機(jī)生沒有這個(gè)鏡像他會(huì)去docker hub 上下載的攀芯。
除了官網(wǎng)的文檔,還查閱了其他博客或者技術(shù)論壇的解釋文虏,有的解釋的比較深入講到了底層實(shí)現(xiàn)侣诺,有的解釋的比較深?yuàn)W吧,作為初學(xué)者的我氧秘,有些詞匯不太理解年鸳。下面是我目前對(duì)鏡像的一個(gè)大致的理解,如果有誤差可以評(píng)論提出來丸相,因?yàn)檫@只是我個(gè)人的理解搔确。
我理解的鏡像按現(xiàn)實(shí)當(dāng)中的比喻,將鏡像比作一個(gè)“模板”。拿簡歷模板來做比喻妥箕,我們從網(wǎng)上下載一個(gè)簡歷模板(從docker hub 上拉去了一個(gè)鏡像) 滥酥,模板的樣式、要填寫的選項(xiàng)(姓名畦幢、聯(lián)系方式坎吻、學(xué)校、項(xiàng)目經(jīng)驗(yàn)...)是固定的宇葱,然后我們基于這個(gè)模板可以增加自己的一些選項(xiàng)比如 “個(gè)人簡介” 或者修改模板的樣式 瘦真,然后作為新的模板再發(fā)布到網(wǎng)上給別人去下載(這個(gè)相當(dāng)于創(chuàng)建了新的鏡像并發(fā)布到Docker hub 上)。這個(gè)過程就是鏡像的制作和發(fā)布
容器是什么黍瞧?
好了诸尽,理解鏡像的概念后可以開始了解容器時(shí)什么了?
下面這段也是使用翻譯工具從官方文檔翻譯過來的內(nèi)容
容器是圖像的可運(yùn)行實(shí)例印颤。您可以使用 Docker API 或 CLI 創(chuàng)建您机、啟動(dòng)、停止年局、移動(dòng)或刪除容器际看。您可以將容器連接到一個(gè)或多個(gè)網(wǎng)絡(luò),將存儲(chǔ)附加到它矢否,甚至可以根據(jù)其當(dāng)前狀態(tài)創(chuàng)建新映像仲闽。
默認(rèn)情況下,一個(gè)容器與其他容器及其主機(jī)的隔離相對(duì)較好僵朗。您可以控制容器的網(wǎng)絡(luò)赖欣、存儲(chǔ)或其他底層子系統(tǒng)與其他容器或主機(jī)的隔離程度。
容器由其映像以及您在創(chuàng)建或啟動(dòng)它時(shí)提供給它的任何配置選項(xiàng)定義验庙。當(dāng)容器被移除時(shí)顶吮,任何未存儲(chǔ)在持久存儲(chǔ)中的狀態(tài)更改都會(huì)消失。
在我剛開始學(xué)習(xí)容器時(shí)看著上面的解釋感覺頭大壶谒,我還不理解鏡像是什么云矫,就直接試圖理解什么是容器,翻閱資料總感覺理解的不到位汗菜。大多數(shù)的解釋是下面幾種:
- 容器是一個(gè)進(jìn)程
- 容器和虛擬機(jī)類似
- 容器是沙箱子
這對(duì)于一個(gè)沒有接觸過容器的小白來說理解起來很痛苦让禀。所以我還是先把這些概念簡單化的理解下(因?yàn)槭莻€(gè)人理解,可能get不到其他人的點(diǎn)):
舉兩個(gè)例子:
- 還是拿簡歷模板來說陨界,模板比作鏡像巡揍,那么使用這個(gè)鏡像的容器 比作是一個(gè)人在做某一件事(相當(dāng)與一個(gè)進(jìn)程)。當(dāng)然不同的模板針對(duì)不同的行業(yè)菌瘪,填寫的內(nèi)容選項(xiàng)也就不同(不同的鏡像腮敌,執(zhí)行的內(nèi)容不同)阱当。當(dāng)人拿到這個(gè)模板后,里面的內(nèi)容選項(xiàng)(姓名糜工、聯(lián)系方式弊添、學(xué)校、項(xiàng)目經(jīng)驗(yàn)...)位置是固定的(相當(dāng)于通過掛載目錄來給這些內(nèi)容留填寫框)捌木,但是這這些位置上的內(nèi)容任你填寫油坝,填寫完成后你再將簡歷發(fā)布到網(wǎng)上(指定好參數(shù),運(yùn)行容器)刨裆,當(dāng)你要修改時(shí)重新再發(fā)布一次就行了(修改掛載目錄下的內(nèi)容重啟容器)澈圈,然后簡歷就制作完成了,之后只需要留意電話或者郵件等待消息(這個(gè)進(jìn)程一直再后臺(tái)運(yùn)行)帆啃。
- 拿平常的后端部署來說瞬女,Java 部署先是打包成jar 包,然后上傳到服務(wù)器上運(yùn)行命令啟動(dòng)服務(wù)努潘。但是運(yùn)行服務(wù)需要JDK诽偷,同時(shí)運(yùn)行這個(gè)服務(wù)還需要mysql 、redis 等一些工具慈俯。這時(shí)你制作了一個(gè)鏡像渤刃,這里面將mysql、redis贴膘、jdk 等都集成了,你只需要把jar 放到指定的掛載目錄下略号,然后運(yùn)行容器時(shí)指定你制作好的鏡像刑峡,項(xiàng)目就部署成功了。同時(shí)因?yàn)槿萜鞯母綦x特性玄柠,當(dāng)你運(yùn)行第二個(gè)項(xiàng)目時(shí)突梦,JDK、Mysql羽利、Redis 版本都不同宫患,只需要制作一個(gè)符合第二個(gè)項(xiàng)目運(yùn)行的鏡像,兩個(gè)項(xiàng)目也能同時(shí)運(yùn)行互不沖突这弧。
最后總結(jié)一下娃闲,我理解的容器和鏡像的關(guān)系一個(gè)是模板提供者,一個(gè)是模板使用這匾浪。
制作第一個(gè)鏡像
好了皇帮,知道容器和鏡像的概念后 開始制作第一個(gè)鏡像。
首相我們要知道蛋辈,制作鏡像的文件叫做 Dockerfile, 這個(gè)文件的編寫就是執(zhí)行 Linux 的命令
以下拿一個(gè)JDK環(huán)境的鏡像做例子属拾。
# 指定該鏡像基于 centos7制作
FROM centos:7
# 作者
MAINTAINER kafeim "373431485@qq.com"
# RUN Linux命令
RUN mkdir /java
# 同RUN一樣作用大致一樣,區(qū)別在于不會(huì)創(chuàng)建 image 新增
CMD echo "創(chuàng)建Java目錄"
# 復(fù)制命令
COPY openjdk-11_28_linux-x64_bin.tar.gz /java
CMD echo "復(fù)制JDK"
RUN cd /java && tar -zxvf openjdk-11_28_linux-x64_bin.tar.gz
CMD echo "解壓jdk"
RUN rm -rf openjdk-11_28_linux-x64_bin.tar.gz
CMD echo "刪除jdk壓縮包"
# ENV 用于設(shè)置環(huán)境變量
ENV JAVA_HOME=/java/jdk-11
ENV CLASSPATH=$:CLASSPATH:$JAVA_HOME/lib/
ENV PATH=$PATH:$JAVA_HOME/bin
CMD echo "設(shè)置jdk環(huán)境變量"
CMD /bin/bash
寫好這個(gè)文件后,運(yùn)行命令制作鏡像
docker build -f dockerfile_11 -t java:11 .
-f 指定要運(yùn)行的Dockerfile文件
-t 鏡像的名稱 這里面 : 冒號(hào)后面跟著的時(shí)標(biāo)簽
最后面的 "." 表示工作目錄渐白。 比如你當(dāng)前所在的目錄是 /home 這個(gè)命令 COPY openjdk-11_28_linux-x64_bin.tar.gz /java
表示將當(dāng)前目錄也就是 /home 這個(gè)目錄下的openjdk-11_28_linux-x64_bin.tar.gz 復(fù)制到容器里面的 /java 目錄下尊浓。 如果將 “.” 改成 “/” 的話 那么里面的命令也要修改 COPY home/openjdk-11_28_linux-x64_bin.tar.gz /java
好了運(yùn)行命令成功后鏡像也就制作完成了,這個(gè)時(shí)候運(yùn)行 docker images
查看當(dāng)前的鏡像
可以看到纯衍,centos:7 的鏡像 docker 幫我們下載到本地 栋齿,java:11 是我們自己制作的鏡像。
Dockerfile命令參考
可以使用Google翻譯來協(xié)助閱讀
運(yùn)行第一個(gè)容器
這里是我運(yùn)行的一個(gè)博客網(wǎng)站做例子托酸。
Dockerfile 文件
FROM java:11
ADD *.jar /root/.halo/
CMD /java/jdk-11/bin/java -server -Xms256m -Xmx256m -jar /root/.halo/application.jar
基于創(chuàng)建的 java:11 的鏡像創(chuàng)建一個(gè)新的鏡像 并且把jar 放到容器里面 /root/.halo/ 目錄下褒颈,然后再啟動(dòng)服務(wù)
創(chuàng)建鏡像:
docker build -f dockerfile_halo -t halo:1 .
運(yùn)行容器:
docker run -it -d --name halo -p 8090:8090 -v $(pwd):/root/.halo --restart=unless-stopped halo:1 /bin/bash
-d
表示以隔離模式啟動(dòng)容器
--name halo
指定容器的名稱
-p 8090:8090
這個(gè)表示將宿主機(jī)的8090端口映射到容器的8090端口
-v $(pwd):/root/.halo
(pwd) 表示的就是 /home 谷丸。 這一段的意思是把 當(dāng)前目錄掛在到容器里面的 /root/.halo 目錄下
--restart=unless-stopped
重啟策略這里指定,在容器非正常退出時(shí)(退出狀態(tài)非0)应结,才會(huì)重啟容器
halo:1
最后的這一段表示指定啟動(dòng)容器的鏡像
/bin/bash
容器啟動(dòng)以后刨疼,內(nèi)部第一個(gè)執(zhí)行的命令。這里是啟動(dòng) Bash鹅龄,保證用戶可以使用 Shell揩慕。有時(shí)候容器一啟動(dòng)就變成了重啟狀態(tài),查資料說是因?yàn)槿萜鞅仨氁\(yùn)行一個(gè)進(jìn)程扮休,避免陷入重啟狀態(tài)這個(gè)還是有必要加的迎卤。
當(dāng)容器啟動(dòng)成功后,后面的部署只需要將掛在目錄下的 application.jar 替換掉 再運(yùn)行重啟容器命令就行了玷坠。
需要注意的時(shí)蜗搔,dockerfile 文件里面的ADD *.jar /root/.halo/
命令 ,如果運(yùn)行啟動(dòng)命令時(shí)掛載了容器里面 “/root/.halo/”目錄,那么需要你自己將 jar 上傳到掛載的目錄里面八堡。如果沒有掛載該目錄樟凄,則會(huì)將鏡像中添加的jar 放到容器里面 “/root/.halo/”目錄下
下面時(shí)常用的命令
查看運(yùn)行的容器:
docker ps
查看所有的容器:
docker ps -a
進(jìn)入容器:
docker exec -it halo /bin/bash
停止容器:
docker stop halo
重啟容器:
docker restart halo
查看日志:
docker logs --tail 200 -f halo
刪除容器(刪除容器前要先停止容器):
docker rm halo
查看鏡像:
docker images
刪除鏡像(刪除鏡像前先刪除使用該鏡像的容器):
docker image rm 鏡像的ID(通過查看鏡像命令查找)
寫文章對(duì)于目前的我來說只是知識(shí)梳理,留下進(jìn)步的腳印兄渺,讓自己能記得更加深刻一點(diǎn)缝龄。
同時(shí)也希望對(duì)其他人有一些幫助,如果里面有什么不對(duì)的歡迎指出來大家可以一起討論挂谍。
博客地址:http://kafeim.cn/