1. 程式人生 > 其它 >第十一章 Dockerfile構建映象

第十一章 Dockerfile構建映象

一、Dockerfile含義

Dockerfile 由一行行命令語句組成, 並且支援以#開頭的註釋行。一般而言, Dockerfile 主體內容分為四部分:基礎映象資訊、 維護者資訊、 映象操作指令和容器啟動時執行指令。

#1.Dockerfile是什麼?
構建映象所使用的指令配置檔案

#2.Dockerfile基礎部分
1、基礎映象,構建一個映象所依賴的映象(必須)
2、構建映象的指令,按照我們需求自定義映象
3、指定映象啟動命令,(指定容器啟動的方式)

#3.使用Dockerfile需要注意的幾點
1、dockerfile必須命名為`Dockerfile`
2、儘量將Dockerfile放在空目錄中,如果目錄中必須有其他檔案,則使用.dockerignore檔案。
3、避免安裝不必須的包。
4、每個容器應該只關注一個功能點。
5、最小化映象的層數。
6、多行引數時應該分類。這樣更清晰直白,便於閱讀和review,另外,在每個換行符\前都增加一個空格。
7、對構建快取要有清楚的認識。

二、Dockerfile的使用

#1.格式:
	docker build [引數] [dockerfile的路徑]

#2.原理
	在構建docker映象的時候,實際上將當前目錄移動到了一個虛擬目錄當中,所有的操作路徑都是以虛擬路徑為準。

#3.引數:
	-c : 指定使用CPU大小
	-f : 指定dockerfile路徑
	-t : 指定構建後的映象名稱

三、Dockerfile檔案說明

Docker以從上到下的順序執行Dockerfile的指令。為了指定基本映像,第一條指令必須是FROM。一個宣告以#字元開頭則被視為註釋。可以在Docker檔案中使用RUN,CMD,FROM,EXPOSE,ENV等指令。

1、FROM指令:指定基礎映象,必須為第一個命令

#1.解釋:
	指定構建映象的基礎映象(有且只能有一個基礎映象)

#2.格式:
	FROM [基礎映象]:[映象版本號]
	FROM <image>
	FROM <image>:<tag>
	FROM <image>@<digest>

#3.示例:
  FROM mysql:5.6

#4.注:
  tag或digest是可選的,如果不使用這兩個值時,會使用latest版本的基礎映象

2、MAINTAINER指令:維護者資訊

#1.解釋:
	指定維護者資訊(現在已經淘汰)

#2.格式:
	MAINTAINER [名字] [des] [...]
    MAINTAINER <name>

#3.示例:
    MAINTAINER Jasper Xu
    MAINTAINER [email protected]
    MAINTAINER Jasper Xu <[email protected]>

3、RUN指令:構建映象時執行的命令

#1.解釋:
	RUN用於在映象容器中執行命令,其有以下兩種命令執行方式:

#2.執行方式:
1.shell執行
格式:
	RUN [linux命令]
    RUN <command>
    
2.exec執行
格式:
    RUN ["executable", "param1", "param2"]

#3.示例:
    RUN ["executable", "param1", "param2"]
    RUN apk update
    RUN ["/etc/execfile", "arg1", "arg1"]
    
#4.注:
	RUN指令建立的中間映象會被快取,並會在下次構建中使用。如果不想使用這些快取映象,可以在構建時指定--no-cache引數,如:docker build --no-cache

4、ADD指令:將本地檔案新增到容器中

#1.解釋:
	將本地檔案新增到容器中,新增檔案到映象中,ADD指令有一個自動解壓的功能(tar),ADD指令可以下載網際網路上的檔案但是不解壓。

#2.格式:
	ADD [宿主主機檔案路徑(必須使用相對路徑)]  [新增到映象中的檔案路徑]
	ADD <src>... <dest>
    ADD ["<src>",... "<dest>"] 用於支援包含空格的路徑

#3.示例:
    ADD hom* /mydir/          # 新增所有以"hom"開頭的檔案
    ADD hom?.txt /mydir/      # ? 替代一個單字元,例如:"home.txt"
    ADD test relativeDir/     # 新增 "test" 到 `WORKDIR`/relativeDir/
    ADD test /absoluteDir/    # 新增 "test" 到 /absoluteDir/
    
# 新增檔案到容器當中
ADD ./1.txt /root

# 新增一個壓縮包,測試是否會自動解壓
ADD etcd-v3.0.17-darwin-amd64.zip /opt

# 在網上下載檔案至映象中(不會自動解壓)
ADD https://mirrors.huaweicloud.com/etcd/v3.0.17/v3.0.17.tar.gz  /opt

# 測試正則
ADD etcd-v3.0.17* /tmp/

# 測試ADD檔案
ADD mysql.txt /root/

#4.注:
	ADD指令支援正則(路徑必須以/結尾)

5、COPY指令 :功能類似ADD,但是是不會自動解壓檔案,也不能訪問網路資源

#1.解釋:
	複製一個檔案到映象中

#2.格式:
	COPY [宿主主機檔案路徑(必須使用相對路徑,只能向下找檔案)]  [新增到映象中的檔案路徑]
	COPY < src>… < dest>|[“< src>”,… “< dest>”]

#3.示例:
    # 測試COPY正則
    COPY etcd-v3.0.17* /etc/

    # 測試COPY檔案
    COPY mysql.txt /opt/
    
    # 測試COPY
    COPY ./1.txt /opt

    # 測試COPY解壓功能
    COPY etcd-v3.0.17-linux-amd64.tar.gz /opt
    
#4.注:
	COPY指令沒有解壓功能.
	COPY指令不支援網際網路下載.
	COPY指令支援正則.
	
ps:指令邏輯和ADD十分相似,同樣Docker Daemon會從編譯目錄尋找檔案或目錄,dest為映象中的絕對路徑或者相對於WORKDIR的路徑

6、CMD指令: 構建容器後呼叫,也就是在容器啟動時才進行呼叫

#1.解釋:
	指定容器啟動時預設命令

#2.格式:
    CMD ["executable","param1","param2"] (執行可執行檔案,優先)
    CMD ["param1","param2"] (設定了ENTRYPOINT,則直接呼叫ENTRYPOINT新增引數)
    CMD command param1 param2 (執行shell內部命令)

#3.示例:
    CMD echo "This is a test." | wc -
    CMD ["/usr/bin/wc","--help"]
	CMD /bin/bash
	CMD ["nginx","-g","daemon off;"]
	
#4. 注:   
	CMD不同於RUN,CMD用於指定在容器啟動時所要執行的命令,而RUN用於指定映象構建時所要執行的命令。

7、LABEL指令:用於為映象新增元資料

#1.解釋:
	使用LABEL指定元資料時
	
#2.格式:
    LABEL <key>=<value> <key>=<value> <key>=<value> ...
    
#3.示例:
  LABEL version="1.0" description="這是一個Web伺服器" by="IT筆錄"
  LABEL key=value
  
#4.注:
  使用LABEL指定元資料時,一條LABEL指定可以指定一或多條元資料,指定多條元資料時不同元資料之間通過空格分隔。推薦將所有的元資料通過一條LABEL指令指定,以免生成過多的中間映象。

8、ENV指令:設定環境變數

#1.解釋:
	指定環境變數
	
#2.格式:
    ENV <key> <value>  #<key>之後的所有內容均會被視為其<value>的組成部分,因此,一次只能設定一個變數
    ENV <key>=<value> ...  #可以設定多個變數,每個變數為一個"<key>=<value>"的鍵值對,如果<key>中包含空格,可以使用\來進行轉義,也可以通過""來進行標示;另外,反斜線也可以用於續行

#3.示例:
	ENV myName John Doe
	
    ENV myDog Rex The Dog
    
    ENV myCat=fluffy
    
	ENV NGINX_WORKER=5
        [root@docker ~/docker/nginx]# docker exec wizardly_cannon printenv
        PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
        NGINX_WORKER=5
        
	ENV NGINX_DES nginx server is very 666
		[root@docker ~/docker/nginx]# docker exec amazing_driscoll printenv
        PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
        NGINX_DES=nginx server is very 666
        
 #4.檢視環境變數
 [root@m01 ~]# docker exec {containerID} env

9、EXPOSE指令:指定於外界互動的埠

#1.解釋:
	指定向外暴露的埠

#2.格式:
    EXPOSE <port> [<port>...]

#3.示例:
    EXPOSE 80 443
    
    EXPOSE 8080 
    
    EXPOSE 11211/tcp 11211/udp

	EXPOSE 80 443 1000 10000
    [root@docker ~/docker/nginx]# docker run -d test/nginx:v12 
    e4f0b3a673dd9c83d2ecdb40c1726d3bed595890eeb9eab7fefb3218eb5650dc
    [root@docker ~/docker/nginx]# docker ps
    CONTAINER ID   IMAGE            COMMAND                  CREATED          STATUS          PORTS                                  NAMES
    e4f0b3a673dd   test/nginx:v12   "/docker-entrypoint.…"   3 seconds ago    Up 3 seconds    80/tcp, 443/tcp, 1000/tcp, 10000/tcp   naughty_fermat
    
    
    EXPOSE 80 443 1000/udp 10000
    [root@docker ~/docker/nginx]# docker ps
    CONTAINER ID   IMAGE            COMMAND                  CREATED          STATUS          PORTS                                  NAMES
    e1e4f2c18f40   test/nginx:v13   "/docker-entrypoint.…"   48 seconds ago   Up 48 seconds   80/tcp, 443/tcp, 10000/tcp, 1000/udp   hungry_aryabhata


#4.注:  
        EXPOSE並不會讓容器的埠訪問到主機。要使其可訪問,需要在docker run執行容器時通過-p來發布這些埠,或通過-P引數來發布EXPOSE匯出的所有埠

10、VILUME指令: 用於指定持久化目錄

#1.解釋:指定掛載點

#2.格式:
  VOLUME ["/path/to/dir"]

#3.示例:
  VOLUME ["/data"]
  
  VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]

  VOLUME /data
  docker inspect test/nginx:v14
        "Mounts": [
            {
                "Type": "volume",
                "Name": "b9b87662e3296ea94db87b48ef642933751f53fe7bf715026f59043bc65335f0",
                "Source": "/var/lib/docker/volumes/b9b87662e3296ea94db87b48ef642933751f53fe7bf715026f59043bc65335f0/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

#4.注:  
	一個卷可以存在於一個或多個容器的指定目錄,該目錄可以繞過聯合檔案系統,並具有以下功能:
		1.卷可以容器間共享和重用
		2.容器並不一定要和其它容器共享卷
		3.修改卷後會立即生效
		4.對卷的修改不會對映象產生影響
		5.卷會一直存在,直到沒有任何容器在使用它
		6.共享儲存卷:docker run --valumes-from [共享容器的名稱] [映象名稱]
		docker run -d --volumes-from upbeat_mcclintock test/nginx:v16
		7.如果使用-v引數,將掛載指定的目錄,不使用則自動生成掛載。

11、ARG指令:1.1、 用於指定傳遞給構建執行時的變數

#1.解釋:
	設定執行時引數,一般是在構建時使用

#2.格式:
	ARG key  : 需要用到docker build --build-arg key=value
	ARG key=value
	ARG <name>[=<default value>]

#3.示例:
	[root@docker ~/docker/nginx]# docker exec 7ed524e38ac8 cat log
	value
	
 	ARG site
 	
 	ARG build_user=www

12、ONBUILD指令:用於設定映象觸發器

#1.解釋:
	映象觸發器(噹噹前映象作為基礎映象時,執行)

#2.格式:
	ONBUILD [dockerfile指令]
	ONBUILD [INSTRUCTION]
	ONBUILD RUN touch 1.txt

#3.示例:
  ONBUILD ADD . /app/src
  ONBUILD RUN /usr/local/bin/python-build --dir /app/src

#4.注:  
    當所構建的映象被用做其它映象的基礎映象,該映象中的觸發器將會被鑰觸發

13. WORKDIR:工作目錄,類似於cd命令

#1.格式:
  WORKDIR /path/to/workdir

#2.示例:
  WORKDIR /a (這時工作目錄為/a)
  WORKDIR b (這時工作目錄為/a/b)
  WORKDIR c (這時工作目錄為/a/b/c)
  
#3.注:  
   通過WORKDIR設定工作目錄後,Dockerfile中其後的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都會在該目錄下執行。在使用docker run執行容器時,可以通過-w引數覆蓋構建時所設定的工作目錄。

四、Dockerfile構建映象案例一

1.新建Dockerfile

1.新建目錄
[root@m01 ~]# mkdir /docker/
[root@m01 ~]# cd /docker

2.新建Dockerfile
[root@m01 /docker]# cat Dockerfile 
#Is my first nginx Dockerfile
# Version 1.0

# Base images 基礎映象
FROM centos

#MAINTAINER 維護者資訊
MAINTAINER jh

#ADD  檔案放在當前目錄下,拷過去會自動解壓
ADD nginx-1.18.0.tar.gz /usr/local/  
ADD epel-release-latest-7.noarch.rpm /usr/local/  

#RUN 執行以下命令

RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm
RUN yum install -y gcc gcc-c++ autoconf pcre pcre-devel make automake wget httpd-tools vim tree && yum clean all
RUN useradd -s /sbin/nologin -M www

#WORKDIR 相當於cd
WORKDIR /usr/local/nginx-1.18.0 

RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_addition_module --with-http_auth_request_module --without-http_gzip_module && make && make install

RUN echo "daemon off;" >> /etc/nginx.conf

#ENV 設定環境變數
ENV PATH /usr/local/nginx/sbin:$PATH

#EXPOSE 對映埠
EXPOSE 80

#CMD 執行以下命令
CMD ["nginx"]

2.上傳相關安裝包

[root@m01 /docker]# rz
-rw-r--r-- 1 root root       918 Jan 14 20:59 Dockerfile
-rw-r--r-- 1 root root     15448 Jan 14 19:44 epel-release-latest-7.noarch.rpm
-rw-r--r-- 1 root root   1039530 Jan 14 19:44 nginx-1.18.0.tar.gz

3.建立映象

[root@m01 /docker]# docker build -t centos_nginx:v4 .
[root@m01 /docker]# docker images
REPOSITORY     TAG       IMAGE ID       CREATED         SIZE
centos_nginx   v4        f87c2b493910   7 minutes ago   483MB
centos         latest    300e315adb2f   5 weeks ago     209MB

4.備份映象

[root@m01 /docker]# docker save f87c2b493910 > centos_nginx:v4.tar

5.執行容器

[root@m01 /docker]# docker run -d -p81:80 centos_nginx:v4 nginx -g "daemon off;"
535f5d0f2829c1d4642020f03e8d48616f31edfe111bab02173f0815892d3698

五、Dockerfile構建映象案例二

1.新建Dockerfile

1.新建目錄
[root@m01 ~]# mkdir /docker/
[root@m01 ~]# cd /docker

2.新建Dockerfile
[root@m01 /docker]# vim Dockerfile 
#Is my first nginx Dockerfile
# Version 1.0

# Base images 基礎映象
FROM centos

#MAINTAINER 維護者資訊
MAINTAINER Jin Hui

#ADD  下載相關檔案放在當前目錄下,不會自動解壓
ADD http://nginx.org/download/nginx-1.18.0.tar.gz /usr/local/
ADD https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm /usr/local/ 

#RUN 執行以下命令
RUN tar xf /usr/local/nginx-1.18.0.tar.gz -C /usr/local/
RUN rpm -ivh /usr/local/epel-release-latest-8.noarch.rpm
RUN yum -y install gcc gcc-c++ autoconf pcre pcre-devel make automake wget httpd-tools vim tree && yum clean all
RUN useradd -s /sbin/nologin -M www

#WORKDIR 相當於cd
WORKDIR /usr/local/nginx-1.18.0 

#RUN 執行以下命令
RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_addition_module --with-http_auth_request_module --without-http_gzip_module && make && make install

#ENV 設定環境變數
ENV PATH /usr/local/nginx/sbin:$PATH

#EXPOSE 對映埠
EXPOSE 80

#CMD 執行以下命令
CMD ["nginx","-g","daemon off;"]

2.構建映象

[root@m01 /docker]# docker build --no-cache -t centos_nginx:v1 .
[root@m01 /docker]# docker images
REPOSITORY     TAG       IMAGE ID       CREATED         SIZE
centos_nginx   v1        ca2a0d26d619   21 minutes ago  521MB
centos         latest    300e315adb2f   5 weeks ago     209MB

3.備份映象

[root@m01 /docker]# docker save ca2a0d26d619 > centos_nginx:v1.tar

4.執行容器

[root@m01 /docker]# docker run -d -p 80:80  --name nginx centos_nginx:v1
dd014764a0d192cb6185d3db92e34a8e0358cf125c20d0a68a80b6a598e84c63

5.測試映象

[root@docker100 ~/1]# curl  127.0.0.1:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>