前一章節,介紹了
Docker
經常使用的命令。在基本使用上,熟悉這些經常使用的命令基本上就夠了。但在一些場景下,好比在部署SpringBoot
應用時,一般咱們都是打成Jar
包,而後利用java
命令進行運行jar包。這個時候咱們就能經過編寫Dockerfile
進行自動化部署了(可能這個比喻不太恰當⊙﹏⊙‖∣)。整體來講,可利用Dockerfile
文件自定義鏡像內容,改變原始鏡像的一些行爲,以知足個性化需求。html
Dockerfile是一個文本文件,裏面包含了若干條指令,每條指令描述了構建鏡像的細節。簡單來講,它就是由一系列指令和參數構成的腳本文件,從而構建出一個新的鏡像文件。java
簡單來講,Dockerfile
格式通常以下:linux
# 註釋 指令 [參數]
這裏以一個修改Nginx
鏡像首頁爲示例(此鏡像使用說明詳見:https://hub.docker.com/_/nginx/),簡單說明:nginx
# 注意:非註釋第一行 必須以FROM 開頭。 # FROM 指定基礎鏡像,即以此鏡像做爲基礎 FROM nginx # 設置元數據,利用 docker inspect [鏡像名稱|鏡像ID],便可查看。 LABEL author="做者:oKong" LABEL version="版本:v0.1" LABEL desc="說明:修改nginx首頁提示" # 操做執行,這裏直接修改了nginx的html的首頁內容,/usr/share/nginx/html # 本來想輸出中文,亂碼了,設置了 ENV LANG C.UTF-8 或者 ENV LANG zh_CN.UTF-8 都不行 放棄了,有知道大神望告知! RUN echo 'hello,oKong' > /usr/share/nginx/html/index.html # 啓動命令 不寫時 會直接使用基礎鏡像的啓動命令 CMD ["nginx", "-g", "daemon off;"]
而後利用build
命令進行關鍵。docker
docker build -t lqdev.cn/mynginx:v1 .
注意:這裏最後面有個(.)
,路徑參數,而(.)
表示是當前路徑。shell
控制檯會顯示具體每個執行說明windows
[root@izbp16chpwsnff41nrjtfhz docker]# docker build -t lqdev.cn/mynginx:v1 . Sending build context to Docker daemon 2.56kB Step 1/6 : FROM nginx ---> c82521676580 Step 2/6 : LABEL author="做者:oKong" ---> Running in 81eb0dc40699 Removing intermediate container 81eb0dc40699 ---> 4d2799492a09 Step 3/6 : LABEL version="版本:v0.1" ---> Running in e4e0d6097bae Removing intermediate container e4e0d6097bae ---> d47eb89ae7b4 Step 4/6 : LABEL desc="說明:修改nginx首頁提示" ---> Running in 36b1bffc8345 Removing intermediate container 36b1bffc8345 ---> 3e9b63e69b0a Step 5/6 : RUN echo 'hello,oKong' > /usr/share/nginx/html/index.html ---> Running in 1f04dafc3bf6 Removing intermediate container 1f04dafc3bf6 ---> c9a649422c1d Step 6/6 : CMD ["nginx", "-g", "daemon off;"] ---> Running in f6f41f072643 Removing intermediate container f6f41f072643 ---> 11e7ca53febd Successfully built 11e7ca53febd Successfully tagged lqdev.cn/mynginx:v1
查看鏡像列表,就能看見剛剛構建的鏡像了:bash
[root@izbp16chpwsnff41nrjtfhz docker]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE lqdev.cn/mynginx v1 11e7ca53febd About a minute ago 109MB nginx latest c82521676580 7 days ago 109MB lqdev.cn/hello-world 1 2cb0d9787c4d 3 weeks ago 1.85kB hello-world latest 2cb0d9787c4d 3 weeks ago 1.85kB
而後,咱們運行下:函數
docker run -p 80:80 -d lqdev.cn/mynginx:v1
以後訪問宿主服務地址:http://宿主IP, 便可看見修改後的首頁了:學習
同時,利用inspect
命令,查看鏡像元數據,就能夠看見剛剛指定的值了。
docker inspect 11e7ca53febd
因此能夠看出Dockerfile主要分爲四個部分
基礎鏡像信息
、元數據信息
、鏡像操做指令
、啓動執行指令
。下一部分就主要講解下關於Dockerfile
的命令說明。
放在第一行,其格式爲:
#語法: FROM <image> FROM <image>:<tag> FROM <image>:<digest>
若想構建一個最小的鏡像,不想基於其餘任何鏡像時。可直接
FROM scratch
能夠設置鏡像的任何元數據,格式爲:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
例如:
LABEL author="做者:oKong" LABEL version="版本:v0.1" LABEL desc="說明:修改nginx首頁提示"
而後利用docker inspect
命令進行查看。
"Labels": { "author": "做者:oKong", "desc": "說明:修改nginx首頁提示", "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>", "version": "版本:v0.1" },
主要就是設置環境變量,以後的命令均可以用此變量進行賦值,格式以下:
ENV <key> <value> ENV <key>=<value> ...
VOLUME用於建立掛載點,即向基於所構建鏡像創始的容器添加捲:
VOLUME ["/data"]
一個卷能夠存在於一個或多個容器的指定目錄,該目錄能夠繞過聯合文件系統,並具備如下功能:
VOLUME
讓咱們能夠將源代碼、數據或其它內容添加到鏡像中,而又不併提交到鏡像中,並使咱們能夠多個容器間共享這些內容。
主要就是構建鏡像時,進行拷貝文件到鏡像的指定路徑下,格式爲:
COPY <源路徑>... <目標路徑> COPY ["<源路徑1>",... "<目標路徑>"]
ADD
指令和 COPY
的格式和性質基本一致。可是在 COPY
基礎上增長了一些功能。好比<源路徑>
能夠是一個 URL
,這種狀況下,Docker
引擎會試圖去下載這個連接的文件放到<目標路徑>
去。
爲鏡像設置監聽端口,容器運行時會監聽改端口,格式爲:
EXPOSE <port> [<port>/<protocol>...]
如,nginx
鏡像,監聽了80端口
EXPOSE 80
同時,也能指定協議名,如:
EXPOSE 80/udp
該命令用於設置構建參數,該參數在容器運行時是獲取不到的,只有在構建時才能獲取。這也是其和ENV
的區別。
ARG <name>[=<default value>]
使用舉例:
arg author=okong # 構建時,也能夠替換了 # docker build --build-arg <varname>=<value> docker build --build-arg author=okong0123
在鏡像的構建過程當中執行特定的命令,並生成一箇中間鏡像。格式:
RUN <command> 或者 RUN ["executable", "param1", "param2"]
這也是很經常使用的一個功能了。 第一種後邊直接跟shell命令
第二種是相似於函數調用。
可將executable
理解成爲可執行文件,後面就是兩個參數。
兩種寫法比對:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME RUN ["/bin/bash", "-c", "echo hello"]
注意:多行命令不要寫多個RUN
,緣由是Dockerfile
中每個指令都會創建一層.多少個RUN就構建了多少層鏡像,會形成鏡像的臃腫、多層,不只僅增長了構件部署的時間,還容易出錯。
RUN
書寫時的換行符是\
功能爲容器啓動時要運行的命令, 語法有三種寫法
1. CMD ["executable","param1","param2"] 2. CMD ["param1","param2"] 3. CMD command param1 param2
第三種比較好理解了,就時shell
這種執行方式和寫法,第一種和第二種其實都是可執行文件加上參數的形式: 舉例說明兩種寫法:
CMD [ "sh", "-c", "echo $HOME" CMD [ "echo", "$HOME" ]
補充細節:這裏邊包括參數的必定要用雙引號,就是雙引號"
,不能是單引號。千萬不能寫成單引號
。緣由是參數傳遞後,docker
解析的是一個JSON array
。
ENTRYPOINT
用於給容器配置一個可執行程序。也就是說,每次使用鏡像建立容器時,經過 ENTRYPOINT
指定的程序都會被設置爲默認程序。ENTRYPOINT
有如下兩種形式:
ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2
ENTRYPOINT
與 CMD
很是相似,不一樣的是經過docker run
執行的命令不會覆蓋 ENTRYPOINT
,而docker run
命令中指定的任何參數,都會被當作參數再次傳遞給ENTRYPOINT
。Dockerfile
中只容許有一個 ENTRYPOINT
命令,多指定時會覆蓋前面的設置,而只執行最後的 ENTRYPOINT
指令。 docker run
運行容器時指定的參數都會被傳遞給ENTRYPOINT
,且會覆蓋 CMD 命令指定的參數。如,執行docker run <image> -d
時,-d
參數將被傳遞給入口點。 也能夠通過docker run --entrypoint
重寫 ENTRYPOINT
入口點。如:能夠像下面這樣指定一個容器執行程序:
ENTRYPOINT ["/usr/bin/nginx"]
這裏以上面Dockerfile格式
章節,做爲例子:
# 注意:第一行 必須以FROM 開頭。 # FROM 指定基礎鏡像,即以此鏡像做爲基礎 FROM nginx # 設置元數據,利用 docker inspect [鏡像名稱|鏡像ID],便可查看。 LABEL author="做者:oKong" LABEL version="版本:v0.1" LABEL desc="說明:修改nginx首頁提示" # 操做執行,這裏直接修改了nginx的html的首頁內容,/usr/share/nginx/html # 本來想輸出中文,亂碼了,設置了 ENV LANG C.UTF-8 或者 ENV LANG zh_CN.UTF-8 都不行 放棄了,有知道大神望告知! RUN echo 'hello,oKong' > /usr/share/nginx/html/index.html # 啓動命令 不寫時 會直接使用基礎鏡像的啓動命令 # CMD ["nginx", "-g", "daemon off;"] # 這裏利用 ENTRYPOINT 改寫 ENTRYPOINT ["nginx"]
使用docker build
構建鏡像,並將鏡像指定爲lqdev.cn/mynginx:v2
:
docker build -t lqdev.cn/mynginx:v2 .
構建完成後,使用lqdev.cn/mynginx:v2
啓動一個容器:
docker run -p 80:80 -d lqdev.cn/mynginx:v2 -g "daemon off;"
在運行容器時,咱們使用了 -g "daemon off;"
,這個參數將會被傳遞給 ENTRYPOINT
,最終在容器中執行的命令爲 nginx -g "daemon off;"
。此時,可利用docker ps -a
查看下,最後效果是同樣的。
用於在容器內設置一個工做目錄:
WORKDIR /opt/docker/workdir
經過WORKDIR
設置工做目錄後,Dockerfile
中其後的命令 RUN
、CMD
、ENTRYPOINT
、ADD
、COPY
等命令都會在該目錄下執行。
用於指定運行鏡像所使用的用戶:
USER okong
使用USER
指定用戶後,Dockerfile
中其後的命令RUN
、CMD
、ENTRYPOINT
都將使用該用戶。鏡像構建完成後,經過docker run
運行容器時,能夠經過-u
參數來覆蓋所指定的用戶。
還有像
ONBUILD
、STOPSIGNAL
、SHELL
及其MAINTAINER(已棄用)
等命令,不是十分經常使用或者已經棄用的,這裏不闡述了。主要是沒看懂具體啥意思,⊙﹏⊙‖∣。你們可經過其官網進行查看下:https://docs.docker.com/engine/reference/builder/
本章節主要是介紹了下
Dockerfile
的一些經常使用命令的說明。學習掌握了Dockerfile
命令使用後,咱們就能進行個性化鏡像的構建了。本章節只是簡單演示了下,下一章節,咱們就主要來一步步動手構建一個屬於本身的鏡像文件!
若文中有錯誤或者遺漏之處,還望指出,共同進步!
499452441
lqdevOps
我的博客:http://blog.lqdev.cn