文章目錄
- 一.為什么要學習自動構建鏡像
- 1.為什么要學習自動化構建鏡像
- 2.根據dockerfile自動構建鏡像的流程
- 3.常用的dockerfile指令
- 二.使用dockerfile構建nginx服務鏡像(FR0M,RUN,CMD)
- 1.創建dockerfile的存儲路徑
- 2.編寫dockerfile文件
- 3.構建docker鏡像(在執行此步驟之前,請先看完第6步驟的說明,然后再返回來繼續執行!)
- 4.基于構建的docker鏡像啟動容器
- 5.測試容器的運行
- 6.RUN指令運行原理
- 7.清除臨時鏡像
- 8.使用Ubuntu制作小鳥飛飛鏡像實戰案例
- 9.使用alpine制作小鳥飛飛鏡像及VOLUME指令實戰案例
- 三.使用dockerfile構建"小鳥飛飛飛" 服務鏡像(FROM,RUN,ADD,COPY,WORKDIR,EXPOSE,VOLUME)
- 1.對"小鳥飛飛飛" 的游戲項目目錄進行打包
- 2.編寫docker文件
- 3.編譯dockerfile文件
- 4.驗證鏡像
- 5.進階案例(WORKDIR,EXPORT,VOLUME)
- 6.啟動容器驗證鏡像是否生效
- 四.使用dockerfile構建alpine基礎鏡像(FROM,ADD,CMD)
- 1.下載已經打包好的Linux文件系統
- 2.解壓并刪除rootfs.tar.xz軟件包
- 3.修改Linux發行版本
- 4.重新打包文件系統鏡像
- 5.編寫dockerfile并編譯
- 6.啟動docker鏡像并測試
- 五.使用dockfile構建nginx+ssh雙服務的鏡像
- 1.編寫服務的啟動腳本
- 2.編寫dockerfile(建議基于自定義的nginx鏡像構建sshd服務)
- 3.啟動容器
- 4.優化dockerfile的編寫
- 5.基于alpine完成多服務鏡像案例,體積減20倍以上:star:
- 六.使用ENV指令給容器傳遞變量
- 1.編寫容器的啟動腳本
- 2.編寫并編譯dockerfile
- 3.啟動容器時傳遞環境變量而定制root密碼
- 4.本案例dockerfile存在的問題
- 5.編寫dockerfile
- 6.驗證ENV指令是否生效
- 七.使用ENTRYPOINT指令案例啟動容器(注意和CMD指令進行對比)
- 1.編寫dockerfile并進行編譯
- 2.啟動容器
- 3.dockerfile的ENV指令和ENTRYPOINT指令實戰案例
- 八.其它指令(了解即可)
- 1.MAINTAINER (deprecated)
- 2.LABEL
- 3.其它指令
- 九.docker鏡像分層
- 1.導出鏡像并拷貝到其它節點進行測試
- 2.先導入centos鏡像,然后再導入nginx鏡像
- 3.先導入nginx鏡像,再導入centos鏡像
- 4.docker鏡像分層概述
- 5.容器和鏡像的關系-寫時復制(copy-on-write,簡稱COW)技術
- 十.聯合文件系統(UnionFS)
- 1.什么是聯合文件系統(UnionFS)
- 2.AUFS概述
- 3.創建測試文件
- 4.測試讀寫層的文件
- 5.推薦閱讀
- 十一.dockerfile的優化
- 1.dockerfile的優化原則
- 2.體驗alpine案例
- 3.刪除無用緩存,合并多條run指令案例(演示的時候建議分別使用3臺干凈的docker環境測試)
- 4.修改dockerfile的時候,盡可能把修改的內容放在最后,這樣可以充分利用緩存鏡像
- 5.使用".dockerignore"忽略構建docker鏡像時不需要的文件,從而減小鏡像體積
- 十二.可能會遇到的報錯
- 1.sshd re-exec requires execution with an absolute path
- 2.sshd: no hostkeys available -- exiting.
- 3.Add correct host key in /root/.ssh/known_hosts to get rid of this message.
- 小的,創作不容易。給個點點關注
- 多多少少給點吧
一.為什么要學習自動構建鏡像
1.為什么要學習自動化構建鏡像
通過前面的學習,發現手動制作鏡像相對來說比較還是比較麻煩的。尤其是在需要對現有鏡像進行修改時,非常的費勁。手動構建鏡像不僅僅是在操作上比較麻煩,在傳輸上也很占用帶寬,如果鏡像中使用的軟件包較小也就罷了,但如果文件較多的話就比較麻煩了,因為這可能傳輸一個鏡像會占用上GB的帶寬喲。綜上所述,我們手動制作鏡像有以下缺陷:(1)占用存儲空間;(2)占用帶寬;(3)修改比較繁瑣;我們很需要一個傳輸占用帶寬較少且構建比較方便的方式來構建咱們的鏡像,這就是我們今天要介紹的主角,即dockerfile。
2.根據dockerfile自動構建鏡像的流程
鏡像和dockerfile的區別:一說起吃飯,想必大家都不陌生。我們的鏡像就好比一道已經做好的菜,比如"魚香肉絲","宮保雞丁","油悶大蝦","地三鮮"等。而dockerfile的就好比一道菜的做法,我們需要按照做菜的流程才能得到我們想要吃的菜。根據dockerfile自動構建鏡像的大致流程如下:(1)手動制作docker鏡像,記錄歷史命令;(2)根據歷史命令編寫dockerfile文件;(3)docker build構建docker鏡像;(4)測試鏡像的功能;
3.常用的dockerfile指令
FROM:指定自動化構建的基礎鏡像,該指令必須指定。RUN:制作鏡像過程中需要的執行命令,通常用作安裝服務。但不能出現阻塞當前終端的命令。CMD:指定容器啟動的時候需要執行的初始命令,當然,我們也可以在啟動容器的時候替換該命令。ENTRYPOINT:指定容器啟動的時候執行的初始命令,與CMD指令不同,因為它不能被替換。如果啟動指令時強行傳遞三處,則僅能用作ENTRYPOINT指令的參數,并不會替換。如果同時使用CMD和ENTRYPOINT,cmd命令將作為ENTRYPOINT命令的參數。ADD:把dockerfile當前目錄下的文件拷貝到容器中,其會自動解壓tar包。COPY:把dockerfile當前目錄下的文件拷貝到容器中,但并不會解壓tar包喲。WORKDIR:指定容器的默認工作目錄。EXPOSE:指定鏡像要對外暴露的端口。VOLUME:指定隨機的持久化卷。ENV:用于設置環境變量,比如設置sshd,數據庫的root密碼等。LABEL:為鏡像的屬性打標簽。MAINTAINER(官方已廢棄,可能在未來的docker版本中移除它,因此我推薦大家使用更加靈活的LABEL指令):管理者標識。推薦閱讀:https://docs.docker.com/engine/reference/builder/
二.使用dockerfile構建nginx服務鏡像(FR0M,RUN,CMD)
1.創建dockerfile的存儲路徑
[root@docker01 ~]# mkdir -pv /koboid/softwares/dockerfile
[root@docker01 ~]# cd /koboid/softwares/dockerfile
[root@docker01 dockerfile]# mkdir centos7_nginx
[root@docker01 dockerfile]# cd centos7_nginx
#錯誤顯示,"docker build" requires exactly 1 argument.。最少要傳遞一個參數
[root@docker01 centos7_nginx]# docker build
"docker build" requires exactly 1 argument.
See 'docker build --help'.Usage: docker build [OPTIONS] PATH | URL | -Build an image from a Dockerfile溫馨提示:(1)在使用"docker build"構建docker鏡像時,當前目錄沒有Dockerfile則會拋出如下圖所示的錯誤喲;(2)早期版本,我們的dockerfile文件的首字母必須大寫,目前咱們使用的最新版本可以直接忽略;
2.編寫dockerfile文件
[root@docker01 centos7_nginx]# vim dockerfile
[root@docker01 centos7_nginx]# cat dockerfile
# 指定基于哪個鏡像構建咱們的自定義鏡像文件
FROM centos:7# 開始安裝服務
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum -y install nginx
RUN rm -rf /usr/share/nginx/html/index.html
RUN echo 'oldboyedu linux' > /usr/share/nginx/html/index.html# 姿勢一: 比較傳統的啟動容器時需要執行的命令.
# CMD nginx -g 'daemon off;'
# 姿勢二: 推薦執行的命令
CMD ["nginx","-g","daemon off;"]
3.構建docker鏡像(在執行此步驟之前,請先看完第6步驟的說明,然后再返回來繼續執行!)
[root@docker01 centos7_nginx]# ll -a
總用量 4
drwxr-xr-x 2 root root 24 6月 15 21:25 .
drwxr-xr-x 3 root root 27 6月 15 21:06 ..
-rw-r--r-- 1 root root 569 6月 15 21:25 dockerfile
[root@docker01 centos7_nginx]# docker build -t oldboyedu_dockerfile_nginx:v1 .[root@docker01 centos7_nginx]# docker image ls
4.基于構建的docker鏡像啟動容器
[root@docker01 ~]# docker container run -d -p 127.0.0.1:8888:80 buffes_dockerfile_nginx:v1
[root@docker01 ~]# docker container ps -a溫馨提示:我們無需指定COMMAND,因為咱們自己定義的鏡像已經寫好了容器啟動時要執行的CMD。
5.測試容器的運行
[root@docker01 ~]# docker container ps -a
[root@docker01 ~]# curl 127.0.0.1:8888溫馨提示:我們可以直接基于暴露的端口進行訪問即可。
6.RUN指令運行原理
[root@docker01 centos7_nginx]# docker ps -a -l --no-trunc
[root@docker01 centos7_nginx]# docker build -t buffes_dockerfile_nginx:v1 .RUN指令運行原理:當我們每執行一次RUN指令,都意味會新啟動一個容器并將其提交為臨時鏡像,然后再移除臨時容器。這些臨時鏡像我們可以通過"docker image ls -a"指令進行查看,建議定期清除這些臨時鏡像。
7.清除臨時鏡像
[root@docker01 ~]# docker image ls -a溫馨提示:我們在自動構建鏡像的時候,會大量的生成臨時鏡像,其"REPOSITORY"和"TAG"的值均為"<none>"。請不要試圖刪除它們,因為最終鏡像是有依賴關系的!
8.使用Ubuntu制作小鳥飛飛鏡像實戰案例
(1)編寫nginx的主配置文件
cat > nginx.conf <<EOF
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {worker_connections 768;
}
http {sendfile on;tcp_nopush on;tcp_nodelay on;keepalive_timeout 65;types_hash_max_size 2048;include /etc/nginx/mime.types;default_type application/octet-stream;ssl_prefer_server_ciphers on;access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;gzip on;include /etc/nginx/conf.d/*.conf;# include /etc/nginx/sites-enabled/*;
}
EOF(2)編寫小鳥飛飛的配置文件
cat > oldboyedu-bird.conf <<EOF
server {listen 80;root /usr/share/nginx/html;
}
EOF(3)編寫Dockerfile文件
cat > Dockerfile << EOF
FROM ubuntu:20.04RUN sed -i -e 's#archive.ubuntu.com#mirrors.aliyun.com#g' \-e 's#security.ubuntu.com#mirrors.aliyun.com#g' /etc/apt/sources.list && \apt update && \apt -y install nginx && \rm -rf /var/cache/ && \rm -rf /usr/share/nginx/html/*ADD oldboyedu-bird.tar.gz /usr/share/nginx/html/EXPOSE 80 81COPY oldboyedu-bird.conf /etc/nginx/conf.d/COPY nginx.conf /etc/nginx/WORKDIR /usr/share/nginx/html/CMD ["nginx","-g","daemon off;"]
EOF溫馨提示:(1)小鳥飛飛的軟件包發給大家的是zip包,請自行打包為"oldboyedu-bird.tar.gz";(2)暫時先放棄使用ubuntu編譯安裝nginx的想法,因為編譯安裝費力不討好,編譯安裝成功后鏡像大小300M+;
9.使用alpine制作小鳥飛飛鏡像及VOLUME指令實戰案例
(1)nginx主配置文件
cat > nginx.conf <<EOF
user nginx;
worker_processes auto;
pid /run/nginx.pid;events {worker_connections 768;
}http {sendfile on;charset utf-8;include /etc/nginx/mime.types;# default_type application/octet-stream;access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;gzip on;include /etc/nginx/conf.d/*.conf;
}
EOF(2)編寫小鳥飛飛的配置文件
cat > oldboyedu-bird.conf <<EOF
server {listen 80;root /usr/share/nginx/html;
}
EOF(3)編寫dockerfile實戰案例
cat > Dockerfile <<EOF
FROM alpineRUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \apk update && \apk add nginx && \rm -rf /var/cache/COPY nginx.conf /etc/nginx/nginx.confCOPY oldboyedu-bird.conf /etc/nginx/conf.d/EXPOSE 80WORKDIR /usr/share/nginx/htmlADD oldboyedu-bird.tar.gz /usr/share/nginx/html# 將容器的某個目錄進行持久化!會自動生成隨機存儲卷!
VOLUME /usr/share/nginx/htmlCMD ["nginx","-g","daemon off;"]
EOF
使用alpine制作鏡像
[root@docker01 ubuntu]# cat buffes-bird.conf
server {listen 80;root /usr/share/nginx/html;
}
docker container inspect practical_archimedes
三.使用dockerfile構建"小鳥飛飛飛" 服務鏡像(FROM,RUN,ADD,COPY,WORKDIR,EXPOSE,VOLUME)
1.對"小鳥飛飛飛" 的游戲項目目錄進行打包
[root@docker01 ~]# ll /buffes/code/
total 144
-rw-r--r--. 1 root root 15329 Aug 2 2014 2000.png
-rw-r--r--. 1 root root 51562 Aug 2 2014 21.js
-rw-r--r--. 1 root root 254 Aug 2 2014 icon.png
drwxr-xr-x. 2 root root 4096 Aug 8 2014 img
-rw-r--r--. 1 root root 3056 Mar 29 10:40 index.html
-rw-r--r--. 1 root root 63008 Aug 2 2014 sound1.mp3[root@docker01 code]# tar zcf ~/xiaoniao.tar.gz *
2.編寫docker文件
[root@docker01 /koboid/softwares/dockerfile/xiaoniao]# vim dockerfile
[root@docker01 /koboid/softwares/dockerfile/xiaoniao]#
[root@docker01 /koboid/softwares/dockerfile/xiaoniao]# cat dockerfile
# 指定基于哪個鏡像構建咱們的自定義鏡像文件
FROM centos:7# 開始安裝服務
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum -y install nginx
RUN rm -rf /usr/share/nginx/html/*# 注意哈,我們的tar包中是包含index.html文件的,因此上面的步驟必須將該文件刪除,避免出現交互式的過程要求咱們進行覆蓋解壓喲。
# ADD指令只能自動解壓tar包
ADD xiaoniao.tar.gz /usr/share/nginx/html# COPY指令并不會自動解壓tar包。
#COPY xiaoniao.tar.gz /usr/share/nginx/html# 姿勢一: 比較傳統的啟動容器時需要執行的命令.
# CMD nginx -g 'daemon off;'
# 姿勢二: 推薦執行的命令
CMD ["nginx","-g","daemon off;"]
[root@docker01 /koboid/softwares/dockerfile/xiaoniao]#
3.編譯dockerfile文件
[root@docker01 /koboid/softwares/dockerfile/xiaoniao]# docker build -t buffes_dockerfile_xiaoniao:v1 .溫馨提示:在本次編譯鏡像時,由于有些步驟在之前構建鏡像時已經做過了,因此該步驟會直接使用臨時的緩存鏡像喲~
4.驗證鏡像
[root@docker01 ~]# docker container run -d -p 80:80 buffes_dockerfile_xiaoniao:v1
5.進階案例(WORKDIR,EXPORT,VOLUME)
[root@docker01 /koboid/softwares/dockerfile/xiaoniao]# vim dockerfile
[root@docker01 /koboid/softwares/dockerfile/xiaoniao]#
[root@docker01 /koboid/softwares/dockerfile/xiaoniao]# cat dockerfile
# 指定基于哪個鏡像構建咱們的自定義鏡像文件
FROM centos:7# 開始安裝服務
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum -y install nginx
RUN rm -rf /usr/share/nginx/html/*# 注意哈,我們的tar包中是包含index.html文件的,因此上面的步驟必須將該文件刪除,避免出現交互式的過程要求咱們進行覆蓋解壓喲。
# ADD指令只能自動解壓tar包
ADD xiaoniao.tar.gz /usr/share/nginx/html# COPY指令并不會自動解壓tar包。
#COPY xiaoniao.tar.gz /usr/share/nginx/html# 指定容器默認的工作目錄,咱們可以理解是執行了一次CD命令
WORKDIR /usr/share/nginx/html# 指定鏡像要暴露的端口,如果設置了該參數,則當我們使用"-P"(大寫)來暴露隨機端口時會觸發該端口的暴露,而無需指定容器要暴露的端口,但宿主機的端口是隨機的。
EXPOSE 80 3306# 指定隨機的持久化卷,通常用于臨時持久化日志數據
VOLUME /var/log/nginx# 姿勢一: 比較傳統的啟動容器時需要執行的命令.
# CMD nginx -g 'daemon off;'
# 姿勢二: 推薦執行的命令
CMD ["nginx","-g","daemon off;"]
[root@docker01 /koboid/softwares/dockerfile/xiaoniao]#
[root@docker01 /koboid/softwares/dockerfile/xiaoniao]# docker image build -t buffes_dockerfile_xiaoniao:v2 .溫馨提示:(1)在演示本案例的時候,建議將WORKDIR,EXPORT,VOLUME指令分開演示。(2)如下所示,編譯dockerfile文件時會出現使用緩存鏡像的現象喲;
6.啟動容器驗證鏡像是否生效
[root@docker01 ~]# docker image ls
[root@docker01 ~]# docker container run -d -P buffes_dockerfile_xiaoniao:v2
[root@docker01 ~]# docker container ps -a
[root@docker01 ~]# docker container exec -it 497757a9f082 bash
[root@docker01 ~]# docker volume ls溫馨提示:我們啟動容器后,會生成一個新的鏡像文件喲~
四.使用dockerfile構建alpine基礎鏡像(FROM,ADD,CMD)
1.下載已經打包好的Linux文件系統
[root@docker01 /koboid/softwares/dockerfile/system]# wget
https://mirrors.tuna.tsinghua.edu.cn/lxc-images/images/alpine/3.14/amd64/default/20210818_13%3A00/rootfs.tar.xzwget https://mirrors.tuna.tsinghua.edu.cn/lxc-images/images/alpine/3.21/amd64/default/20250406_13%3A00/rootfs.tar.xz
溫馨提示:(1)LXC也是容器管理技術,我們使用它已經打包好的文件系統來自己制作一個基礎鏡像,因為容器的文件系統都是通用的。docker也只是和LXC實現相同的功能,即容器管理工具,只不過docker對用戶更加友好;(2)如下圖所示,建議選擇alpine版本(因為該操作系統軟件包最小),下載軟件時建議選擇較為新的版本;
2.解壓并刪除rootfs.tar.xz軟件包
[root@docker01 /koboid/softwares/dockerfile/system]# tar xf rootfs.tar.xz
[root@docker01 /koboid/softwares/dockerfile/system]#
[root@docker01 /koboid/softwares/dockerfile/system]# rm -f rootfs.tar.xz
3.修改Linux發行版本
#參考一:
[root@docker01 /koboid/softwares/dockerfile/system]# sed -i 's#Alpine#buffes#g' etc/os-release#參考二:
[root@docker01 /koboid/softwares/dockerfile/system]# cat etc/os-release
NAME="buffes CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="buffes CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"溫馨提示:如下圖所示,此處我自定義了一個"oldboyedu"的linux系統。
4.重新打包文件系統鏡像
[root@docker01 /koboid/softwares/dockerfile/system]# tar zcf /root/buffes_docker_linux.tar.gz *溫馨提示:我們對文件系統修改后,可以對其進行打包,方便咱們后續使用。
5.編寫dockerfile并編譯
[root@docker01 /oldboy/softwares/dockerfile/koboidlinux]# vim dockerfile
[root@docker01 /oldboy/softwares/dockerfile/koboidlinux]#
[root@docker01 /oldboy/softwares/dockerfile/koboidlinux]# cat dockerfile
# 使用FROM scratch表明我們要構建鏡像中的第一個文件層,scratch是Docker保留鏡像,鏡像倉庫中的任何鏡像都不能使用這個名字。
FROM scratch# 將咱們自定義的文件系統進行解壓到根路徑
ADD buffes_docker_linux.tar.gz /# 編輯容器啟動的COMMAND指令
CMD ["/bin/sh"]
[root@docker01 /koboid/softwares/dockerfile/koboidlinux]#
[root@docker01 /koboid/softwares/dockerfile/koboidlinux]# docker build -t buffes_dockerfile_linux:v1 .
6.啟動docker鏡像并測試
[root@docker01 ~]# docker container run -it buffes_dockerfile_linux:v1 溫馨提示:我們應該查看"cat /etc/os-release"文件中咱們自己修改的內容。
五.使用dockfile構建nginx+ssh雙服務的鏡像
課上案例:
使用dockfile構建nginx+ssh雙服務的鏡像
#更新alpine源
/usr/share/nginx/html # apk update
#搜素sshd
/usr/share/nginx/html # apk search sshd
#下載,openssh-server服務
/usr/share/nginx/html # apk add openssh-server/usr/share/nginx/html # which sshd/usr/share/nginx/html # ssh-keygen -A#啟動sshd 服務
/usr/share/nginx/html # /usr/sbin/sshd/usr/share/nginx/html # ps -ef/usr/share/nginx/html # ifconfig#修改密碼方法一,參考:
/usr/share/nginx/html # passwd#測試連接容器 ip地址
[root@docker101 ~ 02:20:29]# ssh 172.17.0.4
#修改密碼方法二,推薦使用:
/usr/share/nginx/html # sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config/usr/share/nginx/html # grep -i root /etc/ssh/sshd_config/usr/share/nginx/html # ps -ef
chmod +x build.shcat > start-ssh-bird.sh << EOF
#!/bin/sh# enable nginx
nginx# enable sshd
/usr/sbin/sshd# set root password
if [ -n "$OLDBOYEDU_ADMIN_PASSWD" ];thenecho root:$OLDBOYEDU_ADMIN_PASSWD | chpasswd
fi# daemon process
tail -f /etc/hosts
EOFchmod +x start-ssh-bird.sh./build.sh 0
docker container inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' `docker container ps -lq`
docker container inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' `docker container ps -lq`ssh 172.17.0.8ifconfig
之前源文件,案例:
1.編寫服務的啟動腳本
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# vim start_init.sh
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# cat start_init.sh
#!/bin/bash# 啟動nginx,但不需要阻塞當前終端
nginx# 啟動sshd,但需要阻塞當前終端
/usr/sbin/sshd -D
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
2.編寫dockerfile(建議基于自定義的nginx鏡像構建sshd服務)
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# vim dockerfile
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# cat dockerfile
# 基于咱們之前制作好的nginx鏡像即可
FROM buffes_dockerfile_nginx:v1# 安裝依賴包,不要妄圖修改"/etc/hosts"來使用本地yum源,因為RUN指令會每次啟動一個新的容器,而且容器在初始化時的"/etc/hosts"是由宿主機掛載到鏡像的喲!
RUN yum -y install openssh-server
RUN yum -y install initscripts
RUN /usr/sbin/sshd-keygen
RUN /usr/sbin/sshd
RUN echo "123456" | passwd --stdin root# 將咱們編寫的腳本拷貝到鏡像中
COPY start_init.sh /start_init.sh# 暴露指定的端口,如果是修改盡量將修改指令放在最后,因為這樣可以充分利用緩存喲~
EXPOSE 80 22# 編寫容器的啟動流程
# CMD /bin/bash /start_init.sh
CMD ["/bin/bash","/start_init.sh"]
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# docker build -t buffes_dockerfile_nginx:v2 .溫馨提示:(1)如果網絡不佳的小伙伴,可以在編譯的時候使用"--network=host"參數,他會使用宿主機的網絡來下載數據;(2)而一旦使用了宿主機的網絡,則我們就可以在宿主機的"/etc/hosts"文件中將阿里云的軟件源域名解析為內網的yum倉庫,從而達到更好的效果。
3.啟動容器
啟動容器:
[root@docker01 ~]# docker container run -d -P buffes_dockerfile_nginx:v2 測試容器:
[root@docker01 ~]# curl 172.200.1.201:49159[root@docker01 ~]# ssh 172.200.1.201 -p 49160
4.優化dockerfile的編寫
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# vim dockerfile
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# cat dockerfile
# 基于咱們之前制作好的nginx鏡像即可
FROM buffes_dockerfile_nginx:v1# 安裝依賴包,不要妄圖修改"/etc/hosts"來使用本地yum源,因為RUN指令會每次啟動一個新的容器,而且容器在初始化時的"/etc/hosts"是由宿主機掛載到鏡像的喲!
RUN yum -y install openssh-server && \yum -y install initscripts && \/usr/sbin/sshd-keygen && \/usr/sbin/sshd && \echo "123456" | passwd --stdin root# 將咱們編寫的腳本拷貝到鏡像中
COPY start_init.sh /start_init.sh# 暴露指定的端口,如果是修改盡量將修改指令放在最后,因為這樣可以充分利用緩存喲~
EXPOSE 80 22# 編寫容器的啟動流程
# CMD /bin/bash /start_init.sh
CMD ["/bin/bash","/start_init.sh"]
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# 溫馨提示:(1)此處優化我是將多條RUN指令合并成以條指令,這樣做的好處就是僅生成一個臨時鏡像;(2)如下圖所示,建議在編譯鏡像的時候使用"docker container ps -a -l --no-trunc"參數來查看生成的臨時容器,切記,手速要快,否則很快這個過程就被刪除啦!
5.基于alpine完成多服務鏡像案例,體積減20倍以上??
(1)編寫dockerfile
cat > Dockerfile <<EOF
FROM buffes-linux-birds:v4.5RUN apk update && \apk add openssh-server && \ssh-keygen -A && \sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config && \rm -rf /var/cache/COPY start-ssh-bird.sh /start-ssh-bird.shEXPOSE 80 22CMD ["sh","-c","/start-ssh-bird.sh"]
EOF(2)編寫啟動腳本
cat > start-ssh-bird.sh <<EOF
#!/bin/sh# enable nginx
nginx# enable sshd
/usr/sbin/sshd# set root password
if [ -n "$OLDBOYEDU_ADMIN_PASSWD" ];thenecho root:$OLDBOYEDU_ADMIN_PASSWD | chpasswd
elseecho root:123 | chpasswd
fi# daemon process
tail -f /etc/hosts
EOF溫馨提示:(1)alpine鏡像需要"chpasswd"命令完成root用戶的修改喲;(2)alpine鏡像的sshd服務和ubuntu很像,都是默認禁用root用戶登錄啦;
六.使用ENV指令給容器傳遞變量
1.編寫容器的啟動腳本
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# vim start_init.sh
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# cat start_init.sh
#!/bin/bash# 啟動容器后,會修改用戶名的密碼
echo $OLDBOYEDU_ROOT_PASSWORD | passwd --stdin root# 啟動nginx,但不需要阻塞當前終端
nginx# 啟動sshd,但需要阻塞當前終端
/usr/sbin/sshd -D
2.編寫并編譯dockerfile
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# vim dockerfile
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# cat dockerfile
# 基于咱們之前制作好的nginx鏡像即可
FROM oldboyedu_dockerfile_nginx:v1# 暴露指定的端口,如果是修改盡量將修改指令放在最后,因為這樣可以充分利用緩存喲~
EXPOSE 80 22# 安裝依賴包,不要妄圖修改"/etc/hosts"來使用本地yum源,因為RUN指令會每次啟動一個新的容器,而且容器在初始化時的"/etc/hosts"是由宿主機掛載到鏡像的喲!
RUN yum -y install openssh-server && \yum -y install initscripts && \/usr/sbin/sshd-keygen && \sed -i 's@#UseDNS yes@UseDNS no@' /etc/ssh/sshd_config# 將咱們編寫的腳本拷貝到鏡像中
COPY start_init.sh /start_init.sh# 編寫容器的啟動流程
# CMD /bin/bash /start_init.sh
CMD ["/bin/bash","/start_init.sh"]
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# docker build -t buffes_dockerfile_nginx:v7 .溫馨提示:我并沒有直接在dockerfile中啟動sshd服務,也沒有直接修改root密碼,而是在啟動腳本中來做這兩件事情。
3.啟動容器時傳遞環境變量而定制root密碼
[root@docker01 ~]# docker container run -d -P --env "OLDBOYEDU_ROOT_PASSWORD=koboid" buffes_dockerfile_nginx:v7溫馨提示:不難發現,基于sshd服務遠程連接進去的終端是看不到"$OLDBOYEDU_ROOT_PASSWORD"這個環境變量的喲~
4.本案例dockerfile存在的問題
當我們在創建容器時,若沒有使用"--env"傳遞參數時,則可能會存在未能給root用戶設置密碼的情況解決該問題,我目前想到了三種解決方案:方案一:(直接可是演示)登錄容器,手動為root用戶修改密碼即可。方案二:(讓學生課堂練習)修改容器的啟動腳本"start_init.sh",判斷是否存在"$OLDBOYEDU_ROOT_PASSWORD"這個變量,如果不存在則設置初始密碼為:"koboid@buffes"。方案三:(直接課上演示,但需要給學員先做出來方案二)在dockerfile中使用ENV指令設置初始密碼。
5.編寫dockerfile
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# vim dockerfile
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# cat dockerfile
# 基于咱們之前制作好的nginx鏡像即可
FROM buffes_dockerfile_nginx:v1# 暴露指定的端口,如果是修改盡量將修改指令放在最后,因為這樣可以充分利用緩存喲~
EXPOSE 80 22# 安裝依賴包,不要妄圖修改"/etc/hosts"來使用本地yum源,因為RUN指令會每次啟動一個新的容器,而且容器在初始化時的"/etc/hosts"是由宿主機掛載到鏡像的喲!
RUN yum -y install openssh-server && \yum -y install initscripts && \/usr/sbin/sshd-keygen && \sed -i 's@#UseDNS yes@UseDNS no@' /etc/ssh/sshd_config# 將咱們編寫的腳本拷貝到鏡像中
COPY start_init.sh /start_init.sh# 為root用戶設置初始密碼,如果用戶在啟動容器時沒有使用"--env"指令進行傳參時,咱們就可以使用ENV指令為某個變量設置初始值喲,
# OLDBOYEDU_ROOT_PASSWORD變量是我們在/start_init.sh中有調用喲~
ENV OLDBOYEDU_ROOT_PASSWORD koboid@buffes# 編寫容器的啟動流程
# CMD /bin/bash /start_init.sh
CMD ["/bin/bash","/start_init.sh"]
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# docker build -t buffes_dockerfile_nginx:v8 .
6.驗證ENV指令是否生效
[root@docker01 ~]# docker container ls
[root@docker01 ~]# docker container run -d -P buffes_dockerfile_nginx:v8
[root@docker01 ~]# docker container ls
[root@docker01 ~]# docker container exec -it 423def9bce9e bash
[root@423def9bce9e /]# env | grep -i koboid
[root@docker01 ~]# ssh 172.200.1.201 -p 49178
七.使用ENTRYPOINT指令案例啟動容器(注意和CMD指令進行對比)
1.編寫dockerfile并進行編譯
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# vim dockerfile
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# cat dockerfile
# 基于咱們之前制作好的nginx鏡像即可
FROM buffes_dockerfile_nginx:v1# 暴露指定的端口,如果是修改盡量將修改指令放在最后,因為這樣可以充分利用緩存
EXPOSE 80 22# 安裝依賴包,不要妄圖修改"/etc/hosts"來使用本地yum源,因為RUN指令會每次啟動一個新的容器,而且容器在初始化時的"/etc/hosts"是由宿主機掛載到鏡像
RUN yum -y install openssh-server && \yum -y install initscripts && \/usr/sbin/sshd-keygen && \sed -i 's@#UseDNS yes@UseDNS no@' /etc/ssh/sshd_config# 將咱們編寫的腳本拷貝到鏡像中
COPY start_init.sh /start_init.sh# 為root用戶設置初始密碼,如果用戶在啟動容器時沒有使用"--env"指令進行傳參時,咱們就可以使用ENV指令為某個變量設置初始值喲,
# OLDBOYEDU_ROOT_PASSWORD變量是我們在/start_init.sh中有調用喲~
ENV OLDBOYEDU_ROOT_PASSWORD koboid@buffes# 編寫容器的啟動流程
# CMD /bin/bash /start_init.sh
# CMD ["/bin/bash","/start_init.sh"]
ENTRYPOINT ["/bin/bash","/start_init.sh"]
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]#
[root@docker01 /koboid/softwares/dockerfile/centos7_nginx_sshd]# docker build -t buffes_dockerfile_nginx:v9 .
2.啟動容器
啟動容器并指定初始化指令:
[root@docker01 ~]# docker container run -d -P buffes_dockerfile_nginx:v9 echo "buffes linux 6666"查看容器啟動的初始化指令:
[root@docker01 ~]# docker ps -a --no-trunc溫馨提示:當使用ENTRYPOINT指令時,該指令是不可被覆蓋的!
3.dockerfile的ENV指令和ENTRYPOINT指令實戰案例
(1)編寫啟動腳本
cat > start-ssh-bird.sh << EOF
#!/bin/sh# enable nginx
nginx# enable sshd
/usr/sbin/sshd# set root password
if [ -n "$OLDBOYEDU_ADMIN_PASSWD" ];thenecho root:$OLDBOYEDU_ADMIN_PASSWD | chpasswd
fi# daemon process
tail -f /etc/hosts
EOF(2)編寫dockerfile
cat > Dockerfile <<EOF
FROM oldboyedu-linux-birds:v4.5RUN apk update && \apk add openssh-server && \ssh-keygen -A && \sed -i 's@#PermitRootLogin prohibit-password@PermitRootLogin yes@g' /etc/ssh/sshd_config && \rm -rf /var/cache/COPY start-ssh-bird.sh /start-ssh-bird.shEXPOSE 80 22ENV OLDBOYEDU_ADMIN_PASSWD=99999# CMD ["sh","-c","/start-ssh-bird.sh"]
ENTRYPOINT ["sh","-c","/start-ssh-bird.sh"]
EOF
八.其它指令(了解即可)
1.MAINTAINER (deprecated)
該指令已廢棄,不推薦使用,建議使用更加靈活的LABEL標簽。推薦閱讀:https://docs.docker.com/engine/reference/builder/#maintainer-deprecated
2.LABEL
很明顯,我們是可以使用LABEL標簽,因為它更加靈活。舉個例子:LABEL org.opencontainers.image.authors="buffes@buffes.cn"推薦閱讀:https://docs.docker.com/engine/reference/builder/#label
3.其它指令
強烈推薦閱讀:https://docs.docker.com/engine/reference/builder/
九.docker鏡像分層
1.導出鏡像并拷貝到其它節點進行測試
我們找一臺docker虛擬機的將我們之前生成的鏡像導出。導出鏡像后記得拷貝到其它docker測試的節點。
[root@docker01 /koboid/softwares]# docker image save -o buffes_centos.tar.gz centos:7
[root@docker01 /koboid/softwares]# docker image save -o buffes_dockerfile_nginx.tar.gz buffes_dockerfile_nginx:v1
[root@docker01 /koboid/softwares]# scp koboid_* root@172.200.1.202:~
2.先導入centos鏡像,然后再導入nginx鏡像
如下圖所示,我們先導入centos鏡像,然后再導入nginx鏡像,請觀察輸出情況。
[root@docker01 ~]# docker image ls -a#先導入centos鏡像
[root@docker01 ~]# docker image load -i buffes_centos.tar.gz
#再導入nginx鏡像
[root@docker01 ~]# docker image load -i buffes_dockerfile_nginx.tar.gz[root@docker01 ~]# docker image ls -a
3.先導入nginx鏡像,再導入centos鏡像
如下圖所示,我們先導入nginx鏡像,然后再導入centos鏡像,你會發現此次導入的效果和上面并不相同。你可能會問這是為什么,其實這就是docker的"鏡像分層技術"再搗鬼。
[root@docker01 ~]# systemctl stop docker.socket
[root@docker01 ~]# systemctl stop docker
[root@docker01 ~]# rm -fr /var/lib/docker/*
[root@docker01 ~]# systemctl start docker
[root@docker01 ~]# docker image ls -a#你會發現,先導入nginx鏡像的時候,比上次要多導入了一個鏡像層
[root@docker01 ~]# docker image -i buffes_dockerfile_nginx.tar.gz
[root@docker01 ~]# docker image ls -a#后倒入centos鏡像時,你會發現壓根就沒有進行鏡像分層的導入,導入的只是一個鏡像標簽而已
[root@docker01 ~]# docker image load -i buffes_centos.tar.gz
4.docker鏡像分層概述
下圖所示,鏡像分層就是將構建鏡像的過程進行拆解,找到和其它服務的共同點并將其定制為一個基礎鏡像,這樣可以很大的提示工作效率。有利于鏡像的重復利用,就像開發喜歡編寫函數來實現代碼的復用性原理一樣。鏡像分層的優點:(1)節省磁盤空間,對鏡像進行復用;(2)在上傳鏡像時,如果自定義進行的基礎鏡像在倉庫中存在,則不會重復上傳,從而達到了節省帶寬的目的,自然也就提高了上傳的速度;(3)在下載鏡像時,如果該鏡像的基礎鏡像在本地中已存在,則無需重復下載相應的基礎鏡像,從而達到了節省帶寬的目的,自然也就提高了下載的速度;鏡像分層的缺點:基礎鏡像如果少安裝了某個服務,若改動該鏡像將導致所有基于該鏡像制作的子鏡像都發送變動,因此在制作基礎鏡像是要提前考慮周全喲。
5.容器和鏡像的關系-寫時復制(copy-on-write,簡稱COW)技術
如下圖所示,我們的鏡像是由多個鏡像分層合并而來,而這些層都是只讀層。當你啟動一個容器,Docker會在最頂部添加讀寫層,這依賴于寫時復制(copy-on-write,簡稱COW)技術。你在容器內做的所有更改,如寫日志、修改、刪除文件等,都保存到了讀寫層內,一般稱該層為容器層。事實上,容器(container)和鏡像(image)的最主要區別就是容器加上了頂層的讀寫層。所有對容器的修改都發生在此層,鏡像并不會被修改,因為這些鏡像分層的基礎鏡像可能也在被其他容器使用,一旦修改意味著對其他正在運行的容器也會受到牽連。容器需要讀取某個文件時,直接從底部只讀層去讀即可,而如果需要修改某文件,則將該文件拷貝到頂部讀寫層進行修改,只讀層保持不變。每個容器都有自己的讀寫層,因此多個容器可以使用同一個鏡像,另外容器被刪除時,其對應的讀寫層也會被刪除(如果你希望多個容器共享或者持久化數據,可以使用 Docker volume)。
如下所示,在執行命令docker ps -s,可以看到最后多了一列SIZE。關于SIZE相關字段的說明:(1)其中size就是容器讀寫層占用的磁盤空間;(2)而括號內的virtual就是再讀寫層加上對應只讀層所占用的磁盤空間。[root@docker01 ~]# docker ps
[root@docker01 ~]# docker run -itd buffes_dockerfile_xiaoniao:v3
[root@docker01 ~]# docker ps
[root@docker01 ~]# docker ps -s
[root@docker01 ~]# docker image ls溫馨提示:如果兩個容器是從同一個鏡像創建,那么只讀層就是100%共享,也就是在服務器上只存在這同一份鏡像文件。即使不是從同一鏡像創建,其鏡像仍然可能共享部分只讀層(比如共享的鏡像是基于另一個鏡像創建的)。因此,docker實際占用的磁盤空間遠遠小于virtual的總和。
十.聯合文件系統(UnionFS)
1.什么是聯合文件系統(UnionFS)
前面我們介紹了鏡像層和容器層之間的關系,至于這些層的交互、管理就需要存儲驅動程序,也即聯合文件系統(UnionFS)。Docker可使用多種驅動,如目前已經合并入Linux內核、官方推薦的overlay, 曾在Ubuntu、Debian等發行版中得到廣泛使用的 AUFS,以及devicemapper、zfs等等,需要根據Docker以及宿主機系統的版本,進行合適的選擇。接下來以AUFS為例,簡單介紹UnionFS的使用。
2.AUFS概述
AUFS是一種UnionFS,所謂UnionFS就是把不同物理位置的目錄合并到同一個目錄中。例如把CD和硬盤mount到一起,就可以對CD上的文件進行修改,再比如上面所講docker的使用場景。AUFS是Another UnionFS的首字母縮略字,2006年由岡島順治郎開發,是之前的UnionFS的完全重寫,其穩定性和性能上確實好很多,但從第2版開始它代表高級多層統一文件系統(dvanced multi-layered unification filesystem)。這里插播一個悲情的小故事,AUFS被Linus拒絕合并到主線 Linux,其代碼被批評為“稠密,不可讀,無注釋”。然后作者不斷改進代碼,不斷提交,不斷被Linus拒掉,最終放棄。而2014年,OverlayFS被合并到 Linux 內核 3.18版本,岡島順治郎再無希望。
3.創建測試文件
如下圖所示,我使用的是Ubuntu 18.04環境。CentOS默認不支持aufs,需要手動安裝喲~言歸正傳,下面我們簡單試驗下AUFS 的使用。操作步驟如下:
[root@docker01 ~]# mkdir -pv /buffes/{readLayer,writeLayer,unionFs}
[root@docker01 ~]# echo "buffes linux original read file content" >> /buffes/readLayer/readFile
[root@docker01 ~]#
[root@docker01 ~]# echo "buffes linux original write file content" >> /buffes/writeLayer/writeFile
[root@docker01 ~]#
[root@docker01 ~]# cd /buffes/
[root@docker01 /buffes]# mount -t aufs -o dirs=./writeLayer:./readLayer none ./unionFs
[root@docker01 /buffes]#
[root@docker01 /buffes]# cd unionFs/
[root@docker01 /buffes/unionFs]#
[root@docker01 /buffes/unionFs]# ll
total 16
drwxr-xr-x 4 root root 4096 Jun 18 13:29 ./
drwxr-xr-x 5 root root 4096 Jun 18 13:27 ../
-rw-r--r-- 1 root root 43 Jun 18 13:28 readFile
-rw-r--r-- 1 root root 44 Jun 18 13:28 writeFile
[root@docker01 /buffes/unionFs]# cat readFile
[root@docker01 /buffes/unionFs]# cat writeFile
[root@docker01 ~]# cat /etc/os-release
4.測試讀寫層的文件
如下圖所示,可以看到,我們成功模擬了只讀層、讀寫層的聯合使用,Docker的鏡像分層也是此原理,只是實現更加復雜。溫馨提示:
[root@docker01 /buffes/unionFs]# echo "buffes linux edit writeable file" >> writeFile
[root@docker01 /buffes/unionFs]#
[root@docker01 /buffes/unionFs]# echo "buffes linux edit readonly file" >> readFile
[root@docker01 /buffes/unionFs]# cat readFile
[root@docker01 /buffes/unionFs]# cat writeFile
#只讀層的內容并沒有發生改變
[root@docker01 /buffes/unionFs]# cat ..readLayer/readFile
#可寫的文件內容缺發生了改變
[root@docker01 /buffes/unionFs]# cat ../writeLayer/writefile
[root@docker01 /buffes/unionFs]# ll -R ..
測試讀寫層的文件,課上例子
5.推薦閱讀
強烈推薦閱讀:https://docs.docker.com/storage/storagedriver/使用prometheus監控docker環境:https://docs.docker.com/config/daemon/prometheus/
十一.dockerfile的優化
1.dockerfile的優化原則
dockerfile的優化原則簡而言之為:"構建的鏡像盡可能小,構建速度盡可能快"。(1)編譯速度快 ---> 充分利用緩存1)將不經常變更的指令放在靠前位置,修改指令時應該修改靠后的指令;2)在不影響功能的前提下,可以合并多條指令,減少鏡像的層數;3)使用".dockerignore"來忽略不需要發送給docker daemon進程的文件;(2)鏡像體積小 ----> 1)刪除緩存或者無用的軟件包2)使用較小的基礎鏡像溫馨提示:(1)大多數開源的Linux鏡像默認都是用了標準C語言編譯器glibC,這會占用很大一部分空間;(2)而alpine使用musl libc和BusyBox構建的Linux發行版;(3)alpine和其它linux發行版相比就是體積小,但也可能會存在部分軟件不兼容的情況喲;(4)如果alpine無法兼容一些軟件時,可以考慮使用Ubuntu18.04鏡像,因為其63MB;(5)最后再考慮使用centos鏡像,因為其鏡像大小超過200MB;
2.體驗alpine案例
我們已經接觸過centos/redhat的包管理工具yum,其軟件包格式為rpm。也接觸過Ubuntu/debian的包管理工具apt,其軟件包格式為deb。還接觸過suse/opensuse的包管理工具zypper,其也支持rpm軟件包格式。fedora使用的包管理工具為dnf等等。而今日要說的alpine其包管理工具為apk。如下圖所示,我們簡單體驗一下alpine安裝軟件后提交為鏡像其大小吧。安裝nginx軟件包命令如下:
[root@docker01 ~]# docker images
[root@docker01 ~]# docker image pull alpine:latest
[root@docker01 ~]# docker container run -it alpine:latest/ # sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories/ # / # apk update/ # / # apk add nginx/ # nginx -v/ # nginx/ # ps -ef
[root@docker01 ~]# docker container ps
[root@docker01 ~]# docker container stop 4a14ce07ff7a
[root@docker01 ~]# docker ps -a -l
[root@docker01 ~]# docker container commit 78244debf429 alpine_nginx:v1
[root@docker01 ~]# docker image ls alpine nginx
[root@docker01 ~]# docker image ls alpine溫馨提示: 如果想使用阿里云請參考官方連接: https://developer.aliyun.com/mirror/alpine
3.刪除無用緩存,合并多條run指令案例(演示的時候建議分別使用3臺干凈的docker環境測試)
4.修改dockerfile的時候,盡可能把修改的內容放在最后,這樣可以充分利用緩存鏡像
當我們將dockerfile較前的位置修改后,會改變docker鏡像之間的依賴關系,從而無法充分利用之前的鏡像緩存喲。因此生產環境中,建議修改dockerfile的時候,盡可能把修改的內容放在最后,這樣可以充分利用緩存鏡像。
5.使用".dockerignore"忽略構建docker鏡像時不需要的文件,從而減小鏡像體積
dockerfile在構建時會將指定路徑(我們通常指定的是當前路徑)下的所有文件都發送給Dacoker daemon程序,盡管在構建過程中有很多文件用不上的,默認也是會發送該路徑下的所有文件喲。綜上所述,我們可以常見一個".dockerignore"的隱藏文件,它可以幫助咱們在構建鏡像時自動忽略這些文件!從而提示構建鏡像的速度。如下圖所示,我們在構建鏡像時,我故意弄了一堆構建鏡像時用不到的文件放在該目錄下,發現構建鏡像時會將所有的鏡像文件發送給docker daemon進程呢,這大大的減緩了構建鏡像的速度,因此我們可以創建一個名為".dockerignore"的隱藏文件來忽略不需要發送給docker daemon進程的文件,很明顯,該文件是支持通配符的喲~[root@docker201 /buffes/softwares/dockerfile/centos7_nginx/dome3]# vim .dockerignore
[root@docker201 /buffes/softwares/dockerfile/centos7_nginx/dome3]#
[root@docker201 /buffes/softwares/dockerfile/centos7_nginx/dome3]# cat .dockerignore
oldboyedu_docker*
xiaoniao*
docker_rpm_20.10.tar.gz
[root@docker201 /buffes/softwares/dockerfile/centos7_nginx/dome3]# 溫馨提示:我們在生產環境中這種場景還是很常見的,比如下載別人寫的代碼,代碼里有很多ReadMe.md,change.log等文件,在編譯時docker環境時壓根用不上,因此可以適當性忽略,從而達到提速的效果。
十二.可能會遇到的報錯
1.sshd re-exec requires execution with an absolute path
報錯原因:基于alpine鏡像啟動服務sshd服務時,要求咱們使用絕對路徑!解決方案:使用sshd的絕對路徑即可,即"which sshd",得到"/usr/sbin/sshd"
2.sshd: no hostkeys available – exiting.
問題原因:缺少hostkeys.解決方案:"ssh-keygen -A"生成新的主機KEY.
3.Add correct host key in /root/.ssh/known_hosts to get rid of this message.
問題原因:本地記錄的主機KEY和即將鏈接主機的KEY不一致.解決方案:刪除IP在/root/.ssh/known_hosts文件中的記錄.
小的,創作不容易。給個點點關注
多多少少給點吧
