1.DockerFile是什麼
當我們從docker鏡像倉庫中下載的鏡像不能滿足我們的需求時,我們可以通過以下兩種方式對鏡像進行更改。
1.從已經創建的容器中更新鏡像,並且提交這個鏡像
2.使用 Dockerfile 指令來創建一個新的鏡像Dockerfile是用來構建Docker鏡像的構建文件,是由一系列命令和參數構成的腳本。DockerFile是描述鏡像的一種文件!
DockerFile是鏡像的說明書,裏面有一系列的執行,告訴Docker如何構建鏡像!
Dockerfile面向開發,Docker鏡像成爲交付標準,Docker容器則涉及部署與運維,三者缺一不可,合力充當Docker體系的基石。
-
Dockerfile,需要定義一個Dockerfile,Dockerfile定義了進程需要的一切東西。Dockerfile涉及的內容包括執行代碼或者是文件、環境變量、依賴包、運行時環境、動態鏈接庫、操作系統的發行版、服務進程和內核進程(當應用進程需要和系統服務和內核進程打交道,這時需要考慮如何設計namespace的權限控制)等等;
-
在Docker中創建鏡像最常用的方式,就是使用Dockerfile。Dockerfile是一個Docker鏡像的描述文件,我們可以理解成火箭發射的A、B、C、D…的步驟。Dockerfile其內部包含了一條條的指令,每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建。
-
Docker鏡像,在用Dockerfile定義一個文件之後,docker build時會產生一個Docker鏡像,當運行 Docker鏡像時,會真正開始提供服務;
-
Docker容器,容器是直接提供服務的。
-
構建三步驟
編寫Dockerfile文件 -----> 編寫DockerFile文件
docker build -----> 構建鏡像
docker run -----> 使用鏡像啓動容器
DockerFile就是鏡像的描述文件!
2.DockerFile文件什麼樣
2.1.以我們熟悉的CentOS爲例
網站:https://hub.docker.com/_/centos/
2.2.一個Dockerfile的示例如下所示
#基於centos鏡像
FROM centos
#維護人的信息
MAINTAINER The CentOS Project <[email protected]>
#安裝httpd軟件包
RUN yum -y update
RUN yum -y install httpd
#開啓80端口
EXPOSE 80
#複製網站首頁文件至鏡像中web站點下
ADD index.html /var/www/html/index.html
#複製該腳本至鏡像中,並修改其權限
ADD run.sh /run.sh
RUN chmod 775 /run.sh
#當啓動容器時執行的腳本文件
CMD ["/run.sh"]
由上可知,Dockerfile結構大致分爲四個部分:
(1)基礎鏡像信息
(2)維護者信息
(3)鏡像操作指令
(4)容器啓動時執行指令。
Dockerfile每行支持一條指令,每條指令可帶多個參數,支持使用以#號開頭的註釋。下面會對上面使用到的一些常用指令做一些介紹。
2.3.DockerFile構建過程解析
-
Dockerfile內容基礎知識
1:每條保留字指令都必須爲大寫字母且後面要跟隨至少一個參數
2:指令按照從上到下,順序執行
3:#表示註釋
4:每條指令都會創建一個新的鏡像層,並對鏡像進行提交 -
Dockerfile內容基礎知識
1:docker從基礎鏡像運行一個容器
2:執行一條指令並對容器作出修改
3:執行類似docker commit的操作提交一個新的鏡像層
4:docker再基於剛提交的鏡像運行一個新容器
5:執行dockerfile中的下一條指令直到所有指令都執行完成 -
小結
從應用軟件的角度來看,Dockerfile、Docker鏡像與Docker容器分別代表軟件的三個不同階段:
1:Dockerfile是軟件的原材料
2:Docker鏡像是軟件的交付品
3**:Docker容器**則可以認爲是軟件的運行態。
3.Dockerfile常用指令
3.1.FROM
指明構建的新鏡像是來自於哪個基礎鏡像,例如:
FROM centos:6
基礎鏡像不存在會在Docker Hub上拉去(一般會是文件的第一個指令) 使用格式:
FROM <鏡像>:[tag]
3.2.MAINTAINER
指明鏡像維護着及其聯繫方式(一般是郵箱地址),例如
MAINTAINER BRUCELIU<[email protected]>
不過,MAINTAINER並不推薦使用,更推薦使用LABEL來指定鏡像作者,例如:
LABEL maintainer="bruceliu.cn"
[逐漸廢棄] LABLE --替代MAINTANIER 具體使用: LABLE maintainer=“作者信息”
3.3.RUN
RUN 指令是用來執行命令行命令的。由於命令行的強大能力,RUN 指令在定製鏡像時是最常用的指令之一。其格式有兩種:
• shell 格式:RUN <命令>,就像直接在命令行中輸入的命令一樣。剛纔寫的 Dockerfile 中的 RUN 指令就是這種格式.
• exec 格式:RUN [“可執行文件”, “參數1”, “參數2”],這更像是函數調用中的格式。
使用格式:
RUN RUN ["","",""]
構建鏡像時運行的Shell命令,例如:
RUN ["yum", "install", "httpd"]
RUN yum install httpd
RUN 就像 Shell 腳本一樣可以執行命令,那麼我們是否就可以像 Shell 腳本一樣把每個命令對應一個 RUN 呢?比如
這樣:
RUN apt-get update
RUN apt-get install -y gcc libc6-dev make
RUN wget http://download.redis.io/releases/redis-4.0.1.tar.gz
RUN tar xzf redis-4.0.1.tar.gz
RUN cd redis-4.0.1
Dockerfile 中每一個指令都會建立一層,RUN 也不例外。每一個 RUN 的行爲,和剛纔我們手工建立鏡像的過程一樣:新建立一層,在其上執行這些命令,執行結束後,commit 這一層的修改,構成新的鏡像。 而上面的這種寫法,創建了 多 層鏡像。這是完全沒有意義的,而且很多運行時不需要的東西,都被裝進了鏡像裏,比如編譯環境、更新的軟件包等等。結果就是產生非常臃腫、非常多層的鏡像,不僅僅增加了構建部署的時間,也很容易出錯。 這是很多初學 Docker 的人常犯的一個錯誤。
Union FS 是有最大層數限制的,比如 AUFS,曾經是最大不得超過 42 層,現在是不得超過 127 層。上面的Dockerfile 正確的寫法應該是這樣
FROM centos
RUN apt-get update \
&& apt-get install -y gcc libc6-dev make \
&& wget http://download.redis.io/releases/redis-4.0.1.tar.gz \
&& tar xzf redis-4.0.1.tar.gz \
&& cd redis-4.0.1
首先,之前所有的命令只有一個目的,就是編譯、安裝 redis 可執行文件。因此沒有必要建立很多層,這只是一層的事情。因此,這裏沒有使用很多個 RUN 對一一對應不同的命令,而是僅僅使用一個 RUN 指令,並使用 && 將各個所需命令串聯起來。將之前的 7 層,簡化爲了 1 層。
在撰寫 Dockerfile 的時候,要經常提醒自己,這並不是在寫Shell 腳本,而是在定義每一層該如何構建且,這裏爲了格式化還進行了換行。Dockerfile 支持 Shell 類的行尾添加 \ 的命令換行方式,以及行首 # 進行註釋的格式。良好的格式,比如換行、縮進、註釋等,會讓維護、排障更爲容易,這是一個比較好的習慣。
3.4.CMD
啓動容器時執行的Shell命令,例如:
CMD ["-C", "/start.sh"]
CMD ["/usr/sbin/sshd", "-D"]
CMD /usr/sbin/sshd -D
3.5.EXPOSE
聲明容器運行的服務端口,爲容器打開指定要監聽的端口以實現與外部通信,例如:
EXPOSE 80 443
3.6.ENV
ENV指令可以用於爲docker容器設置環境變量 ENV設置的環境變量,可以使用 docker inspect命令來查看。同時還可以使用docker run --env =來修改環境變量。
具體用法:
ENV JAVA_HOME /usr/local/jdk
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/:$JRE_HOME/lib/
ENV PATH $PATH:$JAVA_HOME/bin/
3.7.ADD
類似COPY命令,拷貝文件或目錄到鏡像中,例如:
ADD <src>...<dest>
ADD html.tar.gz /var/www/html
ADD https://xxx.com/html.tar.gz /var/www/html
3.8.COPY
拷貝文件或目錄到鏡像中,用法同ADD,只是不支持自動下載和解壓,例如:
COPY ./start.sh /start.sh
3.9.ENTRYPOINT
啓動容器時執行的Shell命令,同CMD類似,只是由ENTRYPOINT啓動的程序不會被docker run命令行指定的參數所覆蓋,而且,這些命令行參數會被當作參數傳遞給ENTRYPOINT指定指定的程序,例如:
ENTRYPOINT ["/bin/bash", "-C", "/start.sh"]
ENTRYPOINT /bin/bash -C '/start.sh'
PS:Dockerfile文件中也可以存在多個ENTRYPOINT指令,但僅有最後一個會生效。
3.10. VOLUME
創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據等。例如:
VOLUME ["/var/lib/mysql"]
只能定義docker管理的卷: VOLUME /data/mysql運行的時候會隨機在宿主機的目錄下生成一個卷目錄!
一般不會在Dockerfile中用到,更常見的還是在docker run的時候指定-v數據卷。
3.11 USER
爲RUN、CMD和ENTRYPOINT執行Shell命令指定運行用戶,例如:
USER <user>[:<usergroup>]
USER <UID>[:<UID>]
USER bruceliu
3.12 WORKDIR
Docker 默認的工作目錄是/,只有 RUN 能執行 cd 命令切換目錄,而且還只作用在當下下的 RUN,也就是說每一個 RUN 都是獨立進行的。
如果想讓其他指令在指定的目錄下執行,就得靠 WORKDIR。WORKDIR 動作的目錄改變是持久的,不用每個指令前都使用一次 WORKDIR。
WORKDIR /usr/local/tomcat/
3.13.小總結
4.DockerFile案例
4.1.Base鏡像(scratch)
Docker Hub 中 99% 的鏡像都是通過在 base 鏡像中安裝和配置需要的軟件構建出來的
4.2.自定義鏡像mycentos
Docker Hub默認CentOS鏡像什麼情況??
- 準備編寫DockerFile文件
[root@localhost myfile]# pwd
/root/myfile
[root@localhost myfile]# vi mycentos_dockerfile
- myCentOS內容DockerFile
FROM centos
MAINTAINER bruceliu<bruceliu167@126.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
- 構建
命令:
docker build -t 新鏡像名字:TAG .
會看到 docker build 命令最後有一個 .
. 表示當前目錄
[root@localhost myfile]# docker build -f /root/myfile/mycentos_dockerfile -t mycentos:1.3 .
Sending build context to Docker daemon 2.048 kB
Step 1/10 : FROM centos
---> 9f38484d220f
Step 2/10 : MAINTAINER bruceliu<bruceliu167@126.com>
---> Using cache
---> 281446cb753d
Step 3/10 : ENV MYPATH /usr/local
---> Using cache
---> 2e09cdb61576
Step 4/10 : WORKDIR $MYPATH
---> Using cache
---> 4aa136d65f26
Step 5/10 : RUN yum -y install vim
---> Using cache
---> 585392f09407
Step 6/10 : RUN yum -y install net-tools
---> Using cache
---> 9c7971b08e59
Step 7/10 : EXPOSE 80
---> Using cache
---> 6741c0b61390
Step 8/10 : CMD echo $MYPATH
---> Using cache
---> fb1b4b72ba02
Step 9/10 : CMD echo "success--------------ok"
---> Using cache
---> 3d636347cc9a
Step 10/10 : CMD /bin/bash
---> Using cache
---> 720d4eb5c5f0
Successfully built 720d4eb5c5f0
- 運行
docker run -it 新鏡像名字:TAG
可以看到,我們自己的新鏡像已經支持vim/ifconfig命令,擴展成功了。
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/mongo latest 9c02a5a12c52 Less than a second ago 413 MB
mycentos 1.3 720d4eb5c5f0 50 minutes ago 480 MB
bruceliu/centos9527 latest 071e944a589b 8 hours ago 202 MB
bruceliu/tomcat 7-jre7 a66f9aba334d 13 hours ago 359 MB
docker.io/tomcat 7-jre7 47c156f4d4e3 5 weeks ago 359 MB
docker.io/mysql latest 7bb2586065cd 2 months ago 477 MB
docker.io/centos 7 9f38484d220f 3 months ago 202 MB
docker.io/centos latest 9f38484d220f 3 months ago 202 MB
[root@localhost ~]# docker run -it mycentos:1.3
[root@50784a17d114 local]# pwd
/usr/local
[root@50784a17d114 local]# vi 1.txt
[root@50784a17d114 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.3 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:3 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 656 (656.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 列出鏡像的變更歷史
命令:
docker history 鏡像名
[root@localhost ~]# docker history 720d4eb5c5f0
IMAGE CREATED CREATED BY SIZE COMMENT
720d4eb5c5f0 53 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/b... 0 B
3d636347cc9a 53 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ec... 0 B
fb1b4b72ba02 53 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ec... 0 B
6741c0b61390 53 minutes ago /bin/sh -c #(nop) EXPOSE 80/tcp 0 B
9c7971b08e59 53 minutes ago /bin/sh -c yum -y install net-tools 112 MB
585392f09407 54 minutes ago /bin/sh -c yum -y install vim 167 MB
4aa136d65f26 About an hour ago /bin/sh -c #(nop) WORKDIR /usr/local 0 B
2e09cdb61576 About an hour ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0 B
281446cb753d About an hour ago /bin/sh -c #(nop) MAINTAINER bruceliu<bru... 0 B
9f38484d220f 3 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
<missing> 3 months ago /bin/sh -c #(nop) LABEL org.label-schema.... 0 B
<missing> 3 months ago /bin/sh -c #(nop) ADD file:074f2c974463ab3... 202 MB