講一個簡單的案例
@哈希碼用來校驗,這樣子會安全
MAINTANIER可能將會被LABEL代替,僅僅說說明一下鏡像信息罷了。
1、首先是我們創建一個鏡像
[root@ELK-chaofeng08 ~]# mkdir /docker [root@ELK-chaofeng08 ~]# cd /docker [root@ELK-chaofeng08 docker]# vim Dockerfile
輸入以下內容:
#Description: httpd image FROM busybox:latest MAINTAINER "ChaoFeng <chaofeng@qq.com>" COPY index.html /data/web/html
正文的第一行必須是FROM開頭。#號表示注釋。
CPOY命令是復制一個文件,index.html這個文件必須與Dockerfile這個文件同級存放或者在子目錄下也可以。
不過我在這里踩坑了,因為我的COPY那一行寫錯了。
正確的是:
2、接下來我們創建index.html
[root@ELK-chaofeng08 docker]# echo "How are you" > index.html [root@ELK-chaofeng08 docker]# cat index.html How are you [root@ELK-chaofeng08 docker]# ls Dockerfile index.html
3、然后創建目標目錄
[root@ELK-chaofeng08 docker]# mkdir -pv /data/web/html mkdir: created directory ‘/data/web’ mkdir: created directory ‘/data/web/html’
4、開始制作鏡像。
制作的時候最好加上標簽
5、查看一下我們制作的新鏡像
6、啟動一下看看。
這個指令的用法是最常見的。
[root@ELK-chaofeng08 docker]# docker run --name tinyweb1 --rm tinyhttpd:v0.1.1 cat /data/web/html/index.html How are you [root@ELK-chaofeng08 docker]#
后面的cat指令是EXEC的指令,也就是說我們一啟動容器后不運行默認的命令,而是運行我們指定的cat命令,運行完畢后退出容器,我還設置了--rm參數,表示容器停止后就刪除它。要學會這個用法
看的出來我們成功了。
二、如何復制一個目錄呢?
比如現在我們想把物理機下的/etc/yum.repos.d目錄下的所有文件復制到容器內的/etc/yum.repos.d/的目錄下
1、先把物理機下的/etc/yum.repos.d這個目錄復制到Dockerfile同級的目錄下(子目錄下也行)
[root@ELK-chaofeng08 docker]# cp -r /etc/yum.repos.d ./ [root@ELK-chaofeng08 docker]# ls Dockerfile index.html yum.repos.d
2、編輯Dockerfile文件
COPY可以用多個。COPY命令的用法原則是能用一條來代替就不要用多條,因為每一個COPY命令就會生成一個鏡像層。層越多,聯合掛載效率越低。
3、開始制作
4、查看一下新的鏡像
5、查看一下新的鏡像下是否有新的文件
說明成功了。
三、ADD命令的用法,
1、編輯Dockerfile文件
2、制作新的鏡像
3、查看新的鏡像
4、查看新的鏡像下的nginx的tar包
成功了。
四、ADD命令的解壓功能。
ADD命令不僅可以從互聯網下載文件(壓縮文件,普通文件等)並放入新的鏡像內,還可以根據壓縮文件的類型選擇算法實現解壓操作,如下所示:
1、首先是壓縮文件必須是放在本地才可以。
我們以phpmyadmin文件為例
2、編輯Dockerfile文件
3、開始制作鏡像
4、查看新的鏡像下的phpmyadmin的展開文件
成功。
注意:ADD命令可以從指定的URL向互聯網下載各種類型的文件到新鏡像,也可以將一個壓縮文件解壓放入新的鏡像,但是不能同時既進行下載tar壓縮文件又進行壓縮tar文件到新鏡像里面。
五、指定WORKDIR目錄路徑
六、指定存儲卷
不過只能指定docker自己管理的卷,不能指定我們綁定的外部卷的存儲路徑
比如:
七、暴露端口給外部的宿主機
相當於自動幫我們生成一個DNAT端口。跟以前的-p參數一樣的功能。
不過用法也比較限制,只能動態綁定宿主機的動態端口到容器的固定端口。不能綁定指定宿主的ip和指定的端口。但是這有時候也是一種安全的機制。
案例:
因為第一次我們編輯了一個index.html文件,在/data/web/html目錄下存放這,我們直接使用這個文件,。
1、編輯dockerfile文件
2、重新制作新的鏡像
3、查看這個新鏡像
4、啟動這個新鏡像
5、我們去查看這個容器的ip
6、訪問一下這個容器的80端口
非常好。成功
像這種在配置文件中暴露的端口在外部是看不到的,這是半暴露狀態,如果想要全部暴露,加上-P參數。比如:
所以我們可以加上-P參數指定為暴露端口給外部
7、加上-P參數
8、再來查看一下
我們就可以在外部訪問了
八、ENV和RUN命令解釋,
RUN命令是Dockerfile文件中的一個可以執行命令的參數,比如:
1、編輯dockerfile文件
2、制作新鏡像
3、啟動新鏡像查看
成功了。
在Dockerfile中定義的環境變量是可以用在容器啟動以后引用的變量
注意:RUN命令是可以運行多次的。后面的命令可以使用“\”表示續行。所有的RUN操作是基於基礎鏡像的,因此要注意環境。
九、CMD和ENTRYPOINT
注意:json數組要使用雙引號。
ENTRYPOINT 兩種格式: ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2 (shell中執行) 配置容器啟動后執行的命令,並且不可被 docker run 提供的參數覆蓋。每個 Dockerfile 中只能有一個 ENTRYPOINT ,當指定多個時,只有最后一個起效。 CMD 支持三種格式 CMD ["executable","param1","param2"] 使用 exec 執行,推薦方式; CMD command param1 param2 在 /bin/bash 中執行,提供給需要交互的應用; CMD ["param1","param2"] 提供給 ENTRYPOINT 的默認參數; 指定啟動容器時執行的命令,每個 Dockerfile 只能有一條 CMD 命令。如果指定了多條命令,只有最后一條會被執行。如果用戶啟動容器時候指定了運行的命令,則會覆蓋掉 CMD 指定的命令。
ENTRYPOINT 和 CMD 的區別:ENTRYPOINT 指定了該鏡像啟動時的入口,CMD則指定了容器啟動時的命令,當兩者共用時,完整的啟動命令像是 ENTRYPOINT + CMD 這樣。使用 ENTRYPOINT 的好處是在我們啟動鏡像就像是啟動了一個可執行程序,在 CMD 上僅需要指定參數;另外在我們需要自定義 CMD 時不容易出錯。
使用 CMD 的 Dockerfile:
[root@sta2 test]# cat Dockerfile FROM mysql CMD ["echo","test"]
使用 ENTRYPOINT 的 Dockerfile:
[root@sta2 entrypoint]# cat Dockerfile FROM mysql ENTRYPOINT ["echo","test"]
結論:ENTRYPOINT 不能覆蓋掉執行時的參數,CMD 可以掉覆蓋默認的參數。

可以使用以下命令覆蓋默認的參數,方便調試 Dockerfile 中的 bug:[root@sta2 entrypoint]# docker run -it --entrypoint=/bin/bash feiyu/entrypoint:1
案例演示:
制作一個nginx(重點掌握)
1、先制作Dockerfile文件
FROM nginx:1.14-alpine
LABEL maintainer="Chaofeng <chaofeng@chaofeng.com>"
ENV NGX_DOC_ROOT='/data/web/html/'
ADD entrypoint.sh /bin/
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
2、制作entrypoint.sh文件
#!/bin/sh cat > /etc/nginx/conf.d/www.conf << EOF server{ server_name ${HOSTNAME}; listen ${IP:-0.0.0.0}:${PORT:-80}; root ${NGX_DOC_ROOT:-/usr/share/nginx/html}; } EOF exec "$@"
3、給entrypoint.sh文件授權
chmod +x entrypoint.sh
4、制作docker鏡像
[root@ELK-chaofeng08 docker3]# docker build -t tinyweb:v0.3.2 ./ Sending build context to Docker daemon 3.072kB Step 1/6 : FROM nginx:1.14-alpine ---> 66952fd0a8ef Step 2/6 : LABEL maintainer="Chaofeng <chaofeng@chaofeng.com>" ---> Using cache ---> 9b06b920ce9b Step 3/6 : ENV NGX_DOC_ROOT='/data/web/html/' ---> Using cache ---> 9346cf0174b9 Step 4/6 : ADD entrypoint.sh /bin/ ---> c8f80cdc1321 Step 5/6 : CMD ["/usr/sbin/nginx","-g","daemon off;"] ---> Running in 20bace9c162d Removing intermediate container 20bace9c162d ---> 4cbfa737e80f Step 6/6 : ENTRYPOINT ["/bin/entrypoint.sh"] ---> Running in babe021b35b9 Removing intermediate container babe021b35b9 ---> b474e7c54539 Successfully built b474e7c54539 Successfully tagged tinyweb:v0.3.2
5、啟動鏡像
[root@ELK-chaofeng08 docker3]# docker run --name tinyweb1 --rm -P tinyweb:v0.3.2
6、在另一終端查看進程
[root@ELK-chaofeng08 docker3]# docker exec -it tinyweb1 /bin/sh / # ps PID USER TIME COMMAND 1 root 0:00 nginx: master process /usr/sbin/nginx -g daemon off; 8 nginx 0:00 nginx: worker process 9 root 0:00 /bin/sh 14 root 0:00 ps
我們在Dockerfile文件中使用腳本的方式進行傳值,我們執行ENTRYPOINT的時候使用的是數組的形式,意思就是把CMD的元素當作是一個個的參數傳給ENTRYPOINT,首先是在創建完entrypoint.sh腳本的時候,執行最后一句exec操作,這是把當前nginx的進程作為主進程來執行,因此在這里的ps命令中看到nginx的主進程的PID號是1。
我們設計成腳本的方式是比較好傳值的,省去了修改某個參數時重新制作鏡像的麻煩,為什么這么說呢?比如下面這個例子:
[root@ELK-chaofeng08 docker3]# docker exec -it tinyweb1 /bin/sh / # netstat -tnl Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
此時正好是運行在80端口。
假如此時我想運行在8080端口怎么辦呢?可以這樣子來
[root@ELK-chaofeng08 docker3]# docker run --name tinyweb1 --rm -P -e 'PORT=8080' tinyweb:v0.3.2
使用-e參數,表示啟動容器的時候使用作為環境變量傳入
再打開一個終端執行如下:
[root@ELK-chaofeng08 docker3]# docker exec -it tinyweb1 /bin/sh / # netstat -tnl Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
不僅運行在了默認的80端口,還運行在了8080端口,非常的方便。這就是腳本傳值的作用。這里還要理解entrypoint.sh有個“${PORT:-80}”是什么意思呢?就是如果環境中有默認的PORT的值,那么此時PORT就有值然后就使用默認的值,如果沒有值,則使用80端口。那么至於為什么上面還會有80端口呢?這是因為nginx還有自己主配置文件的默認端口是80端口(不要搞混淆了)。
十、HEALTHCHECK檢測
案例演示
在dockerfile中加入如下內容:
然后制作一個新的鏡像並啟動
每隔默認的30s檢測一次是否成功。
十一、在docker build階段傳遞參數ARG
案例:
修改dockerfile
然后構建鏡像時傳值
需要注意的是,我們之前學習的命令中傳遞環境變量參數的時候,使用的都是docker run操作,但是如果我們想在docker build階段傳入參數的值,則要是有docker build –build-tag參數了。
十二、ONBUILD