精選!Docker進(jìn)階-Dockerfile建立一個(gè)自定義的鏡像執(zhí)行自定義進(jìn)程
docker對我來說是一個(gè)很方便的工具,,上一篇文章也寫了docker基本的一些使用,這篇文章重點(diǎn)描述一下Dockerfile的使用,從零建立一個(gè)自己定制化的鏡像,并可以執(zhí)行我們需要的任務(wù)。
作者:良知猶存
轉(zhuǎn)載授權(quán)以及圍觀:歡迎關(guān)注微信公眾號:羽林君
(資料圖)
或者添加作者個(gè)人微信:become_me
命令列表
FROM 指定基礎(chǔ)鏡像:所謂定制鏡像,那一定是以一個(gè)鏡像為基礎(chǔ),在其上進(jìn)行定制。就像我們之前運(yùn)行了一個(gè) nginx 鏡像的容器,再進(jìn)行修改一樣,基礎(chǔ)鏡像是必須指定的。而 FROM 就是指定 基礎(chǔ)鏡像,因此一個(gè) Dockerfile 中 FROM 是必備的指令,并且必須是第一條指令
RUN 執(zhí)行命令:RUN 指令是用來執(zhí)行命令行命令的。其格式有兩種:
shell 格式:RUN <命令>,就像直接在命令行中輸入的命令一樣。剛才寫的 Dockerfile 中的 RUN 指令就是這種格式exec 格式:RUN ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"],這更像是函數(shù)調(diào)用中的格式。COPY 指令將從構(gòu)建上下文目錄中 <源路徑> 的文件/目錄復(fù)制到新的一層的鏡像內(nèi)的 <目標(biāo)路徑> 位置
ADD 指令和 COPY 的格式和性質(zhì)基本一致。但是在 COPY 基礎(chǔ)上增加了一些功能。因此在 COPY 和 ADD 指令中選擇的時(shí)候,可以遵循這樣的原則,所有的文件復(fù)制均使用 COPY 指令,僅在需要自動解壓縮的場合使用 ADD。
CMD 指令的格式和 RUN 相似,也是兩種格式:
shell 格式:CMD <命令>
exec 格式:CMD ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"...]
參數(shù)列表格式:CMD ["參數(shù)1", "參數(shù)2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具體的參數(shù)。Docker 不是虛擬機(jī),容器就是進(jìn)程。既然是進(jìn)程,那么在啟動容器的時(shí)候,需要指定所運(yùn)行的程序及參數(shù)。CMD 指令就是用于指定默認(rèn)的容器主進(jìn)程的啟動命令的。
ENTRYPOINT 的格式和 RUN 指令格式一樣,分為 exec 格式和 shell 格式。
LABEL:你可以給鏡像添加標(biāo)簽來幫助組織鏡像、記錄許可信息、輔助自動化構(gòu)建等。每個(gè)標(biāo)簽一行,由 LABEL 開頭加上一個(gè)或多個(gè)標(biāo)簽對。下面的示例展示了各種不同的可能格式。# 開頭的行是注釋內(nèi)容。
EXPOSE:EXPOSE 指令用于指定容器將要監(jiān)聽的端口。因此,你應(yīng)該為你的應(yīng)用程序使用常見的端口。例如,提供 Apache web 服務(wù)的鏡像應(yīng)該使用 EXPOSE 80,而提供 MongoDB 服務(wù)的鏡像使用 EXPOSE 27017。對于外部訪問,用戶可以在執(zhí)行 docker run 時(shí)使用一個(gè)標(biāo)志來指示如何將指定的端口映射到所選擇的端口。
ENV:為了方便新程序運(yùn)行,你可以使用 ENV 來為容器中安裝的程序更新 PATH 環(huán)境變量。例如使用 ENV PATH /usr/local/nginx/bin:$PATH 來確保 CMD ["nginx"] 能正確運(yùn)行。ENV 指令也可用于為你想要容器化的服務(wù)提供必要的環(huán)境變量,比如 Postgres 需要的 PGDATA。最后,ENV 也能用于設(shè)置常見的版本號,比如下面的示例:
VOLUME:VOLUME 指令用于暴露任何數(shù)據(jù)庫存儲文件,配置文件,或容器創(chuàng)建的文件和目錄。強(qiáng)烈建議使用 VOLUME 來管理鏡像中的可變部分和用戶可以改變的部分。
USER:如果某個(gè)服務(wù)不需要特權(quán)執(zhí)行,建議使用 USER 指令切換到非 root 用戶。先在 Dockerfile 中使用類似 RUN groupadd -r postgres && useradd -r -g postgres postgres 的指令創(chuàng)建用戶和用戶組。
WORKDIR:為了清晰性和可靠性,你應(yīng)該總是在 WORKDIR 中使用絕對路徑。另外,你應(yīng)該使用 WORKDIR 來替代類似于 RUN cd ... && do-something 的指令,后者難以閱讀、排錯(cuò)和維護(hù)。
https://yeasy.gitbook.io/docker_practice/appendix/best_practices
命令驗(yàn)證執(zhí)行從docker build 開發(fā)先做個(gè)簡單編譯demo:
FROMubuntu:18.04USERrootCOPYsources.list/etc/apt/sources.list
docker build . 當(dāng)前目錄執(zhí)行可以看到執(zhí)行情況,一共分為三步
每條指令創(chuàng)建一層:
此時(shí)通過docker images就可以看到我們編好的鏡像了,好了正式進(jìn)入正題了。
from命令幫助我們找尋原始鏡像第一行:FROM ubuntu:18.04from本質(zhì)上等效于 docker pull命令,我們可以使用本地鏡像,也可以指定鏡像源,用如下
FROMregistry.hub.docker.com/library/ubuntu:18.04
執(zhí)行效果:
對于國內(nèi)鏡像源大家可以從此文獲?。篽ttps://segmentfault.com/a/1190000023117518
使用RUN命令安裝工具代替我們在容器執(zhí)行命令:RUN apt update不要在腳本中使用apt命令,如果在腳本中使用apt命令,有可能會得到"WARNING: apt does not have a stable CLI interface. Use with caution in scripts." 提示。請使用apt-get、apt-cache等命令進(jìn)行替換。apt命令不適合在腳本中運(yùn)行,因?yàn)閍pt命令是為用戶(人)而設(shè)計(jì)的,它會有顏色的顯示、進(jìn)度條顯示等一些友好的交互界面。而在腳本中,對于這些“特性”是不穩(wěn)定(不支持或者是輸出錯(cuò)亂等)的。
WARNING:aptdoesnothaveastableCLIinterface.Usewithcautioninscripts.
修改為RUN apt-get update
此外我們可以進(jìn)行命令一次執(zhí)行完成
RUNapt-getupdateRUNapt-get--fix-brokeninstallRUNapt-getinstall-ygcc\zip\curl\python\kmod\openssh-server\sudo安裝之后進(jìn)行 設(shè)置一個(gè)賬戶
RUNgroupadd-g1011lynRUNuseradd-d/home/lyn-m-s/bin/bash-u1010-glynlynRUNmkdir-p/home/lyn/work\&&chown-Rlyn:lyn/home/lynRUNecho"lynALL=(ALL)ALL">/etc/sudoersRUNecho"root:root"|chpasswd&&echo"lyn:lyn"|chpassswdWORKDIR/home/lyn/workUSERlynCOPY.bashrc/home/lyn/.bashrc
設(shè)置工具目錄,可以看到進(jìn)去之后工具目錄被設(shè)置為/home/lyn,通過WORKDIR /home/lyn/work執(zhí)行。
使用docker images 看一下打包好的鏡像
看到有個(gè)沒有命名的包,就是我們剛剛編出來的
這個(gè)時(shí)候我們進(jìn)行改個(gè)名字
docker tag IMAGEID(鏡像id) REPOSITORY:TAG(倉庫:標(biāo)簽)
docker tag 025673a91e65 lyn_image:v1
啟動使用 這個(gè)時(shí)候給大家介紹 volume命令
docker使用volume實(shí)現(xiàn)數(shù)據(jù)的持久化,不僅如此volume還能幫助容器和容器之間,容器和host之間共享數(shù)據(jù)。
我們可以使用dockerfile的VOLUME或者 docker run -v參數(shù) ,直接設(shè)置需要掛載的目錄。
在Dockerfile增加 VOLUME /home/lyn/work,開始編譯。
編譯完成后,首先通過docker inspect查看我們編譯好的鏡像信息或者容器信息:
docker inspect 47920709b10c 鏡像id進(jìn)行查看是否設(shè)置掛載目錄
docker inspect f4c2449431c5 啟動之后的容器id
docker volume ls 可以看到當(dāng)前所有的volume
修改映射的文件夾內(nèi)容
sudotouch/var/lib/docker/volumes/567f9c362f6067b3b354bea8b0b370bf304b845ae18e38b125fbdaaface09cfb/_data/lyn.log
可以看到文件已經(jīng)同步過來了
同樣我們也可以使用 docker run -v進(jìn)行控制,首先注釋掉這句VOLUME /home/lyn/work,重新編譯鏡像
docker run -v /home/lyn/docker_share:/home/lyn/work [imageid]-v A:B A是在主機(jī)上的地址,B是在容器中的地址,這兩個(gè)地址如果不存在都會創(chuàng)建,一旦容器運(yùn)行,AB的會完全同步。
具體執(zhí)行為:docker run -it -v /home/lyn/docker_share:/home/lyn/work 208aca0306ab /bin/bash
關(guān)于volume更詳細(xì)的介紹大家可以看此文:https://docs.docker.com/engine/reference/commandline/volume_create/
寫了一個(gè)循環(huán)執(zhí)行的代碼,編譯成固件,用dockerfile 編譯讓鏡像自動執(zhí)行
COPYhello_world/home/lyn/workCMD./hello_world
docker run -it 47920709b10c
最終的Dockerfile文件:
FROMubuntu:18.04USERrootCOPYsources.list/etc/apt/sources.listRUNapt-getupdateRUNapt-getinstall-ygcc\zip\curl\python\kmod\openssh-server\sudoRUNgroupadd-g1011lynRUNuseradd-d/home/lyn-m-s/bin/bash-u1010-glynlynRUNmkdir-p/home/lyn/work\&&chown-Rlyn:lyn/home/lynRUNecho"lynALL=(ALL)ALL">/etc/sudoersRUNecho"root:root"|chpasswd&&echo"lyn:lyn"|chpasswdWORKDIR/home/lyn/workUSERlynCOPY.bashrc/home/lyn/.bashrcVOLUME/home/lyn/workCOPYhello_world/home/lyn/workCMD./hello_world
docker build執(zhí)行的log:因?yàn)橛羞^編譯了,所以這里好多執(zhí)行就是Using cache,很少的打印了
lyn@lyn:~/Documents/lyn_test/docker_build_ubuntu$dockerbuild.SendingbuildcontexttoDockerdaemon28.16kBStep1/16:FROMubuntu:18.04--->71eaf13299f4Step2/16:USERroot--->Usingcache--->d3fe45bd0e46Step3/16:COPYsources.list/etc/apt/sources.list--->Usingcache--->d4f825c3fc77Step4/16:RUNapt-getupdate--->Usingcache--->3863a99d6e2bStep5/16:RUNapt-getinstall-ygcczipcurlpythonkmodopenssh-serversudo--->Usingcache--->9b77c43d6709Step6/16:RUNgroupadd-g1011lyn--->Usingcache--->bbba5f18057aStep7/16:RUNuseradd-d/home/lyn-m-s/bin/bash-u1010-glynlyn--->Usingcache--->47e999f10256Step8/16:RUNmkdir-p/home/lyn/work&&chown-Rlyn:lyn/home/lyn--->Usingcache--->36faf04c6390Step9/16:RUNecho"lynALL=(ALL)ALL">/etc/sudoers--->Usingcache--->0422bf50db6bStep10/16:RUNecho"root:root"|chpasswd&&echo"lyn:lyn"|chpasswd--->Usingcache--->68da5bb15877Step11/16:WORKDIR/home/lyn/work--->Usingcache--->b30d4dcd99f8Step12/16:USERlyn--->Usingcache--->5dfa565d0c6aStep13/16:COPY.bashrc/home/lyn/.bashrc--->Usingcache--->f2b39d61f05bStep14/16:VOLUME/home/lyn/work--->Runningin5482493ab221Removingintermediatecontainer5482493ab221--->0e359e093a4fStep15/16:COPYhello_world/home/lyn/work--->ac326932752cStep16/16:CMD./hello_world--->Runningin430cfd90ad30Removingintermediatecontainer430cfd90ad30--->fc180e4919daSuccessfullybuiltfc180e4919da補(bǔ)充操作:
發(fā)現(xiàn)兩個(gè)鏡像的id相同,如果用docker rmi [鏡像id]它就不知道該如何刪除,我們可以用:
Errorresponsefromdaemon:conflict:unabletodelete71eaf13299f4(mustbeforced)-imageisreferencedinmultiplerepositories
docker rmi 鏡像名:版本號 當(dāng)我建立錯(cuò)誤的鏡像之后,使用rmi進(jìn)行刪除
結(jié)語這就是我自己的一些Dockerfile使用分享。如果大家有更好的想法和需求,也歡迎大家加我好友交流分享哈。
此外對于想要更加細(xì)節(jié)的dockerfile使用可以官網(wǎng)的文章:https://docs.docker.com/engine/reference/builder/https://docs.docker.com/develop/develop-images/dockerfile_best-practices/這篇文章:https://yeasy.gitbook.io/docker_practice/image/build
作者:良知猶存,白天努力工作,晚上原創(chuàng)公號號主。公眾號內(nèi)容除了技術(shù)還有些人生感悟,一個(gè)認(rèn)真輸出內(nèi)容的職場老司機(jī),也是一個(gè)技術(shù)之外豐富生活的人,攝影、音樂 and 籃球。關(guān)注我,與我一起同行。
???????????????? END ????????????????
關(guān)鍵詞: 環(huán)境變量 這個(gè)時(shí)候
相關(guān)閱讀
-
精選!Docker進(jìn)階-Dockerfile建立一個(gè)自...
前言docker對我來說是一個(gè)很方便的工具,,上一篇文章也寫了docker... -
天天熱消息:無限滾動效應(yīng)——設(shè)計(jì)如何...
點(diǎn)擊▲三分設(shè)關(guān)注,和10萬設(shè)計(jì)師一起成長三分設(shè)x翻閱計(jì)劃正文共:99... -
環(huán)球觀速訊丨Python實(shí)現(xiàn)一個(gè)音樂下載器...
Python實(shí)現(xiàn)一個(gè)音樂下載器,不存在充會員的|附源碼前言halo,包子們... -
Python實(shí)現(xiàn)一個(gè)羊人殺小游戲,祝愿看到...
Python實(shí)現(xiàn)一個(gè)羊人殺小游戲,祝愿看到文章的小伙伴都不是小羊人前... -
設(shè)計(jì)技巧 | 利用用戶評價(jià)提升下單轉(zhuǎn)化...
▲點(diǎn)擊 "TCC翻譯情報(bào)局 "關(guān)注,回復(fù) "社群 "加入我們本文共5554... -
工作坊|2023迎接后疫情,社會創(chuàng)新設(shè)計(jì)...
點(diǎn)擊▲三分設(shè)關(guān)注,和10萬設(shè)計(jì)師一起成長設(shè)計(jì)關(guān)懷疫情下的社會創(chuàng)新...