第十一章 Dockerfile構建映象
阿新 • • 發佈:2021-09-14
一、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>