docker使用小記3-dockerfile自定義鏡像

最近公司項目須要使用docker進行項目部署,現記錄下這段時間的學習內容,本章主要記錄dockerfile來自定義鏡像。固然咱們還能夠用commit經過容器來自定義鏡像,可是我此次基本都是用dockerfile來生成鏡像,commit等之後有用到再做記錄。java

1、dockerfile命令

FROM 指定基礎鏡像,放在第一行,其格式爲:mysql

1 #語法:
2 FROM <image> 
3 FROM <image>:<tag>
4 FROM <image>:<digest>

 

若想構建一個最小的鏡像,不想基於其餘任何鏡像時。可直接linux

1 FROM scratch

 

MAINTAINER指令容許你設置生成這個鏡像的做者。web

1 MAINTAINER lzq <xxx@xx.com>

 

也可使用LABEL設置鏡像相關信息redis

1 LABEL author="做者:xxx"
2 LABEL version="版本:v0.1"
3 LABEL desc="說明:test"

要查看時,可使用docker inspect 鏡像名或id 進行查看sql

 

ENV 設置環境變量,如java_home等。docker

1 ENV <key> <value>
2 ENV <key>=<value> ...

 

VOLUME 定義匿名卷,在咱們運行容器時,有些數據是須要被持久化保存的,好比mysql容器中的數據,tomcat容器中的logs日誌等,可是通常來講容器內的數據會隨着容器的刪除而消失,就算是用相同鏡像再去生成容器,運行時產生的數據也不會存在。因此當咱們須要對某些數據進行持久化時,能夠在生成容器時加上【-v 卷名或主機目錄:容器目錄 】的參數來對容器某個或多個目錄進行掛載,這樣的話就算以後容器被刪除,其被掛載的目錄數據仍會存在於主機之中,並且掛載以後對卷或主機目錄的修改會同步到容器對應目錄中,反之亦然。而若是掛載的主機卷或者目錄一開始就存在數據,則不管容器對應目錄內有無數據,都會被隱藏,顯示的是掛載主機卷或目錄存在的數據。通常來講-v參數若是沒有指定卷名或者主機目錄,只指定容器目錄的話,那麼docker會自動爲容器生成一個匿名卷,這樣的話效果跟在dockerfile中用VOLUME命令是同樣的,但每次都靠執行run命令生成容器時去添加-v參數的話有時會遺漏。因此咱們能夠在dockerfile文件使用VOLUME命令先定義匿名卷,對須要持久化的目錄進行掛載,這樣的話若是生成容器時忘了使用-v參數去掛載容器重要目錄,docker也會生成匿名卷將數據保存。而若是在run時使用-v參數對dockerfile中使用VOLUME掛載的目錄進行定義時(如指定卷名或者主機目錄),則docker不會生成匿名卷,而是根據當前指定的卷名或主機目錄對容器目錄進行掛載。shell

例如這是一份docekrfile文件:windows

 1 FROM centos:latest
 2 RUN groupadd -r redis && useradd  -r -g redis redis
 3 RUN yum -y update &&  yum -y install epel-release && yum -y install redis && yum -y install net-tools
 4  
 5 RUN mkdir -p /config && chown -R redis:redis /config
 6  
 7  
 8 VOLUME /share/data      #聲明容器中/share/data爲匿名卷
 9  
10  
11 EXPOSE 6379

那麼使用該Dockerfile構建鏡像的爲centos

1 #docker build -t image-redis    //構建鏡像image-redis
2 ......
3 #docker run -itd -name redis1 -v /data:/share/data image-redis    //運行一個容器而且將當前機器的/data目錄綁定到容器的匿名卷中
4 .....
5 #docker run -itd  -name redis2 image-redis     //運行一個容器可是不綁定目錄到容器的匿名卷,這時候在/var/lib/docker/volumes(不一樣版本目錄不同)中就會建立一個目錄綁定匿名卷
6 .....

刪除數據卷

數據卷 是被設計用來持久化數據的,它的生命週期獨立於容器,Docker 不會在容器被刪除後自動刪除 數據卷,而且也不存在垃圾回收這樣的機制來處理沒有任何容器引用的 數據卷。若是須要在刪除容器的同時移除數據卷。能夠在刪除容器的時候使用 docker rm -v 這個命令。

數據卷可能會佔據不少空間,可使用如下命令清理掉沒有容器使用的數據卷
謹慎操做,這須要你確認如今暫時沒有使用數據卷在之後也不會再使用,裏面也沒有有價值的數據。

1 docker volume prune

 

COPY 複製文件,主要就是構建鏡像時,進行拷貝文件到鏡像的指定路徑下,格式爲:

1 COPY <源路徑>... <目標路徑>
2 COPY ["<源路徑1>",... "<目標路徑>"]

 

ADD 更高級的複製文件,ADD 指令和 COPY 的格式和性質基本一致。可是在 COPY 基礎上增長了一些功能。好比<源路徑>能夠是一個 URL,這種狀況下,Docker 引擎會試圖去下載這個連接的文件放到<目標路徑>去,而若是原路徑是個壓縮包的話,ADD會在複製完畢後在目標目錄將文件進行解壓。

1 ADD jdk-8u45-linux-x64.tar.gz /usr/local

 

EXPOSE 設置監聽端口,爲鏡像設置監聽端口,容器運行時會監聽改端口,格式爲:

1 EXPOSE <port> [<port>/<protocol>...]
2 EXPOSE 80
3 EXPOSE 80/udp

 

RUN 執行命令,在鏡像的構建過程當中執行特定的命令,並生成一箇中間鏡像。格式:

1 RUN <command>
2 或者
3 RUN ["executable", "param1", "param2"]

這也是很經常使用的一個功能了。
第一種後邊直接跟shell命令

  • 在linux操做系統上默認 /bin/sh -c
  • 在windows操做系統上默認 cmd /S /C

第二種是相似於函數調用。

可將executable理解成爲可執行文件,後面就是兩個參數。

兩種寫法比對:

1 RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME
2 RUN ["/bin/bash", "-c", "echo hello"]

注意:多行命令不要寫多個RUN,緣由是Dockerfile中每個指令都會創建一層.多少個RUN就構建了多少層鏡像,會形成鏡像的臃腫、多層,不只僅增長了構件部署的時間,還容易出錯。

RUN書寫時的換行符是\

 

CMD 啓動時命令,功能爲容器啓動時要運行的命令,有三種寫法:

1 1. CMD ["executable","param1","param2"]
2 2. CMD ["param1","param2"]
3 3. CMD command param1 param2

第三種比較好理解了,就時shell這種執行方式和寫法,第一種和第二種其實都是可執行文件加上參數的形式:
舉例說明兩種寫法:

1 CMD [ "sh", "-c", "echo $HOME" ]
2 CMD [ "echo", "$HOME" ]

補充細節:這裏邊包括參數的必定要用雙引號,就是雙引號",不能是單引號。千萬不能寫成單引號。緣由是參數傳遞後,docker解析的是一個JSON array

 

ENTRYPOINT 啓動默認命令,ENTRYPOINT 用於給容器配置一個可執行程序。也就是說,每次使用鏡像建立容器時,經過 ENTRYPOINT 指定的程序都會被設置爲默認程序。ENTRYPOINT 有如下兩種形式:

1 ENTRYPOINT ["executable", "param1", "param2"]
2 ENTRYPOINT command param1 param2

ENTRYPOINT 與 CMD 很是相似,不一樣的是經過docker run執行的命令不會覆蓋 ENTRYPOINT,而docker run命令中指定的任何參數,都會被當作參數再次傳遞給ENTRYPOINTDockerfile 中只容許有一個 ENTRYPOINT 命令,多指定時會覆蓋前面的設置,而只執行最後的ENTRYPOINT 指令。
docker run運行容器時指定的參數都會被傳遞給ENTRYPOINT,且會覆蓋 CMD 命令指定的參數。如,執行docker run <image> -d時,-d 參數將被傳遞給入口點。
也能夠通過docker run --entrypoint重寫 ENTRYPOINT 入口點。

 

WORKDIR 指定工做目錄,用於在容器內設置一個工做目錄:

1 WORKDIR /opt/docker/workdir

經過WORKDIR設置工做目錄後,Dockerfile 中其後的命令RUNCMDENTRYPOINTADDCOPY等命令都會在該目錄下執行。

 

USER 指定當前用戶,用於指定運行鏡像所使用的用戶:

1 USER lzq

使用USER指定用戶後,Dockerfile 中其後的命令RUNCMDENTRYPOINT都將使用該用戶。鏡像構建完成後,經過docker run運行容器時,能夠經過-u參數來覆蓋所指定的用戶。

 

2、使用dockerfile構建自定義鏡像

經過上面的命令咱們能夠編寫一個dockerfile來自定義咱們的鏡像,如今咱們來構建一個tomcat鏡像,首先咱們得準備jdk和tomcat,咱們能夠在dockerfile中去下載,但我這裏已經下載了下來了

dockerfile當前目錄:

dockerfile內容:

 

 

 該文件內容定義了:

一、使用了centos做爲基礎鏡像

二、複製並解壓了jdk,定義了JAVA環境變量

三、複製並解壓了tomcat,定義了CATALINA_HOME

四、設置8080監聽接口

五、定義tomcat的webapps目錄爲匿名卷

六、複製web文件夾中的文件到容器webapps目錄中

七、設置tomcat的bin目錄爲工做目錄

八、設置容器啓動時默認啓動tomcat

 

接下來咱們用這個文件生成一個鏡像:

1 docker build -t tomcat .

 

 這樣就生成了一個自定義tomcat鏡像,咱們能夠運行docker images查看

 

 可見tomcat鏡像已經生成,接下來咱們用該鏡像生成一個容器:

1  docker run -itd -p 9000:8080 --name tomcat tomcat

 

 容器已經生成,咱們能夠輸入docker ps 查看正在運行的容器:

 

 可見容器已經在運行,此時咱們打開瀏覽器,輸入ip:9000並回車,能夠看到

 

 出現如上頁面,說明咱們容器中的tomcat也隨着容器啓動而啓動了。

 

參考資料:https://blog.lqdev.cn/2018/08/04/docker/docker-five/

     https://blog.csdn.net/fangford/article/details/88873104

相關文章
相關標籤/搜索