Dokcer入門及其Docker file的製作指令
阿新 • • 發佈:2018-11-05
Docker借鑑了kvm中應用映象的方式,使得Docker的出現方便了容器的實現和使用,從此docker就佔據了容器的市場。
docker:引擎:建立、執行容器,採用C/S架構 客戶端:docker 服務端:dockerd,dockerd負責接收docker客戶端的請求,客戶端傳送指令,dockerd通過映象倉庫,把映象拖到本地,執行執行容器 容器是基於映象啟動的,如果本地沒有映象,dockerd會去遠端拉取映象。 IT行業的部署異構化程度越來越大。不同的開發平臺,不同的執行平臺,各個服務不同的需求環境。此時我們不必再根據不同的底層執行平臺部署不同的執行環境。但是有了docker之後,只需保證能在docker上執行就可以,而不同的環境只要能執行docker就可以。 docker後來把lxc換成了libcontainer。 docker並沒有解決容器之間的編排工具,google的kubernetes解決了這個問題。 容器提供的映象包含了應用的所有依賴項,因而從開發到測試、生產環境中都有可移植性。 容器技術起源於FreeBSD jail,jail 的目的是讓程序在經過修改的 chroot 環境中建立,而不會脫離和影響整個系統 — 在 chroot 環境中,對檔案系統、網路和使用者的訪問都實現了虛擬化。儘管 Jail 在實施方面存在侷限性,但最終人們找到了脫離這種隔離環境的方法。 映象檔案儲存於Registry倉庫中,映象檔案是分層構建的,所以其檔案系統必需為分層檔案系統(aufs,overlafs) docker可以通過一個映象檔案啟動多個容器,映象是隻讀的,每一個容器都在映象上層建立了一層內部可寫的專用層,所有讀寫都僅在自己的專用層上實現。 Registry:一個映象倉庫伺服器,可以通過一個套接字接受映象的搜尋和下載請求。映象儲存於Registry後面的儲存空間中,可以有很多倉庫,每一個倉庫只放一種映象,其中的每一個映象都有其對應的tag(標籤)。Registry對每一個倉庫和映象有一個索引,還有使用者的賬戶密碼,對倉庫進行認證和管理。 每一個容器內可以允許多個程序、執行緒,但docker中每一個容器內部只執行一個程序及其子程序,只要次程序停止,則該容器也停止了。容器內程序執行的日誌被送到控制檯,這樣檢視日誌的時候就不需要進入容器內部,只需在控制檯檢視。容器管理被簡化。 Registry:通過一個httpd伺服器提供服務,https為Registry,http為insecure Registyry Registry可以自定義,也可以使用官方提供的
docker image
採用分層構建機制,最底層為bootfs,其之為rootfs bootfs:用於系統引導的檔案系統,包括BootLoader和kernel,容器啟動完成後會被解除安裝以節約記憶體資源; rootfs:位於bootfs之上,表現為docker容器的根檔案系統; 傳統模式中,系統啟動之時,核心掛載rootf時會首先將其掛載為只讀,完整性自檢完成後將其重新掛載為讀寫 docker中,rootfs由核心掛載為只讀模式,而後通過聯合掛載技術額外掛載一個“可寫”層。 位於下層的映象稱為父映象,最底層的稱為基礎映象 最上層為“可讀寫”層,其下的為“只讀”層 automated builds:docker hub可以根據使用者上傳的指令製作docker映象 webhooks:docker hub可以根據git伺服器上程式碼的變化而自動製作映象
製作映象
製作映象的時候只需要把最上面的可寫層修改後儲存。後續呼叫此映象的時候,分層掛載系統會自動把基礎映象給掛載上去 執行為容器之後因為只有一個程序,所以就不可能通過systemd來管理各個程序了。 docker save httpd:v0.1 centos7:v0.1 /data/centos-httpd.tar 通過docker save把本機的image儲存至一個tar檔案,通過scp等命令把tar檔案傳輸到目標主機上 docker load -i centos-httpd.tar 根據tar檔案解壓映象到本地 docker container commit -a "zhanghw" -c 'CMD ["/bin/sh","-c","/bin/httpd -h var/www/html -f"]' -p b1 tiny-httpd:v5 以正在執行的image為基礎,用命令修改映象啟動後的首個程序。
docker 啟動時顯示:bridge-nf-iptables is disabled 解決方法
vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
讓docker可以自動設定iptables
docker network
三種內建虛擬網路:none,bridge,host
四種網路型別
closed container:沒有外網介面,只要lo網絡卡
bridged container:一個lo網絡卡,一個橋接網絡卡
united container:網絡卡由兩塊網絡卡共用,共用同一個TCP/IP 協議棧
open container:直接使用host的物理網絡卡
docker run --name a1 -it --network none httpd:2.4
--network none 設定其網路為:closed container
--network bridge 設定其網路為:bridged container
--network container:a1 設定其網路為:united container
--network host 設定其網路為:open container
docker -p 釋出服務,暴露服務
把一個容器內的網路暴露到外部,讓外部網路可以訪問容器內的服務
hostIP:hostPort ---> conIP:conPort PNAT機制實現
在建立容器的時候使用-p選項指定
-p conPort 主機埠隨機指派
-p conPort:hostPort 指定主機埠
-p hostIP::conPort 指定主機IP,::之間為主機埠,不指定為隨機獲取
-p hostIP:hostPort:conPort 指定主機的IP和埠
docker port continer 檢視容器暴露埠的情況
docker network create
docker network create -d bridge --gateway 192.168.1.1 --subnet 192.168.1.0/24 vmnet1
docker run --network create container 通過--network指定多個網路時,只有最後一個生效
docker network connect bridge vmnet1 c1 把c1連線至vmnet1
docker network disconnect vmnet1 c1 剝離網路
docker network rm vmnet1 刪除網路
docker inspect host 檢視網路定義
docker network inpect -t
create:根據指定資訊建立網路
docker network create -h 檢視幫助
docker network create -d bridge --gateway 192.168.1.1 --subnet 192.168.1.0/24 vmnet1
docker container run --name a1 --network vmnet1 -it --rm busybox:latest 啟動容器時指定其網路
docker network connect bridge a1 吧container a1 連線到bridge網路上
Data volume
可寫層依存於下一層映象,docker commit 是根據最上層映象的變化來建立映象的,其底層的映象通過聯合掛載技術實現。
Docker映象由多個只讀層疊加而成,啟動容器時,Docker會載入只讀映象層並在映象棧頂部新增一個讀寫層。
寫時複製(cow):如果一個檔案需要修改,則會把在底層中的檔案複製到最上面的可寫層,聯合掛載系統此時會遮蔽最下面只讀層中的檔案,只顯示可寫層中的檔案。
大量業務資料不建議直接儲存在容器映象中:
1.多層映象讀寫效能差。
2.容器一刪除,其儲存的檔案也被刪除
3.磁碟的IO讀寫一直是伺服器整體效能的瓶頸
卷:容器上的一個或多個目錄,此類目錄可繞過聯合檔案系統,與宿主機上的某個目錄關聯。獨立於容器的生命週期實現資料持久化,實現資料和執行程式分離。
•Volume於容器初始化之時即會建立,由base image提供的卷中的資料會於此期間完成複製
• Data volumes can be shared and reused among containers
• Changes to a data volume are made directly
• Changes to a data volume will not be included when you update an image
• Data volumes persist even if the container itself is deleted
•Volume的初衷是獨立於容器的生命週期實現資料持久化,因此刪除容器之時既不會刪除卷,也不會對哪怕未被引用的卷做垃圾回收操作
Docker支援兩種型別的儲存卷
1.動態:container上指定儲存卷,但至於對應的宿主機中的檔案路徑則是docker-daemon隨機產生的,也稱之為docker管理的卷。
2.靜態:container上指定、宿主機上對應的卷也由使用者手動指定。
•為docker run命令使用-v選項即可使用Volume
• Docker-managed volume
• docker run -it -name bbox1 –v /data busybox
• docker inspect -f {{.Mounts}} bbox1
• 檢視bbox1容器的卷、卷識別符號及掛載的主機目錄
• Bind-mount Volume
• docker run -it -v HOSTDIR:VOLUMEDIR --name bbox2 busybox
• docker inspect -f {{.Mounts}} bbox2
docker volume ls 檢視已存在的volume
docker volume inspect filename 檢視卷的詳細資訊
兩個容器共用一個儲存卷,就可以共享資料
•多個容器的卷使用同一個主機目錄,例如
• docker run –it --name c1 -v /docker/volumes/v1:/data busybox
• docker run –it --name c2 -v /docker/volumes/v1:/data busybox
•複製使用其它容器的卷,為docker run命令使用--volumes-from選項
• docker run -it --name bbox1 -v /docker/volumes/v1:/data busybox
• docker run -it --name bbox2 --volumes-from bbox1 busybox
配置容器化應用
• MariaDB:
• 命令列選項:使程式執行特性和程式解耦
• 配置檔案
• 容器化方式執行MariaDB
• 啟動容器
• exec -it
• 配置容器化應用
• docker run
• 通過自定義要執行的命令,並向傳遞命令列引數;
• 自定義映象,將修改好的配置檔案直接焙進映象。不同環境不同的映象
• 環境變數,應用程式支援變數配置,容器啟動時通過載入使用者傳入的變數值,實現同一個映象,不同的執行環境。但傳統意義上的應用大部分都不支援次方法
• docker run -e
• 儲存卷:把配置檔案在本地編輯好,啟動時載入特定的volume
但這些配置方式都需要一個docker額外的平臺,通過這個平臺去管理docker,而不是直接通過docker
容器化時代靜態已不是主流,動態才是,動態化是容器時代的一大特徵。
容器和程序
• 容器:一個程序;
• 程序終止,必將導致容器終止;
• 傳遞終止訊號:SIGTERM,SIGKILL
• 程序沒終止:running
• 健康狀態檢測
• 通過重啟自愈,映象內部應該有自愈機制
配置中心:專門的鍵值儲存系統,Redis、etcd
程式通過watch監測,當配置中心的配置檔案發生變化時從配置中心載入配置,reload配置。此時就可以達到以一應百。
註冊中心,配置中心
Docker file
Dockerfile:Dockerfile is nothing but the source code for building,製作docker映象的指令、原始碼。
• docker build:根據docker file裡的指令根據指定的某一個基礎映象來製作docker image
• Dokcerfile必須放在workdir目錄下,build把workdir作為根,所以所有build用到的檔案必須放在workdir下
• docker build必須基於一個基礎映象製作新的映象,不可能完全製作一個新映象
• 一個docker file中一條指令就一層映象,所以映象層次越少越好
• docker build在製作過程中會基於base image啟動一個容器
• dockerfile所支援的命令和製作環境都是基於基礎映象的,不是基於宿主機的
• 指令全大寫,易於區分引數和指令,第一個指令必須是FROM
• dockerignore file:指定要排除的檔案
dockerfile instruction
FROM:指定docker build的basic image
Syntax
• FROM <repository>[:<tag>] 或
• FROM <resository>@<digest> -->digest:映象的校驗碼,
• <reposotiry>:指定作為base image的名稱;
• <tag>:base image的標籤,為可選項,省略時預設為latest;
MAINTANIER:指定作者資訊(以後會被替代,建議不要用)
• Syntax
• MAINTAINER <authtor's detail>
• <author's detail>可是任何文字資訊,但約定俗成地使用作者名稱及郵件地址
LABEL:指定作者資訊
• Syntax: LABEL <key>=<value> <key>=<value> <key>=<value> ...
COPY:用於Docker主機複製檔案至建立的新映像檔案
• Syntax
• COPY <src> ... <dest> 或
• COPY ["<src>",... "<dest>"] • <src>:要複製的原始檔或目錄,支援使用萬用字元
• <dest>:目標路徑,即正在建立的image的檔案系統路徑;建議為<dest>使用絕對路徑,否則,COPY指定則以WORKDIR為其起始路徑;
• 注意:在路徑中有空白字元時,通常使用第二種格式
•檔案複製準則
• <src>必須是build上下文中的路徑,不能是其父目錄中的檔案
• 如果<src>是目錄,則其內部檔案或子目錄會被遞迴複製,但<src>目錄自身不會被複制
• 如果指定了多個<src>,或在<src>中使用了萬用字元,則<dest>必須是一個目錄,且必須以/結尾
• 如果<dest>事先不存在,它將會被自動建立,這包括其父目錄路徑
ADD
•ADD指令類似於COPY指令,ADD支援使用TAR檔案和URL路徑
• Syntax
• ADD <src> ... <dest> 或
• ADD ["<src>",... "<dest>"]
•操作準則
• 同COPY指令
• 如果<src>為URL且<dest>不以/結尾,則<src>指定的檔案將被下載並直接被建立為<dest>;如果<dest>以/結尾,則檔名URL指定的檔案將被直接下載並儲存為<dest>/<filename>
• 如果<src>是一個本地系統上的壓縮格式的tar檔案,它將被展開為一個目錄,其行為類似於“tar -x”命令;然而,通過URL獲取到的tar檔案將不會自動展開;
• 如果<src>有多個,或其間接或直接使用了萬用字元,則<dest>必須是一個以/結尾的目錄路徑;如果<dest>不以/結尾,則其被視作一個普通檔案,<src>的內容將被直接寫入到<dest>;
WORKDIR
•用於為Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定設定工作目錄
• Syntax
• WORKDIR <dirpath>
• 在Dockerfile檔案中,WORKDIR指令可出現多次,其路徑也可以為相對路徑,不過,其是相對此前一個WORKDIR指令指定的路徑
• 另外,WORKDIR也可呼叫由ENV指定定義的變數
• 例
• WORKDIR /var/log
• WORKDIR $STATEPATH
VOLUME
•用於在image中建立一個掛載點目錄,以掛載Docker host上的卷或其它容器上的卷
• Syntax
• VOLUME <mountpoint> 或
• VOLUME ["<mountpoint>"]
•如果掛載點目錄路徑下此前在檔案存在,docker run命令會在卷掛載完成後將此前的所有檔案複製到新掛載的卷中
EXPOSE
•用於為容器開啟指定要監聽的埠以實現與外部通訊
• Syntax
• EXPOSE <port>[/<protocol>] [<port>[/<protocol>] ...]
• <protocol>用於指定傳輸層協議,可為tcp或udp二者之一,預設為TCP協議
• EXPOSE指令可一次指定多個埠,例如
• EXPOSE 11211/udp 11211/tcp
docker run --name web1 -it --rm -P tinyweb:v0.1 建立容器的時候,需要通過-P選項來暴露EXPOSE指定的埠
ENV
•用於為映象定義所需的環境變數,並可被Dockerfile檔案中位於其後的其它指令如ENV、ADD、COPY等)所呼叫
•呼叫格式為$variable_name或${variable_name}
• Syntax
• ENV <key> <value> 或
• ENV <key>=<value> ...
• 第一種格式中,<key>之後的所有內容均會被視作其<value>的組成部分,因此,一次只能設定一個變數;
• 第二種格式可用一次設定多個變數,每個變數為一個"<key>=<value>"的鍵值對,如果<value>中包含空格,可以以反斜線(\)進行轉義,也可通過對<value>加引號進行標識;另外,反斜線也可用於續行;
• 定義多個變數時,建議使用第二種方式,以便在同一層中完成所有功能
Dockerfile 中指定的變數只能在docker build中使用,docker run指定的變數在docker container中使用。
RUN
•用於指定docker build過程中執行的程式,其可以是任何命令
• Syntax
• RUN <command> 或
• RUN ["<executable>", "<param1>", "<param2>"]
• 第一種格式中,<command>通常是一個shell命令,且以“/bin/sh -c”來執行它,這意味著此程序在容器中的PID不為1,不能接收Unix訊號,因此,當使用docker stop <container>命令停止容器
時,此程序接收不到SIGTERM訊號;
• 第二種語法格式中的引數是一個JSON格式的陣列,其中<executable>為要執行的命令,後面的<paramN>為傳遞給命令的選項或引數;然而,此種格式指定的命令不會以“/bin/sh -c”來發起
,因此常見的shell操作如變數替換以及萬用字元(?,*等)替換將不會進行;不過,如果要執行的命令依賴於此shell特性的話,可以將其替換為類似下面的格式。
• RUN ["/bin/sh", "-c", "<executable>", "<param1>"]
•注意:json陣列中,要使用雙引號
CMD
•類似於RUN指令,CMD指令也可用於執行任何命令或應用程式,不過,二者的執行時間點不同
• RUN指令運行於映像檔案構建過程中,而CMD指令運行於基於Dockerfile構建出的新映像檔案啟動一個容器時
• CMD指令的首要目的在於為啟動的容器指定預設要執行的程式,且其執行結束後,容器也將終止;不過,CMD指定的命令其可以被docker run的命令列選項所覆蓋
• 在Dockerfile中可以存在多個CMD指令,但僅最後一個會生效
• Syntax
• CMD <command> 或 作為shell的子命令執行
• CMD [“<executable>”, “<param1>”, “<param2>”] 或
• CMD ["<param1>","<param2>"]
•前兩種語法格式的意義同RUN
•第三種則用於為ENTRYPOINT指令提供預設引數
ENTRYPOINT
•類似CMD指令的功能,用於為容器指定預設執行程式,從而使得容器像是一個單獨的可執行程式
•與CMD不同的是,由ENTRYPOINT啟動的程式不會被docker run命令列指定的引數所覆蓋,而且,這些命令列引數會被當作引數傳遞給ENTRYPOINT指定指定的程式
• 不過,docker run命令的--entrypoint選項的引數可覆蓋ENTRYPOINT指令指定的程式
• Syntax
• ENTRYPOINT <command>
• ENTRYPOINT ["<executable>", "<param1>", "<param2>"]
• docker run命令傳入的命令引數會覆蓋CMD指令的內容並且附加到ENTRYPOINT命令最後做為其引數使用
• Dockerfile檔案中也可以存在多個ENTRYPOINT指令,但僅有最後一個會生效
如果CMD和ENTRYPOINT同時存在,CMD作為ENTRYPOINT的引數執行。
在docker run時也可以通過docker -e來改變環境變數
USER
•用於指定執行image時的或執行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程式時的使用者名稱或UID
•預設情況下,container的執行身份為root使用者
• Syntax
• USER <UID>|<UserName>
• 需要注意的是,<UID>可以為任意數字,但實踐中其必須為/etc/passwd中某使用者的有效UID,否則,docker run命令將執行失敗
HELTHCHECK
• 檢測容器的健康狀態
HEALTHCHECK [OPTIONS] CMD command (check container health by running a command inside the container)
HEALTHCHECK NONE (disable any healthcheck inherited from the base image)
[options]:
--interval=DURATION (default: 30s) 間隔時長
--timeout=DURATION (default: 30s) 超時時長
--start-period=DURATION (default: 0s) container啟動之後多久開始監測
--retries=N (default: 3) 重試次數
退出碼含意
0: success - the container is healthy and ready for use
1: unhealthy - the container is not working correctly
2: reserved - do not use this exit code
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
如果容器自己沒有健康檢測,則可以在docker run時通過-e 定義
SHELL
改變系統預設的shell程式,因為基礎映象可能是windows。
STOPSIGNAL
指定系統的終止訊號,預設為9
ARG
在build映象的時候,通過 --build-arg 來傳遞引數給ARG定義的變數,而不用事先在Dockerfile中定義好
Syntax:ARG<name>[=<default value>]
ONBUILD
在Dockerfile中定義一個指令,ONBULID後面必須跟一個正常的Dockerfile指令,我們自己build的映象可能被別人作為FROM映象。ONBUILD後面的指令在我們build時不執行,當別人用我們的映象build時ONBUILD才會執行。
所以任何來路不明的映象都不應該被執行。