Dockfile制作鏡像


講一個簡單的案例

@哈希碼用來校驗,這樣子會安全

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM