Docker基礎 6.DockerFile
Docker基礎
@Author:hanguixian
@Email:[email protected]
Docker文件:https://docs.docker.com/
Dcker中文文件:https://docs.docker-cn.com/
六.DockerFile
1.是什麼
Dockerfile是用來構建Docker映象的構建檔案, 是由一系列命令和引數構成的指令碼。
構建三步驟
- 1.編寫DokcerFile檔案
- 2.docker build
- 3.docker run
檔案什麼樣?
FROM scratch MAINTAINER https://github.com/CentOS/sig-cloud-instance-images ADD centos-7-docker.tar.xz / LABEL name="CentOS Base Image" \ vendor="CentOS" \ license="GPLv2" \ build-date="20161214" CMD ["/bin/bash"]
2.DockerFile構建過程解析
Dockerfile內容基礎知識
- 每條保留字指令都必須為大寫字母且後面要跟隨至少一個引數\
- 指令按照從上到下,順序執行
- #表示註釋
- 每條指令都會建立一個新的映象層,並對映象進行提交
docker執行Dockerfile的大致流程
- (1) docker從基礎映象執行一個容器
- (2)執行一條指令並對容器作出修改
- (3) 執行類似docker commit的操作提交一個新的映象層
- (4) docker再基於剛提交的映象執行一個新容器
- (5) 執行dockerfile中的下一條指令直到所有指令都執行完成
總結
從應用軟體的角度來看,Dockerfile、 Docker映象與Docker容器分別代表軟體的三個不同階段
Dockerfile是軟體的原材料Docker映象是軟體的交付品
Docker容器則可以認為是軟體的執行態。
Dockerfile面向開發,Docker映象成為交付標準,Docker容器則涉及部署與運維,三者缺一不可,合力充當Docker體系的基石。
1 Dockerfile, 需要定義一個Dockerfile, Dockerfile定義了程序需要的一切東西。Dockerfile涉及的內容包括執行程式碼或者是檔案、環境變數、依賴包、執行時環境、動態連結庫、作業系統的發行版、服務程序和核心程序(當應用程序需要和系統服務和核心程序打交道,這時需要考慮如何設計namespace的許可權控制)等等;
- 2 Docker映象,在用Dockerfile定義一個檔案之後,docker build時會產生一個Docker映象, 當執行Docker映象時,會真正開始提供服務;
- 3 Docker容器,容器是直接提供服務的。
3.DockerFile體系結構(保留字指令)
FROM
基礎映象,當前新映象是基於哪個映象的MAINTAINER
映象維護者的姓名和郵箱地址RUN
容器構建時需要執行的命令EXPOSE
當前容器對外暴露出的埠WORKDIR
指定在建立容器後,終端預設登陸的進來工作目錄,一個落腳點ENV
用來在構建映象過程中設定環境變數口- ENV MY_ PATH /usr/mytest 這個環境變數可以在後續的任何RUN指令中使用,這就如同在命令前面指定了環境變數字首一樣; 也可以在其它指令中直接使用這些環境變數, 比如: WORKDIR $MY_ PATH
ADD
將宿主機目錄下的檔案拷貝進映象且ADD命令會自動處理URL和解壓tar壓縮包COPY
- 類似ADD,拷貝檔案和目錄到映象中。
- 將從構建上下文目錄中<源路徑>的檔案/目錄複製到新的一層的映象內的<目標路徑>位置
- COPY src dest COPY
- COPY [“sre”, “dest”]
VOLUME
容器資料卷,用於資料儲存和持久化工作CMD
- 指定一個容器啟動時要執行的命令
- CMD容器啟動命令:CMD指令的格式和RUN相似,也是兩種格式
- shell 格式: CMD<命令>
- exec 格式: CMD [“可執行檔案”,”引數1”,”引數2”,…]
- 引數列表: CMD [“引數1”,”引數2”,..] ,在指定了ENTRYPOINT指令後,用CMD指定具體的引數
- Dockerfile中可以有多個CMD指令,但只有最後一個生效,CMD會被docker run之後的引數替換
ENTRYPOINT
- 指定一個容器啟動時要執行的命令
- ENTRYPOINT的目的和CMD一樣,都是在指定容器啟動程式及引數
ONBUILD
當構建一個被繼承的Dockerfle時執行命令,父映象在被子繼承後父映象的onbuild被觸發總結
4.案例
4.1Base映象scratch
- Dokcer hub中99%的映象都是在base映象中安裝和配置需要的軟體構建出來的
4.2自定義映象mycentos
編寫
Hub預設Centos映象什麼情況
初始化centos執行該映象進入是預設路徑是/
- 預設不支援vim
預設不支援ifconfig
準備編寫DokcerFile檔案
自定義mycentos目的,使我們的自己的映象具備如下:
- 登陸後的預設路徑
- vim編輯器
- ifconfig查詢網路配置
建立檔案並編輯:
vim DockerFile2
myCentOS內容DokcerFile
FROM centos MAINTAINER hanguixian<[email protected]163.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 -f /mydocker/DockerFile2 -t mycentos:1.3 .
檢視:
docker images
[root@iZuf64yofkbhp8tm0ackshZ mydocker]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mycentos 1.3 d70dd7d1c9d0 About a minute ago 371MB centos latest 5182e96772bf 3 weeks ago 200MB
- 可以看到有了mycentos映象,同時和原來的centos映象大小有了明顯的區別
執行
- 命令: dcoker run -it mycnetos:1.3
[[email protected] mydocker]# docker run -it mycentos:1.3 [[email protected]9f936361751f local]# pwd /usr/local
可以看到預設的路徑是:/usr/local
驗證vim,ifconfig,可以看到我們修改的映象
列出映象的變更歷史
命令 : docker history 映象名或映象IMAGE ID
例子:docker history d70dd7d1c9d0 或 docker history mycentos:1.3
[[email protected] mydocker]# docker history mycentos:1.3
IMAGE CREATED CREATED BY SIZE
d70dd7d1c9d0 25 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
fa82ffb7c68b 25 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
353215faa466 25 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
34a9a9b7c41d 25 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
8803a34e02ea 25 minutes ago /bin/sh -c yum -y install net-tools 22.4MB
0effdb62c656 25 minutes ago /bin/sh -c yum -y install vim 149MB
5a83aca44197 25 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
e8b15471d355 26 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
d99ee0589704 26 minutes ago /bin/sh -c #(nop) MAINTAINER hanguixian<hn_… 0B
5182e96772bf 3 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:6340c690b08865d7e… 200MB
4.3CMD/ENTRYPOINT 映象案例
都是指定一個容器啟動時要執行的命令
CMD
Dockerfile中可以有多個CMD指令,但只有最後一個生效,CMD會被
docker run
之後的引數替換如tomcat:dockerfile最後有:
CMD ["catalina.sh", "run"]
我們用:
docker run -it -p 7777:80 tomcat
能啟動tomcat,可以看到列印的日誌如果使用:
docker run -it -p 7777:80 tomcat ls -l
tomcat沒有啟動起來[[email protected] mydocker]# docker run -it -p 7777:80 tomcat ls -l total 152 -rw-r----- 1 root root 19533 Aug 12 08:23 BUILDING.txt -rw-r----- 1 root root 6090 Aug 12 08:23 CONTRIBUTING.md -rw-r----- 1 root root 57092 Aug 12 08:23 LICENSE -rw-r----- 1 root root 1726 Aug 12 08:23 NOTICE -rw-r----- 1 root root 3255 Aug 12 08:23 README.md -rw-r----- 1 root root 7140 Aug 12 08:23 RELEASE-NOTES -rw-r----- 1 root root 16262 Aug 12 08:23 RUNNING.txt drwxr-x--- 2 root root 4096 Aug 23 00:47 bin drwx--S--- 2 root root 4096 Aug 12 08:23 conf drwxr-sr-x 3 root staff 4096 Aug 23 00:47 include drwxr-x--- 2 root root 4096 Aug 23 00:47 lib drwxr-x--- 2 root root 4096 Aug 12 08:20 logs drwxr-sr-x 3 root staff 4096 Aug 23 00:47 native-jni-lib drwxr-x--- 2 root root 4096 Aug 23 00:47 temp drwxr-x--- 7 root root 4096 Aug 12 08:21 webapps drwxr-x--- 2 root root 4096 Aug 12 08:20 work [[email protected] mydocker]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 相當於:
CMD ["catalina.sh", "run"]
被ls -l
替換掉了
CMD ["catalina.sh", "run"] CMD ls -l
- 相當於:
ENTRYPOINT
docker run
之後的引數會被稻作引數傳遞給ENTRYPOINT,之後形成新的命令組合- Case
crul命令解釋:
- curl命令可以用來執行下載、傳送各種HTTP請求,指定HTTP頭部等操作。
- 如果系統沒有curl可以使用yum install curl安裝,也可以下載安裝。
- curl是將下載檔案輸出到stdout
- 使用命令: curl http://www.baidu.com 執行後,www.baidu.com的html就會顯示在螢幕上了.這是最簡單的使用方法。用這個命令獲得了http://curl.haxx.se指向的頁面.
- 如果這裡的URL指向的是一個檔案或者一幅圖都可以直接下載到本地。如果下載的是HTML文件,那麼預設的將只顯示檔案頭部,即HTML文件的header。要全部顯示,請加引數-i
製作CMD版可以查詢ip資訊的容器
- vim DockerFile3
FROM centos RUN yum install -y curl CMD ["curl","-s","http://ip.cn"]
- 構建
docker build -f /mydocker/DockerFile3 -t myip .
[email protected] mydocker]# docker build -f /mydocker/DockerFile3 -t myip . Sending build context to Docker daemon 4.096kB Step 1/3 : FROM centos ---> 5182e96772bf Step 2/3 : RUN yum install -y curl ---> Running in c50d2b39b009 Loaded plugins: fastestmirror, ovl Determining fastest mirrors * base: ftp.sjtu.edu.cn * extras: ftp.sjtu.edu.cn * updates: ftp.sjtu.edu.cn Package curl-7.29.0-46.el7.x86_64 already installed and latest version Nothing to do Removing intermediate container c50d2b39b009 ---> bcb77c235890 Step 3/3 : CMD ["curl","-s","http://ip.cn"] ---> Running in 9a8447179feb Removing intermediate container 9a8447179feb ---> 4780e697e548 Successfully built 4780e697e548 Successfully tagged myip:latest
- 執行:
docker run myip
- 輸出: 當前 IP:xxxx 來自:xxxxx
問題
- 如果要顯示Http頭資訊,就需要加上引數 -i
WHY
- 執行docker run myip -i ,相當於在
CMD ["curl","-s","http://ip.cn"]
後面,加上CMD -i
- 我們可以看到可執行檔案找不到的報錯,executable file not found。跟在映象名後面的是command,執行時會替換CMD的預設值。
- 因此這裡的-i替換了原來的CMD,而不是新增在原來的
curl -s http://ip.cn
後面。而-i根本不是命令,所以自然找不到。 - 那麼如果我們希望加入-i這引數,我們就必須重新完整的輸入這個命令:
docker run myip curl -s http://ip.cn -i
- 執行docker run myip -i ,相當於在
製作ENTRYPOINT版可以查詢ip資訊的容器
- vim DockerFile4
FROM centos RUN yum install -y curl ENTRYPOINT ["curl","-s","http://ip.cn"]
- 構建
docker build -f /mydocker/DockerFile4 -t myip2
- 執行
dokcer run myip2 -i
[r[email protected] mydocker]# docker run myip2 -i HTTP/1.1 200 OK Date: Tue, 28 Aug 2018 04:28:37 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: keep-alive Set-Cookie: __cfduid=d762232cds1acd1cd4328e662d6dbb13990ede35430517; expires=Wed, 28-Aug-19 04:28:37 GMT; path=/; domain=.ip.cn; HttpOnly Server: cloudflare CF-RAY: 4we9e87vv8b63c5426-LAX 當前 IP:xxxxx 來自:xxxx
4.4 ONBUILD
當構建一個被繼承的Dockerfle時執行命令,父映象在被子繼承後父映象的onbuild被觸發了
例子:
- vim Dockerfile_father
FROM centos RUN yum install -y curl ENTRYPOINT ["curl","-s","http://ip.cn"] ONBUILD RUN echo "father onbuild ....."
docker build -f /mydocker/Dockerfile_father -t myip_father .
vim Dockerfile_son
FROM myip_father RUN yum install -y curl ENTRYPOINT ["curl","-s","http://ip.cn"]
docker build -f /mydocker/Dockerfile_son -t myip_son .
- 會有下面這句話,可以看到ONBUILD被觸發
# Executing 1 build trigger ---> Running in f3e46b30c6fa father onbuild .....
4.5自定義映象Tomcat8
- 準備
- 在 /mydocker:
touch hgxDockerFile
- vim c.txt
- 下載java8和tomcat8.5到/mydocker下:
- 在 /mydocker:
[[email protected] mydocker]# ll
total 190728
-rw-r--r-- 1 root root 9621331 Aug 28 17:28 apache-tomcat-8.5.33.tar.gz
-rw-r--r-- 1 root root 17 Aug 28 17:49 c.txt
-rw-r--r-- 1 root root 1048 Aug 28 18:01 hgxDockerFile
-rw-r--r-- 1 root root 185646832 Aug 28 17:30 jdk-8u181-linux-x64.tar.gz
- dockerfile編寫:
FROM centos
MAINTAINER hanguixian<hn_hanguixian@163.com>
#把宿主機當前上下文的c.txt拷貝到容器/usr/local/路徑下
COPY c.txt /usr/local/cincontainer.txt
#把java與tomcat新增到容器中
ADD jdk-8u181-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.33.tar.gz /usr/local/
#安裝vim編輯器
RUN yum -y install vim
#設定工作訪問時候的WORKDIR路徑,登入落腳點
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java與tomcat環境境變數
ENV JAVA_HOME /usr/local/jdk1.8.0_181
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.33
ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.33
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
#容器執行時監聽的埠
EXPOSE 8080
#啟動時執行tomcat
#ENTRYPOINT「"/usr/local/apache-tomcat-8.5.33/bin/startup.sh"]
#CMD["/usr/local/apache-tomcat-8.5.33/bin/catalina.sh","run"l
CMD /usr/local/apache-tomcat-8.5.33/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.33/logs
catalina.out
- 構建 :
docker build -f hgxDockerFile -t hgxtomcat8 .
- 執行:
docker run -d -p 8888:8080 --name myt8 -v /hanguixian/mydockerfile/tomcat8/test:/usr/local/apache-tomcat-8.5.33/webapps/test -v /hanguixian/mydockerfile/tomcat8/tomcat8logs/:/usr/local/apache-tomcat-8.5.33/logs --privileged=true hgxtomcat8
可以看到有tomcat啟動:
結合前面的容器卷將測試web服務test釋出
在 /hanguixian/mydockerfile/tomcat8/test下:
vim index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>docker test</title> </head> <body> <%= "I am docker tomcat self" %> <h2>釋出一個docker jsp</h2> <% System.out.println("docker tomcat self"); %> </body> </html>
mkdir WEB-INF
- cd WEB-INF
- vim web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> </web-app>
訪問 : xxxx:8888/test/index.jsp