? Docker Data Volume (存儲卷)
Docker鏡像由多個只讀層疊加而成,啟動容器時,Docker會加 載只讀鏡像層并在鏡像棧頂部添加一個讀寫層
如果運行中的容器修改了現有的一個已經存在的文件,那該文 件將會從讀寫層下面的只讀層復制到讀寫層,該文件的只讀版 本仍然存在,只是已經被讀寫層中該文件的副本所隱藏,此即 “寫時復制(COW)”機制
“卷”是容器上的一個或多個“目錄”,此類目錄可繞過聯合文件 系統,與宿主機上的某目錄“綁定(關聯)”
即使將容器刪除,同步到宿主機上的數據也不會消失,保證數據的持久化。
Docker管理卷:
Docker有兩種類型的卷,每種類型都在容器中存在一個掛載點 ,但其在宿主機上的位置有所不同;
1 . Bind mount volume? (將卷綁定到宿主機)
指定容器 上的路徑目錄和宿主機上的目錄:
docker run –name dd1 -it –rm -v /data/b2:/data? busybox (創建一個容器,前面的路徑為宿主機的路徑,后面為容器的路徑;兩個位置的路徑都不需要創建會自動生成的)
docker inspect dd1? :用此命令可以查看容器的詳細信息:(關連路徑的詳細信息)
此時在容器路徑下/data/創建數據,會自動同步到指定的宿主機/data/b2/路徑下的。
如果將原來的容器刪除,再下次創建容器時指定上一次宿主機的路徑,就可以將原來的數據同步到新建的容器上了。容器的路徑可以和原來不同,但宿主機的路徑必須要和你要同步的數據路徑相同
docker run –name dd1 -it –rm -v /data/b2:/app busybox
2 . Docker-managed volume (docker管理卷)
只需要指定容器里的目錄,docker引擎會自動關連到宿主機上對應的路徑位置,可以通過探測容器的詳細信息來查詢。
docker run –name dd1 -it -v /data busybox ?? (只指定容器的路徑)
docker inspect dd1? (查看具體關連到本地的路徑的信息)
此時在容器里/data/下創建數據,會自動同步到宿主機上的路徑下的。
有了脫離容器的持久狀態。
兩個docker容器共享一個卷:也可以多個容器共享。
在同一個宿主機上:
docker run –name dd1 -it –rm -v /data/b2:/data busybox
docker run –name dd2 -it –rm -v /data/b2:/app busybox
創建兩個容器,指定相同的宿主機目錄.本容器的目錄可以各不相同。此時如果在一個容器的/data目錄下創建一個文件,會將數據同步到本地的/data/b2目錄下,也會同步到另一個容器的/app/目錄下。
也可以有另一種思路:
新建一個容器,設置卷關連到宿主機。然后再設定網絡環境。這樣其他容器再啟動時可以使用此容器的卷設置和網絡設置。
做一個基礎的容器,再創建其他容器時,復制此容器的配置。
docker run –name base -it –rm -v /data/b2:/data busybox? (創建基礎容器)
docker run –name nginx –network container:base -it –rm –volumes-from base busybox? (創建一個新的容器,網路是基于base容器的;卷的關連設置也是基于base容器的)
此時查看新創建的nginx容器的網絡設置和卷的設置都是和此前基礎容器base的設置是相同的。
刪除容器之時刪除相關的卷
為docker rm命令使用-v選項 v
刪除指定的卷 docker volume rm
Dockerfile? (制作容器鏡像)
大多數從dockerhub上下載下來的容器鏡像大多都不符合實際需求,許多配置參數都需要修改,比較麻煩,所以需要我們自己來制作符合自己需求的容器鏡像。
上文介紹了以原有容器鏡像為基礎,來修改之后再制作成鏡像的方式,此處采用另一種的制作容器鏡像的方式。
dockerfile的方式是將應用的配置文件做成模板,每次運行一個鏡像容器是,加載設定好的模板配置文件,就可以實現對不同鏡像容器的不同需求了。
工作原理:在開啟一個容器鏡像時,不啟動容器的主進程而是先開啟另一個進程,讀取模板配置文件里的參數,設定好容器主進程的各項環境變量的參數,然后再開啟容器的主進程。不在通過去修改應用程序的配置文件,而是在啟動程序時,給容器的應用傳遞環境變量。(環境變量就存放在dockerfile文件里)
FROM 指令:(指定制作鏡像的基礎鏡像)
FROM指令是最重的一個且必須為Dockerfile文件開篇的第一個非 注釋行,用于為映像文件構建過程指定基準鏡像,后續的指令運 行于此基準鏡像所提供的運行環境。
實踐中,基準鏡像可以是任何可用鏡像文件,默認情況下, docker build會在docker主機上查找指定的鏡像文件,在其不存在 時,則會從Docker Hub Registry上拉取所需的鏡像文件
如果找不到指定的鏡像文件,docker build會返回一個錯誤信息
form 指定鏡像的格式:
FROM <image>[:<tag>] :直接指定鏡像名稱
FROM <image>@<digest> ? :指定鏡像的哈希值;(防止在使用鏡像時, 被人在鏡像里添加危害系統的代碼)
MAINTANIER 指令:(已被廢棄了)新版已經換成了LABEL
用于讓鏡像制作者提供本人的詳細信息
Dockerfile并不限制MAINTAINER指令可在出現的位置,但推薦將 其放置于FROM指令之后
MAINTAINER <authtor’s detail> l <author’s detail>可是任何文本信息,但約定俗成地使用作者名稱及郵件地址? :例如:MAINTAINER? “tom <lv@qq.com>” ? (作者名和郵箱地址)
LABEL:格式是鍵值數據對:?LABEL maintainer= “magedu <mage@magedu.com>”
COPY 指令
用于從Docker宿主機復制文件至創建的新映像文件
Syntax? 格式
COPY <src> … <dest>
COPY [“<src>”,… “<dest>”]? 列表格式:前面多個源文件,后面一個目標文件夾
<src>:要復制的源文件或目錄,支持使用通配符
<dest>:目標路徑,即正在創建的image的文件系統路徑;建議為<dest>使用絕對路 徑,否則,COPY指定則以WORKDIR為其起始路徑;
注意:在路徑中有空白字符時,通常使用第二種格式用引號。
文件復制的規則:
<src>必須是build上下文中的路徑,不能是其父目錄中的文件
如果<src>是目錄,則其內部文件或子目錄會被遞歸復制,但<src>目錄自身 不會被復制。不復制目錄,只是將目錄下的文件復制過去。
如果指定了多個<src>,或在<src>中使用了通配符,則<dest>必須是一個目錄 ,且必須以/結尾
如果<dest>事先不存在,它將會被自動創建,這包括其父目錄路徑
例如:copy index.html /data/web/html/? (僅復制一個文件到要啟動容器的目錄下,容器的目錄如果不存在,系統會默認創建的,index.html文件的路徑在當前目錄下及和dockerfile文件在同一目錄下)
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 指令 ? (指定容器的路徑)
在使用copy和add命令時,用于指定容器的路徑。
用于為Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和 ADD指定設定工作目錄
Syntax ? WORKDIR <dirpath> l 在Dockerfile文件中,WORKDIR指令可出現多次,其路徑也可以為相對路徑,不過 ,其是相對此前一個WORKDIR指令指定的路徑 l 另外,WORKDIR也可調用由ENV指定定義的變量 ? 例如 l WORKDIR /var/log l WORKDIR $STATEPATH
例如:
WORKDIR /usr/local/src ? ? (先指定好容器的路徑)
ADD nginx-1.15.2.tar.gz ./ ? (引用時只寫當前路徑就可以了)
VOLUME指令 (卷的掛載)
用于在image中創建一個掛載點目錄,以掛載Docker host上的卷或 其它容器上的卷
Syntax? 格式
VOLUME <mountpoint>
VOLUME [“<mountpoint>”]
如果掛載點目錄路徑下此前在文件存在,docker run命令會在卷掛 載完成后將此前的所有文件復制到新掛載的卷中
例如:VOLUME /data/mysql ? ? (前面路徑為容器里的路徑,后面宿主機的目錄路徑不指定會自動創建的,也可以自定義的指定)
這樣就實現了將容器里的/data/mysql/? 目錄直接就掛載到了宿主機上了。
EXPOSE 指令? (暴露端口)
用于為容器打開指定要監聽的端口以實現與外部通信;只能指定自己暴露的端口,不能指定自己的IP地址。需要動態綁定到宿主機上的所有地址和隨機端口,因為本機到底是運行在哪個主機上不確定,且宿主機的哪個端口空閑也是不確定的,所以是隨機指定的。
Syntax
EXPOSE <port>[/<protocol>] [<port>[/<protocol>] …]
<protocol>用于指定傳輸層協議,可為tcp或udp二者之一,默認為TCP協議
EXPOSE指令可一次指定多個端口,例如
EXPOSE 11211/udp 11211/tcp
只寫在此文件里,是不會暴露的,只有在docker run 運行時添加-P選項就會讀取此文件里的暴露的配置內容,為了防止安全才這樣做。
ENV指令(定義容器的環境變量)
用于為鏡像定義所需的環境變量,并可被Dockerfile文件中位于其 后的其它指令(如ENV、ADD、COPY等)所調用
調用格式為$variable_name或${variable_name}
dockerfile里的變量:
${variable:-word} 當變量有值時,使用原變量的值,如果沒有給與變量賦值,則使用-號后面的值。
${variable:+word} 和上述變量相反,當變量有值時,使用+后面的值,變量沒有值時,就沒有值了
Syntax? 格式
1 .? ENV <key> <value>
2 .? ENV <key>=<value> …
第一種格式中,<key>之后的所有內容均會被視作其<value>的組成部分 ,因此,一次只能設置一個變量;
第二種格式可用一次設置多個變量,每個變量為一個”<key>=<value>”的 鍵值對,如果<value>中包含空格,可以以反斜線(\)進行轉義,也可通過 對<value>加引號進行標識;另外,反斜線也可用于續行
定義多個變量時,建議使用第二種方式,以便在同一層中完成所有功能
例如:
第一種格式的寫法,一次定義單個變量值
ENV dock_root /data/web/html/
copy index.html $dock-root ?
?copy index.html ${dock-root :-/data/web/html/}? 這種寫法就是當變量值沒有設定的時候,使用后面的字符串作為變量的值。
第二種格式的寫法,一次定義多個變量值。
ENV dock_root=/data/web/html/ \ ?? (反斜線用于換行再寫,如果變量值中間有空白字符需要添加“”)
web=/data/http/dd
RUN指令
用于指定docker build過程中運行的程序,其可以是任何命令,但在基礎鏡像里需要有相對應的命令,否則也無法運行。
Syntax? 格式
1 . RUN <command>
2 . 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/bash”, “-c”, “<executable>”, “<param1>”]
例如:
RUN :mkdir /data/hhhhhh ? (就會在容器的/data目錄下新建一個hhhhhh的目錄)
也可以寫多個命令&&+另一條命令&&+另一條命令,盡量寫在一行,因為寫了多行會造成容器封層數的增加。
格式:
RUN :command1&&\
command 2 && \ ?? (反斜線為續行在寫)
command 3
CMD指令(定義鏡像文件啟動為容器時, 將定義的程序運行為容器的主程序;如果此程序結束容器也會跟隨者結束)
類似于RUN指令,CMD指令也可用于運行任何命令或應用程序, 不過,二者的運行時間點不同
RUN指令運行于映像文件構建過程中,而CMD指令運行于基于Dockerfile 構建出的新映像文件啟動一個容器時
CMD指令的首要目的在于為啟動的容器指定默認要運行的程序,且其運 行結束后,容器也將終止;不過,CMD指定的命令其可以被docker run創建容器時后面添加的命令所覆蓋掉,而不去運行dockerfile文件里定義的命令,至運行docker run 后面的命令+/bin/sh/ls /etc/? 等命令。
在Dockerfile中可以存在多個CMD指令,但僅最后一個會生效
Syntax
CMD <command>
CMD [“<executable>”, “<param1>”, “<param2>”]
CMD [“<param1>”,”<param2>”]
前兩種語法格式的意義同RUN
第三種則用于為ENTRYPOINT指令提供默認參數
CMD httpd -h /data/web/html? (在dockerfile文件里添加的)如果將此命令添加到以busybox的鏡像里,運行時,原來默認是運行的主程序/bin/sh的,添加CMD后主程序變為httpd程序了。
第三種格式的寫法:將自己定義的內容當參數傳遞給ENTRYPOINT的:例如:
CMD [“/bin/httpd”,”-f”,”-h /data/web/html”]
ENTROPIONT /bin/sh -c ? ? (添加-c則指定從字符串獲取參數,及允許獲得CMD傳送過來的參數)
ENTRYPOINT指令:
類似CMD指令的功能,用于為容器指定默認運行程序,從而使得 容器像是一個單獨的可執行程序
與CMD不同的是,由ENTRYPOINT啟動的程序不會被docker run命 令行指定的參數所覆蓋,而且,這些命令行參數會被當作參數傳 遞給ENTRYPOINT指定指定的程序
不過,docker run命令的–entrypoint選項的參數可覆蓋ENTRYPOINT指令 指定的程序
Syntax 格式
ENTRYPOINT <command>
ENTRYPOINT [“<executable>”, “<param1>”, “<param2>”]
docker run命令傳入的命令參數會覆蓋CMD指令的內容并且附加到 ENTRYPOINT命令最后做為其參數使用
Dockerfile文件中也可以存在多個ENTRYPOINT指令,但僅有最后 一個會生效
例如:
ENTRYPOINT /bin/httpd -f -h /data/web/html/ 在dockerfile文件里指定要運行的命令,且默認為主進程,在運行dockerfile容器時,docker run –name kkk -it –rm httpd:2.1 ls /data/web/html/ 其他的功能和CMD指令相同,會把其指令后面的程序運行為主程序,但和CMD不同的時在命令行運行容器時添加的命令不會運行的。而CMD會運行并將其自己指定的命令覆蓋掉。
USER 指令:
用于指定運行image時的或運行Dockerfile中任何RUN、CMD或 ENTRYPOINT指令指定的程序時的用戶名或UID
默認情況下,container的運行身份為root用戶
Syntax 格式
USER <UID>|<UserName>
需要注意的是,<UID>可以為任意數字,但實踐中其必須為/etc/passwd中 某用戶的有效UID,否則,docker run命令將運行失敗
ONBUILD 指令:
用于在Dockerfile中定義一個觸發器
Dockerfile用于build映像文件,此映像文件亦可作為base image被 另一個Dockerfile用作FROM指令的參數,并以之構建新的映像文 件
在后面的這個Dockerfile中的FROM指令在build過程中被執行時, 將會“觸發”創建其base image的Dockerfile文件中的ONBUILD指令 定義的觸發器
Syntax 格式:
ONBUILD <INSTRUCTION>
盡管任何指令都可注冊成為觸發器指令,但ONBUILD不能自我嵌套,且不會觸 發FROM和MAINTAINER指令
使用包含ONBUILD指令的Dockerfile構建的鏡像應該使用特殊的標簽,例如 ruby:2.0-onbuild
在ONBUILD指令中使用ADD或COPY指令應該格外小心,因為新構建過程的上 下文在缺少指定的源文件時會失敗
創建鏡像的示例1:(copy命令復制單個文件到容器目錄下)
mkdir imge1 (創建一個文件夾)
cd imge1/ ?? (進入到此文件夾下)
vim Dockerfile? (創建一個dockerfie文件,注意創建的文件開頭字母要大寫)
#Description test image? (描述信息)
FROM busybox:latest ? ?? (基于什么鏡像來制作)
MAINTAINER “magedu <mage@magedu.com>” ? (指定鏡像制作的人的信息)
#LABEL maintainer= “magedu <mage@magedu.com>” ? (新的指令用法)
copy index.html /data/web/html/ ?? (需要在imge1目錄下創建一個index.html文件)
vim index.html
hello
保存退出。
docker build -t httpd:1.1 imge1/? (制作鏡像)
(httpd為自定義的倉庫名;1.1為標簽版本號;imge1/:為dockerfile文件的父目錄。)
docker image ls? (查看本地鏡像已經生成新的鏡像文件了)
基于上面制作的鏡像文件來開啟一個容器:
docker run –name hhh -it –rm httpd:1.1 ? (交互式的方式登陸進去查看dockerfile里復制到容器里的文件是否復制過去了)。
創建鏡像示例2:(copy命令復制目錄下的多個文件到容器目錄里)
首先復制一個目錄到img1下:
cp -r /etc/yum.repos.d? /img1/
修改dockerfile文件:
其中yum.repos.d為目錄。復制過去不復制目錄,只復制目錄下的文件,另外dockerfile文件里命令如果能寫一行不要分兩行來寫,因為每一行都在運行容器時都是一層封裝。
docker build -t httpd:1.2 /root/imge1/? (再次制作鏡像)
docker run –name hhh -it –rm httpd:1.2? (以第二版本的鏡像開啟一個容器,查看是否將目錄下的文件復制過去)
創建鏡像示例3:(add命令下載網絡上tar格式的文件。和下載本地的tar格式的文件)
首先找一個網絡上的tar格式的包,復制其url的路徑。
http://nginx.org/download/nginx-1.12.2.tar.gz
編輯dockerfile文件:/roo/imge1/
docker build -t httpd:1.3 /root/imge1/? (再次制作鏡像文件)
docker run –name kkk -it –rm httpd:1.3? (以此次的鏡像文件運行一個docker容器,來驗證是否將文件下載下來)
網絡上的url路徑下載的tar格式的包不會自動將其解壓所。
但如果將tar格式的包下載到宿主機上的目錄下,使用add命令,會將其自動的解壓縮。
wget http://nginx.org/download/nginx-1.15.2.tar.gz? 先將文件下載到本地/root/imge1/下
編輯dockerfile文件:
docker build -t httpd:1.4 /root/imge1/? (創建一個新的鏡像文件)
docker run –name kkk -it –rm httpd:1.4? (以此鏡像運行一個容器)
進入到容器后發現,此包已經下載下來并解壓縮了。
創建鏡像示例4:(workdir指令的用法)
dockerfile文件的內容:
創建鏡像和運行此鏡象的容器來驗證參考上面的操作就可以了。
當有多個workdir路徑時,從下向上找,離自己最近的workdir為自己引用的路徑。
創建鏡像示例5:(volume的掛載)
不指定宿主機的路徑只指定容器的路徑的掛載
編輯/root/imge1/下的dockerfile文件:
docker build -t httpd:1.5 /root/imge1/(制作鏡像)
docker run –name kkk -it –rm httpd:1.5? (啟動容器)
docker inspect kkk? (查看容器的詳細信息,容器里的目錄是否掛載到宿主機上了)
創建鏡像示例6:(expose暴露端口號)
編輯/root/imge1/下的dockerfile文件:
docker build -t httpd:1.6 /root/imge1/? (再次制作鏡像)
docker run –name kkk -it -P? –rm httpd:1.6? (以此鏡像運行一個容器)
在容器里操作
httpd -h /data/web/html? (啟動http程序并指定主頁面的路徑)
netstat -nlt ? (查看端口號是否打開)
ifconfig ? (查看容器的IP地址)
最后在宿主機上curl 容器的IP地址應該可以訪問容器提供的http的web服務。
docker port kkk (查看端口號是否暴露了,和查看關連到宿主機的哪個端口)
在瀏覽器上打開L:? 宿主機IP:端口號
創建鏡像示例7:(ENV環境變量)
編輯/root/imge1/下的dockerfile文件:
docker build -t httpd:1.7 /root/imge1/ (再次制作鏡像)
docker run –name kkk -it -P –rm httpd:1.7 (以此鏡像運行一個容器)
進入容器后查看是否完成。
docker run –name kkk -it -P –rm httpd:1.7 printenv (查看環境變量信息)
docker run –name kkk -it -P -e web=”nginx-1.15.1.tar.gz” –rm httpd:1.7? (也可以在build時重新來定義其變量的值)
創建鏡像示例8: (run指令;前提是基礎容器里有此命令)
編輯/root/imge1/下的dockerfile文件:
docker build -t httpd:1.8 /root/imge1/? (再次制作鏡像)
docker run –name kkk -it -P –rm httpd:1.8? (基于此鏡像開啟容器)
查看容器驗證run命令是否執行成功。
創建鏡像示例8:( ENTRYPOINT指令)
編輯/root/imge1/下的dockerfile文件:
docker build -t httpd:2.1 /root/imge1/? (再次制作新的鏡像)
docker run –name kkk -it –rm httpd:2.1? (以此鏡像為基礎開啟一個新的容器;默認就會運行httpd的程序,而不是原本busybox的/bin/sh的程序了)
docker run –name kkk -it –rm httpd:2.1 ls /data/web/html/? (但是和CMD不同的是 ,命令行后面的 命令與不會運行,而CMD定義的主程序,如果命令行也有命令,則運行命令行上的命令)
如果一定要想運行自己的命令:需要指定專門的選項:
docker run –name kkk -it –rm –entrypoint “ls /data/web/html” httpd:2.1? (這樣寫就能將定義的entrypoint的命令覆蓋掉)。
CMD [“/usr/sbin/nginx”,”-g”,”daemon off;”] ? (daemon off:運行為前端,在dockerfile文件里)
/usr/sbin/nginx -g “daemon off;” ? 在命令行里
創建鏡像示例8:(使用entrypoint來傳遞變量的參數)
mkdir /root/img3 ? (創建一個文件夾)
vim /root/img3/Dockerfile ? (創建dockerfile的配置文件)
vim entrypoint.sh? (編寫一個腳本)
添加腳本的執行權限。
docker build -t nginx:2.3 /root/img3/? (創建新的鏡像)
docker run –name kk –rm nginx:2.3? (以此鏡像為基礎開啟一個容器)
本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/104466