Docker系列之四:Dockerfile的使用
系列連結
Docker系列之一:Docker介紹及在Ubuntu上安裝
Docker系列之五:Volume 卷的使用——以Redis為例
Docker系列之六:Volume 卷的使用——在Dockerfile中的用法
Docker系列之七:Docker 網路(內部網路、容器之間的連線)
Docker系列之八:在Dockerfile中使用多段構建Muti-stage build
Docker系列之九:Docker用於持續整合,構建Jenkins和Docker伺服器
簡介
Dockerfile是自動構建Docker映象的配置檔案,使用者可以使用Dockerfile快速建立自定義的映象。
Dockerfile 可以自定義映象,通過 Docker 命令去執行映象,從而達到啟動容器的目的。Dockerfile 是由一行行命令語句組成,並且支援已 # 開頭的註釋行。
Dockerfile 分為四個部分:
-
基礎映象(父映象)資訊指令 FROM。
-
維護者資訊指令 MAINTAINER。
-
映象操作指令 RUN 、EVN 、ADD 和 WORKDIR 等。
-
容器啟動指令 CMD 、ENTRYPOINT 和 USER 等。
例子
先看個最簡單的例子吧
[email protected]:/home/cong/DockerDemo# ls
Dockerfile index.html
[email protected]:/home/cong/DockerDemo# cat Dockerfile
#nginx基礎映象
FROM nginx
#指定工作路徑
WORKDIR /usr/share/nginx/html
#將前前路徑下的所有檔案都COPY到工作路徑下
COPY . .
#EXPOSE 命令用來指定對外開放的埠,實際用處不大,可不寫
EXPOSE 80
[email protected] :/home/cong/DockerDemo# cat index.html
<h1>hello</h1>
[email protected]:/home/cong/DockerDemo# docker build --tag firstdemo .
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM nginx
---> dbfc48660aeb
Step 2/4 : WORKDIR /usr/share/nginx/html
---> Using cache
---> 49eb0195ae40
Step 3/4 : COPY . .
---> 38b65eaf39e1
Step 4/4 : EXPOSE 80
---> Running in 48478a97934d
Removing intermediate container 48478a97934d
---> e16afe49d571
Successfully built e16afe49d571
Successfully tagged firstdemo:latest
[email protected]:/home/cong/DockerDemo# docker run -itd -p 91:80 firstdemo
abd51e5f69b37bc25bbe57d55da41a7bc53fd373c4842d601371956213354261
[email protected]:/home/cong/DockerDemo# curl localhost:91
<h1>hello</h1>
[email protected]:/home/cong/DockerDemo# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
firstdemo latest e16afe49d571 30 seconds ago 109MB
nginx latest dbfc48660aeb 4 weeks ago 109MB
[email protected]:/home/cong/DockerDemo# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
abd51e5f69b3 firstdemo "nginx -g 'daemon of…" 17 seconds ago Up 16 seconds 0.0.0.0:91->80/tcp heuristic_panini
常用命令的講解
FROM
FROM 是用於指定基礎的 images ,一般格式為 FROM 。所有的 Dockerfile 都應該以 FROM 開頭,FROM 命令指明 Dockerfile 所建立的映象檔案以什麼映象為基礎,FROM 以後的所有指令都會在 FROM 的基礎上進行建立映象。可以在同一個 Dockerfile 中多次使用 FROM 命令用於建立多個映象。
MAINTAINER
MAINTAINER 是用於指定映象建立者和聯絡方式,一般格式為 MAINTAINER。
COPY
COPY 是用於複製本地主機的(為 Dockerfile 所在目錄的相對路徑)到容器中的。當使用本地目錄為源目錄時,推薦使用 COPY 。一般格式為 COPY。例如我們要拷貝當前目錄到容器中的 /app 目錄下,我們可以這樣操作:COPY ./app
WORKDIR
WORKDIR 用於配合 RUN,CMD,ENTRYPOINT 命令設定當前工作路徑。可以設定多次,如果是相對路徑,則相對前一個 WORKDIR 命令。預設路徑為/。一般格式為 WORKDIR /path/to/work/dir。
RUN
RUN 用於容器內部執行命令。每個 RUN 命令相當於在原有的映象基礎上添加了一個改動層,原有的映象不會有變化。一般格式為 RUN。例如我們要安裝 Python 依賴包,我們做法如下:RUN pip install -r requirements.txt
EXPOSE
EXPOSE 命令用來指定對外開放的埠。一般格式為 EXPOSE[...]。例如上面那個例子,開放80埠:EXPOSE 80
ENTRYPOINT
ENTRYPOINT 可以讓你的容器表現得像一個可執行程式一樣。一個 Dockerfile 中只能有一個 ENTRYPOINT,如果有多個,則最後一個生效。
ENTRYPOINT 命令也有兩種格式:
-
ENTRYPOINT ["executable", "param1", "param2"] :推薦使用的 Exec 形式。
-
ENTRYPOINT command param1 param2 :Shell 形式。
CMD
CMD 命令用於啟動容器時預設執行的命令,CMD 命令可以包含可執行檔案,也可以不包含可執行檔案。
不包含可執行檔案的情況下就要用 ENTRYPOINT 指定一個,然後 CMD 命令的引數就會作為 ENTRYPOINT 的引數。
CMD 命令有三種格式:
-
CMD ["executable","param1","param2"]:推薦使用的 exec 形式。
-
CMD ["param1","param2"]:無可執行程式形式。
-
CMD command param1 param2:Shell 形式。
一個 Dockerfile 中只能有一個 CMD,如果有多個,則最後一個生效。而 CMD 的 Shell 形式預設呼叫 /bin/sh -c 執行命令。
CMD 命令會被 Docker 命令列傳入的引數覆蓋:docker run nginx /bin/echo Hello Docker 會把 CMD 裡的命令覆蓋。
例子2
看下面的命令
[email protected]:/home/cong# cat Dockerfile
FROM ubuntu
MAINTAINER Jason "[email protected]"
ENV REFRESHED_AT 2018-11-14
#更新資源庫
RUN apt-get -yqq update
#安裝curl
RUN apt-get install iputils-ping -y
#安裝ifconfig
RUN apt-get install net-tools -y
RUN echo aaaa
CMD echo bbbbb
CMD echo ccccc
ENTRYPOINT hostname
[email protected]:/home/cong# docker build -t second .
Sending build context to Docker daemon 10.56MB
Step 1/10 : FROM ubuntu
latest: Pulling from library/ubuntu
Status: Downloaded newer image for ubuntu:latest
---> ea4c82dcd15a
Step 2/10 : MAINTAINER Jason "[email protected]"
---> Running in fae67d94ec2d
Removing intermediate container fae67d94ec2d
---> e7f2fd8da425
Step 3/10 : ENV REFRESHED_AT 2018-11-14
---> Running in a252947b9ff0
Removing intermediate container a252947b9ff0
---> 9f578f16661d
Step 4/10 : RUN apt-get -yqq update
---> Running in ee0f56995d2b
Removing intermediate container ee0f56995d2b
---> 84eb3d468051
Step 5/10 : RUN apt-get install iputils-ping -y
---> Running in e78b3707f5d0
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Removing intermediate container e78b3707f5d0
---> ace6ee693276
Step 6/10 : RUN apt-get install net-tools -y
---> Running in 8a0e627277ed
Reading package lists...
Building dependency tree...
Reading state information...
The following NEW packages will be installed:
net-tools
0 upgraded, 1 newly installed, 0 to remove and 5 not upgraded.
Need to get 194 kB of archives.
After this operation, 803 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 net-tools amd64 1.60+git20161116.90da8a0-1ubuntu1 [194 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 194 kB in 2s (89.6 kB/s)
Selecting previously unselected package net-tools.
(Reading database ... 4081 files and directories currently installed.)
Preparing to unpack .../net-tools_1.60+git20161116.90da8a0-1ubuntu1_amd64.deb ...
Unpacking net-tools (1.60+git20161116.90da8a0-1ubuntu1) ...
Setting up net-tools (1.60+git20161116.90da8a0-1ubuntu1) ...
Removing intermediate container 8a0e627277ed
---> 639597a35e80
Step 7/10 : RUN echo aaaa
---> Running in 8507b4f441ab
aaaa
Removing intermediate container 8507b4f441ab
---> 5d4d0e9d04c9
Step 8/10 : CMD echo bbbbb
---> Running in 8547b9d26a38
Removing intermediate container 8547b9d26a38
---> 04b07e79a65a
Step 9/10 : CMD echo ccccc
---> Running in dca4181b0c76
Removing intermediate container dca4181b0c76
---> 885f695315c9
Step 10/10 : ENTRYPOINT hostname
---> Running in ec1672da6ab5
Removing intermediate container ec1672da6ab5
---> b2d4ae15cf42
Successfully built b2d4ae15cf42
Successfully tagged second:latest
[email protected]:/home/cong# docker run -it second
dafc85f4d1c8
#這裡面後面加echo ddddd不起作用,因為entrypoint 指定的是uname,在uname可執行程式下,不能執行echo
[email protected]:/home/cong# docker run -it second echo ddddd
554f4d2e53f3
可以看出上面的 RUN aaaaa,在build時被打印出來了,說明run是用於容器內容的執行命令,但CMD echo bbbbb和CMD echo cccc在任何條件下都沒有被打印出來,因為它被entrypoint覆蓋了,我們直接run之後,可以看到它執行了entrypoint裡的hostname命令。
我們嘗試修改一下,將entrypoint刪除後,再執行,得出如下結果,說明CMD的最後一個命令被執行了。
[email protected]:/home/cong# cat Dockerfile
FROM ubuntu
MAINTAINER Jason "[email protected]"
ENV REFRESHED_AT 2018-11-14
#更新資源庫
RUN apt-get -yqq update
#安裝curl
RUN apt-get install iputils-ping -y
#安裝ifconfig
RUN apt-get install net-tools -y
RUN echo aaaa
CMD echo bbbbb
CMD echo ccccc
[email protected]:/home/cong# docker build -t second .
[email protected]:/home/cong# docker run -it second
ccccc
#這裡dockerfile裡面的 cmd命令都被覆蓋了
[email protected]:/home/cong# docker run -it second echo ddddd
ddddd
我們重新將Entrypoint 加入,並指定/bin/bash,作為可執行程式
[email protected]:/home/cong# cat Dockerfile
FROM ubuntu
MAINTAINER Jason "[email protected]"
ENV REFRESHED_AT 2018-11-14
#更新資源庫
RUN apt-get -yqq update
#安裝curl
RUN apt-get install iputils-ping -y
#安裝ifconfig
RUN apt-get install net-tools -y
RUN echo aaaa
CMD echo bbbbb
CMD echo ccccc
ENTRYPOINT /bin/bash
[email protected]:/home/cong# docker build -t second .
[email protected]:/home/cong# docker run -it second
# 直接進入了容器裡的bash命令終端
[email protected]:/#
講到這裡,其實還有一些其他的命令,參考如下連結