Dockerfile 構建映象(4)
1. Dockerfile 常用指令
1.1. FROM
語法:FROM :
指明構建的新映象來自於哪個基礎映象,如果沒有選擇tag,那麼預設值為latest。
FROM centos:7
如果不以任何映象為基礎,那麼寫法為:FROM scratch。官方說明:sceatch 映象是一個空映象,可以用於構建 busybox 等超小映象,可以說是真正的從零開始構建屬於自己的映象。
1.2. MAINTAINER(deprecated)
語法: MAINTAINER
指明映象維護者及其聯絡方式(一般是郵箱地址)。官方說明已過時,推薦使用 LABEL。
MAINTAINER xxxx <[email protected]
1.3. LABEL
語法: LABEL
功能是為映象指定標籤。也可以使用 LABEL 來指定映象作者。
LABEL maintainer="xxxx.com"
1.4. RUN
語法: RUN
構建映象時執行的 Shell 命令,比如構建的新映象中我們想在 /usr/local 目錄下建立一個 java 目錄。
RUN mkdir -p /usr/local/java
1.5. ADD
語法: ADD
拷貝檔案或目錄到映象中。src 可以是一個本地檔案或者是一個本地壓縮檔案,壓縮檔案會自動解壓。還可以是一個 url,如果把 src 寫成一個 url,那麼 ADD 就類似於 wget 命令,然後自動下載和解壓。
ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java
1.6. COPY
語法: COPY
拷貝檔案或目錄到映象中。用法同 ADD,只是不支援自動下載和解壓。
COPY jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java
1.7. EXPOSE
語法: EXPOSE
暴露容器執行時的監聽埠給外部,可以指定埠是監聽TCP還是UDP,如果未指定協議,則預設為TCP。
EXPOSE 80 443 8080/TCP
如果想使得容器與宿主機的埠有對映關係,必須在容器啟動的時候加上 -P 引數。
1.8. ENV
語法: ENV
設定容器內環境變數。
ENV JAVA_HOME /usr/local/java/jdk-11.0.6/
1.9. CMD
語法:
CMD ["executable","param1","param2"] ,比如: CMD ["/usr/local/tomcat/bin/catalina.sh", "run"]
CMD ["param1","param2"] ,比如: CMD [ "echo", "$JAVA_HOME" ]
CMD command param1 param2 ,比如: CMD echo $JAVA_HOME
啟動容器時執行的 shell 命令。在 Dockerfile 中只能有一條 CMD 命令。如果設定了多條 CMD ,只有最後一條 CMD 會生效。
CMD ehco $JAVA_HOME
如果建立容器的時候指定了命令,則 CMD 命令會被替代。假如映象叫 centos:7,建立容器的命令是:docker run -it --name centos7 centos:7 echo "helloworld" 或者 docker run -it --name centos7 centos:7 /bin/bash ,就不會輸出 $JAVA_HOME 的環境變數資訊了,因為 CMD 命令被 echo "helloworld" 、/bin/bash 覆蓋了。
1.10. ENTRYPOINT
語法:
ENTRYPOINT ["executable", "param1", "param2"] ,比如:ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh","run"]
ENTRYPOINT command param1 param2 ,比如: ENTRYPOINT ehco $JAVA_HOME
啟動容器時執行的 Shell 命令,同 CMD 類似,不會被 docker run 命令列指定的引數所覆蓋。在 Dockerfile 中只能有一條 ENTRYPOINT 指令。如果設定了多條 ENTRYPOINT,只有最後一條 ENTRYPOINT 會生效。
ENTRYPOINT ehco $JAVA_HOME
如果在 Dockerfile 中同時寫了 ENTRYPOINT 和 CMD,並且 CMD 指令不是一個完整的可執行命令,那麼 CMD 指定的內容將會作為 ENTRYPOINT 的引數;
如果在 Dokcerfile 中同時寫了 ENTRYPOINT 和 CMD,並且 CMD 是一個完整的指令,那麼它倆會互相覆蓋,誰在最後誰生效。
1.11. WORKDIR
語法:WORKDIR /path/to/workdir
為 RUN、CMD、ENTRYPOINT 以及 COPY 和 AND 設定工作目錄。
WORKDIR /usr/local
1.12. VOLUME
指定容器掛載點到宿主機自動生成的目錄或其他容器。一般的使用場景為,需要持久化儲存資料時。
# 容器的 /var/lib/mysql 目錄會在執行時自動掛載為匿名卷,匿名卷在宿主機的 /var/lib/docker/volume 目錄下
VOLUME ["/var/lib/mysql"]
一般不會在 Dockerfile 中用到,更常見的還是在 docker run 的時候通過 -v 指定資料卷。
2. 構建映象
Dockerfile 檔案編寫好以後,真正構建映象時需要通過 docker build 命令。
docker build 命令用於使用 Dockerfile 建立映象。
# 使用當前目錄的 Dockerfile 建立映象
docker build -t mycentos:7 .
# 通過 -f Dockerfile 檔案的位置建立映象
docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 .
# -f:指定要使用的 Dockerfile 路徑
# -tag,-t:映象的名字及標籤,可以在一次構建中為一個映象設定多個標籤。
2.1. 關於 . 理解
我們在使用 docker build 命令去構建映象時,往往會看到命令最後會有一個 . 號。它究竟是什麼意思呢?
很多人以為是用來指定 Dockerfile 檔案所在的位置的,但其實 -f 引數才是用來指定 Dockerfile 的路徑的,那麼 . 號究竟是用來做什麼的呢?
Docker 在執行時分為 Docker引擎(服務端守護程序)和 客戶端工具,我們日常使用各種 docker 命令,其實是在使用 客戶端工具 與 Docker引擎 進行互動。
當我們使用 docker build 命令來構建映象時,這個構建過程其實是在 Docker引擎 中完成的,而不是在本機環境。如果在 Dockerfile 中使用了一些 ADD 等指令來操作檔案,如何讓 Docker引擎 獲取到這些檔案呢?
這裡就有了一個 映象構建上下文 的概念,當構建的時候,由使用者指定構建映象時的上下文路徑,而 docker build 會將這個路徑下所有的檔案都打包上傳給 Docker引擎 ,引擎內將這些內容展開後,就能獲取的上下文中的檔案了。
舉個例子:
# 我的宿主機 jdk 檔案在 /root 目錄下,Dockerfile 檔案在 /usr/local/dockerfile 目錄下,檔案內容如下:
ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java
# 那麼構建映象時的命令就該這樣寫:
docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 /root
再舉個例子:
# 我的宿主機 jdk 檔案和 Dockerfile 檔案都在 /usr/local/dockerfile 目錄下,檔案內容如下:
ADD jkd-11.0.6_linux-x64_bin.tar.gz /usr/local/java
# 那麼構建映象時的命令則這樣寫:
docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 .
3. Dockerfile 實踐
通過基礎映象 centos:7 ,在該映象中安裝 jdk 和 tomcat 以後將其製作為一個新的映象 mycentos:7。
# 建立目錄
mkdir -p /usr/local/dockerfile
# 編寫 Dockerfile 檔案。
vi Dockerfile
Dockerfile 檔案內容如下:
# 指明構建的新映象是來自於 centos:7 基礎映象
FROM centos:7
# 通過映象標籤聲明瞭作者資訊
LABEL maintainer="xxxx.com"
# 設定工作目錄
WORKDIR /usr/local
# 新映象構建成功以後建立指定目錄
RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat
# 拷貝檔案到映象中並解壓
ADD jdk-11.0.7_linux-x64_bin.tar.gz /usr/local/java
ADD apache-tomcat-9.0.39.tar.gz /usr/local/tomcat
# 暴露容器執行時的 8080 監聽埠給外部
EXPOSE 8080
# 設定容器內 JAVA_HOME 環境變數
ENV JAVA_HOME /usr/local/java/jdk-11.0.7/
ENV PATH $PATH:$JAVA_HOME/bin
# 啟動容器時啟動 tomcat
CMD ["/usr/local/tomcat/apache-tomcat-9.0.39/bin/catalina.sh", "run"]
構建映象:
[root@localhost ~]# docker build -f /usr/local/dockerfile/Dockerfile -t mycentos:7 /root/
Sending build context to Docker daemon 191.4MB
Step 1/10 : FROM centos:7
---> 7e6257c9f8d8
Step 2/10 : LABEL maintainer="xxxx.com"
---> Running in 3f18aa4f3fb2
Removing intermediate container 3f18aa4f3fb2
---> 7364f68ca4ab
Step 3/10 : WORKDIR /usr/local
---> Running in d9889152cfc4
Removing intermediate container d9889152cfc4
---> d05bd2e09fa4
Step 4/10 : RUN mkdir -p /usr/local/java && mkdir -p /usr/local/tomcat
---> Running in 3bcd6ef78350
Removing intermediate container 3bcd6ef78350
---> 4832abf9d769
Step 5/10 : ADD jdk-11.0.6_linux-x64_bin.tar.gz /usr/local/java
---> e61474bf7a76
Step 6/10 : ADD apache-tomcat-9.0.37.tar.gz /usr/local/tomcat
---> 7110cdff7438
Step 7/10 : EXPOSE 8080
---> Running in a4731c1cf77d
Removing intermediate container a4731c1cf77d
---> f893cefee00c
Step 8/10 : ENV JAVA_HOME /usr/local/java/jdk-11.0.6/
---> Running in f0cb08f390db
Removing intermediate container f0cb08f390db
---> ff9f6acf6844
Step 9/10 : ENV PATH $PATH:$JAVA_HOME/bin
---> Running in eae88cf841d0
Removing intermediate container eae88cf841d0
---> 4b9226a23b10
Step 10/10 : CMD ["/usr/local/tomcat/apache-tomcat9.0.37/bin/catalina.sh", "run"]
---> Running in ccf481045906
Removing intermediate container ccf481045906
---> 9ef76a16441b
Successfully built 9ef76a16441b
Successfully tagged mycentos:7
4. 映象構建歷史
docker history 映象名稱:標籤|ID
docker history mycentos:7
5. 使用構建的映象建立容器
# 建立容器
docker run -di --name mycentos7 -p 8080:8080 mycentos:7
# 進入容器
docker exec -it mycentos7 /bin/bash
# 測試 java 環境變數
[root@dcae34gsdf /]# java -version
java version "11.0.6" 2020-01-14 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.6+8-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.6+8-LTS, mixedmode)
# 瀏覽器訪問 8080 檢視介面,雲伺服器需要在安全組開啟埠