歡迎光臨
每天分享高質量文章

如何用Dockerfile構建鏡像

來自:編程無界(微信號:qianshic)

前面講到鏡像的構建時,講述的是用commit的方式構建鏡像,而Dockerfile是另一種構建鏡像的方式。

Dockerfile構建鏡像是以基礎鏡像為基礎的,Dockerfile是一個文本檔案,內容是用戶編寫的一些docker指令,每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建。

Dockerfile的基本指令有十三個,分別是:FROM、MAINTAINER、RUN、CMD、EXPOSE、ENV、ADD、COPY、ENTRYPOINT、VOLUME、USER、WORKDIR、ONBUILD

從前面的內容可以看出,要構建一個容器,需要做很多的工作,設置很多的配置,如果我們可以把每一層修改、安裝、構建、操作的命令都寫入一個腳本,用這個腳本來構建、定製鏡像,那麼之前提及的無法重覆的問題、鏡像構建透明性的問題、體積的問題就都會解決。
這個腳本就是 Dockerfile。

因此學會用Dockerfile來構建鏡像,是非常有必要的。學習Dockerfile之前,我們先來學習一些Dockerfile常用的指令。

文章提綱:

  1. Dockerfile常用指令

  2. Dockerfile的編寫

  3. 用Dockerfile構建鏡像

  4. 彩蛋

1、Dockerfile常用指令

型別 命令
基礎鏡像信息 FROM
維護者信息 MAINTAINER
鏡像操作指令 RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME等
容器啟動時執行指令 CMD、ENTRYPOINT

1.1、FROM :指定基礎鏡像

所謂定製鏡像,那一定是以一個鏡像為基礎,在其上進行定製。就像我們之前運行了一個nginx鏡像的容器,再進行修改一樣,基礎鏡像是必須指定的。而FROM就是指定基礎鏡 像,因此一個Dockerfile中FROM是必備的指令,並且必須是第一條指令。

如:指定ubuntu的14版本作為基礎鏡像

1FROM ubuntu:14

1.2、 RUN:執行命令

RUN指令在新鏡像內部執行的命令,如:執行某些動作、安裝系統軟體、配置系統信息之類,

格式如下兩種:

  • 1)shell格式:RUN< command > ,就像直接在命令列中輸入的命令一樣。
    如在nginx里的預設主頁中寫”hello“:

1RUN echo 'hello ' >/etc/nginx/html/index.html

  • 2)exec格式:RUN [“可執行檔案”, “引數1”, “引數2”]
    如在新鏡像中用yum方式安裝nginx:

1RUN ["yum","install","nginx"]

註:多行命令不要寫多個RUN,原因是Dockerfile中每一個指令都會建立一層.多少個RUN就構建了多少層鏡像,會造成鏡像的臃腫、多層,不僅僅增加了構件部署的時間,還容易出錯,RUN書寫時的換行符是

1.3、COPY:複製檔案

COPY命令用於將宿主機器上的的檔案複製到鏡像內,如果目的位置不存在,Docker會自動創建。但宿主機器用要複製的目錄必須是和Dockerfile檔案統計目錄下。

格式:

1COPY [--chown=<user>:<group><源路徑>... <標的路徑>
2COPY [--chown=<user>:<group>] ["<源路徑1>",... "<標的路徑>"]

如把宿主機中的package.json檔案複製到容器中/usr/src/app/目錄下:

1COPY package.json /usr/src/app/

1.4、CMD:容器啟動命令

CMD命令用於容器啟動時需要執行的命令,CMD在Dockerfile中只能出現一次,如果出現多個,那麼只有最後一個會有效。

其作用是在啟動容器的時候提供一個預設的命令項。如果用戶執行docker run的時候提供了命令項,就會改寫掉這個命令,沒提供就會使用構建時的命令。

格式:

1shell 格式:CMD <命令>
2exec 格式:CMD ["可執行檔案", "引數1", "引數2"...]

如容器啟動時進入bash:

1CMD /bin/bash

也可以用exec寫法:

1CMD ["/bin/bash"]

1.5 MAINTAINER:指定作者

用來指定dockerfile的作者名稱和郵箱,主要作用是為了標識軟體的所有者是誰。
語法:

1MAINTAINER <name> <email>

如:

1MAINTAINER autor_jiabuli [email protected]

1.6、EXPOSE:暴露端口

EXPOSE命名適用於設置容器對外映射的容器端口號,如tomcat容器內使用的端口8081,則用EXPOSE命令可以告訴外界該容器的8081端口對外,在構建鏡像時
用docker run -p可以設置暴露的端口對宿主機器端口的映射。

語法:

1EXPOSE <端口1> [<端口2>...]

如:

1EXPOSE 8081

EXPOSE 8081 其實等價於 docker run -p 8081 當需要把8081端口映射到宿主機中的某個端口(如8888)以便外界訪問時,則可以用docker run -p 8888:8081

1.7、WORKDIR:配置工作目錄

WORKDIR命令是為RUN、CMD、ENTRYPOINT指令配置工作目錄。其效果類似於Linux命名中的cd命令,用於目錄的切換,但是和cd不一樣的是:如果切換到的目錄不存在,WORKDIR會為此創建目錄。

語法:

1WORKDIR path

如需要在nginx目錄下創建一個hello.txt的檔案:

1##進入/usr/local/nginx目錄下
2WORKDIR /usr/local/nginx
3
4##進入/usr/local/nginx中的html目錄下
5WORKDIR html
6
7## 在html目錄下創建了一個hello.txt檔案
8RUN echo 'hello' > hello.txt

1.8、ENTRYPOINT:容器啟動執行命名

ENTRYPOINT的作用和用法和CMD一模一樣,但是ENTRYPOINT有和CMD有2處不一樣:

  1. CMD的命令會被docker run的命令改寫而ENTRYPOINT不會

  2. CMD和ENTRYPOINT都存在時,CMD的指令變成了ENTRYPOINT的引數,並且此CMD提供的引數會被 docker run 後面的命令改寫

1.9、VOLUME

VOLUME用來創建一個可以從本地主機或其他容器掛載的掛載點。例如我們知道tomcat的webapps目錄是放web應用程式代碼的地方,此時我們要把webapps目錄掛載為匿名捲,這樣任何寫入webapps中的心都不會被記錄到容器的儲存層,讓容器儲存層無狀態化。

格式:

1VOLUME ["path"]

如創建tomcat的webapps目錄的一個掛載點

1VOLUME /usr/local/tomcat/webapps

這樣,在運行容器時,也可以用過docker run -v來把匿名掛載點掛載都宿主機器上的某個目錄,如

1docker run -d -v /home/tomcat_webapps:/usr/local/tomcat/webapps

1.10、 USER
USER命令用於指定當前望下執行的用戶,需要註意的是這個用戶必須是已經存在,否則無法指定。它的用法和WORKDIR有點像,切換用戶。

格式:

1USER daemon

1.11、ADD

作用和使用方法和COPY一模一樣,在此不重覆講述。

1.12、ONBUILD

ONBUILD用於配置當前所創建的鏡像作為其它新創建鏡像的基礎鏡像時,所執行的操作指令。

意思就是:這個鏡像創建後,如果其它鏡像以這個鏡像為基礎,會先執行這個鏡像的ONBUILD命令
格式:

1ONBUILD [INSTRUCTION]

1.13、ENV:設置環境變數

ENV命名用於設置容器的環境變數,這些變數以”key=value”的形式存在,在容器內被腳本或者程式呼叫,容器運行的時候這個變數也會保留。

格式:

  • 1) 設置一個: ENV

  • 2) 設置多個:ENV = =…

如設置一個環境變數JAVA_HOME,接下來的命名就可以使用這個變數:

1ENV JAVA_HOME /opt/jdk
2ENV PATH $PATH:$JAVA_HOME/bin

在使用ENV設置環境變數時,有幾點需要註意:

  • 1)具有傳遞性,也就是當前鏡像被用作其它鏡像的基礎鏡像時,新鏡像會擁有當前這個基礎鏡像所有的環境變數

  • 2)ENV定義的環境變數,可以在dockerfile被後面的所有指令(CMD除外)中使用,但不能被docker run 的命令引數取用
    如:

1ENV tomcat_home_name tomcat_7
2RUN mkdir $tomcat_home_name

  • 3)除了ENV之外,docker run -e 也可以設置環境變數傳入容器內。
    如:

1docker run -d tomcat -e "tomcat_home_name=tomcat_7"

這樣我們進入容器內部用ENV可以看到tomcat_home_name這個環境變數。

2、Dockerfile的編寫

我們先看一個例子

 1#在centos上安裝nginx
 2FROM centos
 3#標明著作人的名稱和郵箱
 4MAINTAINER jiabuli [email protected]
 5#測試一下網絡環境
 6RUN ping -c 1 www.baidu.com
 7#安裝nginx必要的一些軟體
 8RUN yum -y install gcc make pcre-devel zlib-devel tar zlib
 9#把nginx安裝包複製到/usr/src/目錄下
10ADD nginx-1.15.8.tar.gz /usr/src/
11#切換到/usr/src/nginx-1.15.8編譯並且安裝nginx
12RUN cd /usr/src/nginx-1.15.8 
13    && mkdir /usr/local/nginx 
14    && ./configure --prefix=/usr/local/nginx && make && make install 
15    && ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/ 
16    && nginx
17#刪除安裝nginx安裝目錄
18RUN rm -rf /usr/src/nginx-nginx-1.15.8
19#對外暴露80端口
20EXPOSE 80
21#啟動nginx
22CMD ["nginx", "-g", "daemon off;"]

上面的註釋已經講的非常清楚,其實不難發現,上面的例子就是類似於在centos系統上安裝一個nginx的的一個過程,因此編寫Dockerfile構建鏡像就和在Linux上安裝軟體的流程幾乎是一模一樣的。所以我們在編寫Dockerfile來構建鏡像時,可以先思考在Linux上安裝該軟體的流程,再用Dockerfile提供的指令轉化到Dockerfile中即可。

3、用Dockerfile構建鏡像

用Dockerfile的核心在於編寫Dockerfile,但是編寫完之後我們需要知道怎麼使用Dockerfile來構建鏡像,下麵以構建nginx鏡像為例來簡要說明構建流程

3.1 上傳安裝包

首先我們需要把要構建的軟體安裝包上傳到服務器中,我們可以在服務器目錄上創建一個專門的檔案夾,如:/var/nginx_build,然後把從nginx官網下載的nginx-1.15.8.tar.gz安裝包上傳到這個目錄里。

3.2 編寫Dockerfile

如何編寫nginx的Dockerfile上面已經詳細介紹,現在我們只需把編寫好的Dockerfile上傳到/var/nginx_build目錄下,當然你也可以在服務器上直接編寫Dockerfile,但是要記得一定保證Dockerfile檔案和安裝包在一個目錄下。

3.3 運行構建命令構建

docker build 命令用於使用 Dockerfile 創建鏡像。
格式:

1  docker build [OPTIONS] PATH | URL | -

OPTIONS有很多指令,下麵列舉幾個常用的:

  • –build-arg=[] :設置鏡像創建時的變數;

  • -f :指定要使用的Dockerfile路徑;

  • –force-rm :設置鏡像過程中刪除中間容器;

  • –rm :設置鏡像成功後刪除中間容器;

  • –tag, -t: 鏡像的名字及標簽,通常 name:tag 或者 name 格式;

因此我們構建nginx可以用以下命令:

1docker build -t nginx:v1.0 .

當Dockerfile和當前執行命令的目錄不在同一個時,我們也可以指定Dockerfile,如

1docker build -f /var/nginx_build/Dockerfile .

執行命名之後,會看到控制台逐層輸出構建內容,直到輸出兩個Successfully即為構建成功。

    赞(0)

    分享創造快樂