Dokcer入門及其Docker file的制作指令
阿新 • • 發佈:2018-11-05
std 存儲空間 應用程序 man period 數據持久化 adb chroot not work 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才會執行。
所以任何來路不明的鏡像都不應該被運行。
Dokcer入門及其Docker file的制作指令