最近公司項目須要使用docker進行項目部署,現記錄下這段時間的學習內容,本章主要記錄dockerfile來自定義鏡像。固然咱們還能夠用commit經過容器來自定義鏡像,可是我此次基本都是用dockerfile來生成鏡像,commit等之後有用到再做記錄。java
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命令
第二種是相似於函數調用。
可將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
命令中指定的任何參數,都會被當作參數再次傳遞給ENTRYPOINT
。Dockerfile
中只容許有一個 ENTRYPOINT
命令,多指定時會覆蓋前面的設置,而只執行最後的ENTRYPOINT
指令。docker run
運行容器時指定的參數都會被傳遞給ENTRYPOINT
,且會覆蓋 CMD 命令指定的參數。如,執行docker run <image> -d
時,-d
參數將被傳遞給入口點。
也能夠通過docker run --entrypoint
重寫 ENTRYPOINT
入口點。
WORKDIR 指定工做目錄,用於在容器內設置一個工做目錄:
1 WORKDIR /opt/docker/workdir
經過WORKDIR
設置工做目錄後,Dockerfile
中其後的命令RUN
、CMD
、ENTRYPOINT
、ADD
、COPY
等命令都會在該目錄下執行。
USER 指定當前用戶,用於指定運行鏡像所使用的用戶:
1 USER lzq
使用USER
指定用戶後,Dockerfile
中其後的命令RUN
、CMD
、ENTRYPOINT
都將使用該用戶。鏡像構建完成後,經過docker run
運行容器時,能夠經過-u
參數來覆蓋所指定的用戶。
經過上面的命令咱們能夠編寫一個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也隨着容器啓動而啓動了。