先前咱們在講述docker的鏡像構建時對Dockerfile作了初步介紹,本文將結合上次的內容作更加細緻的介紹,從回顧到實戰演練講述Dockerfile,本文先經過三個簡單的案例感覺、理解Dockerfile,主要是寫httpd、sshd、以及systemctl的Dockerfile,以後會進行對其餘服務如Nginx、Tomcat以及MySQL編寫而且測試Dockerfile。html
說到Dockerfile,就離不開Dockerfile的核心組件,尤爲是鏡像。鏡像是運行容器的基礎環境,也就是說鏡像是docker容器建立的關鍵,而建立鏡像的三種方式之一的Dockerfile是最爲靈活的。nginx
Dockerfile能夠看作是被Docker程序所解釋翻譯的腳本,由一組命令集合而成,每一條命令都對應一條操做命令,有其翻譯爲Linux下的具體命令。用戶能夠經過自定義內容來快速構建鏡像。web
其實說簡單點,你能夠認爲Dockerfile是「專門用於構建鏡像的shell腳本」。docker
還記得Dockerfile的嚴格格式嗎?咱們先來看一下這個表格。shell
Dockerfile是一種分層結構,其中的指令每一條都會構建一層鏡像及容器,只不過這是臨時的,除了基礎鏡像,其餘中間產生的容器最後都會被清除。固然有時候會出現一些「無名氏」鏡像,標誌就是使用docker images命令時ID和tag都是none。apache
出現none鏡像的緣由有兩類:一則是好的none鏡像;二則是壞的none鏡像。好的none鏡像:表明的是中間鏡像,你能夠認爲是父鏡像的子鏡像,可使用docker images -a查看。這類鏡像不會佔用磁盤空間,可是佔用了屏幕顯示空間。壞的none鏡像:這類可能會致使磁盤空間問題。通常這種狀況是舊鏡像更新產生。vim
所以,通常狀況咱們均可以經過命令將none鏡像刪除(實戰中會給出)。centos
Dockerfile的核心做用就是用戶能夠靈活、快速、支持自定義構建所需鏡像。瀏覽器
(1)docker從基礎鏡像運行一個容器;
(2)執行一條指令並對容器做出修改;
(3)執行相似docker commit的操做提交一個新的鏡像層;
(4)docker再基於剛提交的鏡像運行一個新容器;
(5)執行dockerfile中的下一條指令直到全部指令都執行完成。緩存
構建鏡像命令舉例:docker build -t image_name . (不要忽視這個點)
使用鏡像命令舉例:docker run -d -P image_name
最後使用docker ps -a 查看容器運行狀態,若是是up狀態就能夠鏡像測試驗證了。
首先建立工做目錄
mkdir apache cd apache
編寫Dockerfile
vim Dockerfile
#基於的基礎鏡像 FROM centos #維護鏡像的用戶信息 MAINTAINER lokott@lokott.org #鏡像操做指令安裝Apache軟件 RUN yum -y update RUN yum -y install httpd #開啓 80端口 EXPOSE 80 #複製網站首頁文件 ADD index.html /var/www/html/index.html #將執行腳本複製到鏡像中 ADD run.sh /run.sh RUN chmod 755 /run.sh #啓動容器是執行腳本 CMD ["/run.sh"]
其中注意:run 命令能夠有多條CMD只能有一條,如有多條則只會執行最後一條
編寫啓動httpd服務的shell腳本
vim run.sh
#!/bin/bash rm -rf /run/httpd/* exec /usr/sbin/apachectl -D FOREGROUND
編寫測試頁面
vim index.html
<h1>this is docker httpd web</h1>
使用tree命令查看目錄的文件結構
[root@localhost apache]# tree ./ ./ ├── Dockerfile ├── index.html └── run.sh 0 directories, 3 files
構建和使用鏡像(建立運行容器)
[root@localhost apache]# docker build -t httpd:new . #由於我以前已經構建過,因此很快,此處案例顯示過程是爲了體現Dockerfile執行時的特徵:分層和中間容器及鏡像 Sending build context to Docker daemon 4.096kB Step 1/9 : FROM centos:7 ---> 5e35e350aded Step 2/9 : MAINTAINER lokott@123.com ---> Using cache ---> 3a68b2812314 Step 3/9 : RUN yum -y update ---> Using cache ---> ecf1ecb0a774 Step 4/9 : RUN yum install -y httpd ---> Using cache ---> ae8c1ee32fbd Step 5/9 : EXPOSE 80 ---> Using cache ---> 29f12f1f7490 Step 6/9 : ADD index.html /var/www/html/index.html ---> Using cache ---> f56113e6b984 Step 7/9 : ADD run.sh /run.sh ---> Using cache ---> 886bf9e654ab Step 8/9 : RUN chmod +x /run.sh ---> Using cache ---> bf53e19ad44f Step 9/9 : CMD ["/run.sh"] ---> Using cache ---> 9500f0aefd1d Successfully built 9500f0aefd1d Successfully tagged httpd:new [root@localhost apache]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE httpd new 9500f0aefd1d 35 seconds ago 524MB centos 7 5e35e350aded 5 months ago 203MB ...//以後的案例將再也不查看鏡像了哈! #基於構建的鏡像建立並運行容器,給容器取名爲test [root@localhost apache]# docker run --name test -d -P httpd:new b7ec122849c61e36adb4a8891a87126afb53b1d5edfa2fda2a1ea18afa1a3169 [root@localhost apache]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b7ec122849c6 httpd:new "/run.sh" 3 seconds ago Up 3 seconds 0.0.0.0:32768->80/tcp test
這樣咱們進入容器中檢查一下這個頁面文件是否存在
[root@localhost apache]# docker exec -it test /bin/bash [root@b7ec122849c6 /]# cat /var/www/html/index.html <h1>this is docker httpd web</h1>
那麼此時咱們能夠經過瀏覽器訪問宿主機ip地址結合端口號(32768)來訪問網站,結果以下:
下面的案例構建就直接給出Dockerfile和構建測試命令了。主要介紹其中的關鍵點。
mkdir sshd cd sshd
#sshd服務的鏡像構建——基於Dockerfile #首先先下載基礎鏡像centos,建立對應的工做目錄 #開始編寫nginx的Dockerfile #第一步:基礎鏡像 FROM centos:7 #第二步:維護者信息 MAINTAINER lokott@123.com #第三步:指令集 RUN yum -y update RUN yum -y install openssh* net-tools lsof telnet passwd RUN echo '123123' | passwd --stdin root #不以PAM認證登陸而是以密鑰對登陸(非對稱密鑰),即禁用ssh的PAM認證 RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key #禁用ssh中PAM會話模塊 RUN sed -i '/^session\s\+required\s\+pam_loginuid.so/s/^/#/' /etc/pam.d/sshd #建立ssh工做目錄和權限設置 RUN mkdir -p /root/.ssh && chown root:root /root && chmod 700 /root/.ssh #開放22端口 EXPOSE 22 #第四步:啓動容器時執行指令 CMD ["/usr/sbin/sshd","-D"]
構建鏡像和運行容器
[root@localhost sshd]# docker build -t sshd:new . [root@localhost sshd]# docker run -d -P sshd:new c7991648efebd192eb29f1d4e3503e47e0581f55381ff7a23e545041ef5d3e67 [root@localhost sshd]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c7991648efeb sshd:new "/usr/sbin/sshd -D" 20 seconds ago Up 20 seconds 0.0.0.0:32769->22/tcp jolly_ishizaka b7ec122849c6 httpd:new "/run.sh" 20 minutes ago Up 20 minutes 0.0.0.0:32768->80/tcp test
測試
[root@localhost sshd]# ssh 20.0.0.149 -p 32769 The authenticity of host '[20.0.0.149]:32769 ([20.0.0.149]:32769)' can't be established. RSA key fingerprint is SHA256:XLezVGFvOKIKW3fTBD0sIE9rsdz4021taphmcCo8IJM. RSA key fingerprint is MD5:1e:86:94:2a:f5:a3:6c:e2:b4:b1:e4:50:9c:ad:8e:fb. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[20.0.0.149]:32769' (RSA) to the list of known hosts. root@20.0.0.149's password: [root@c7991648efeb ~]# exit logout Connection to 20.0.0.149 closed.
此時咱們登陸該容器(ssh或者docker exec命令)查看sshd服務的狀態(可是systemctl沒法使用)
[root@c7991648efeb ~]# systemctl status sshd Failed to get D-Bus connection: Operation not permitted
一則咱們可使用下面的命令使用該命令,二則咱們能夠基於上面構建的鏡像做爲基礎鏡像構建systemctl的鏡像來測試驗證。
[root@localhost sshd]# docker run --privileged -itd -P sshd:new /usr/sbin/init 8dafa05dc12fc02f91dce93c6ab3085ab55eff1ee6b18c24731205e5c2ed37a9 [root@localhost sshd]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8dafa05dc12f sshd:new "/usr/sbin/init" 3 seconds ago Up 3 seconds 0.0.0.0:32770->22/tcp hardcore_mccarthy c7991648efeb sshd:new "/usr/sbin/sshd -D" 20 minutes ago Up 20 minutes 0.0.0.0:32769->22/tcp jolly_ishizaka b7ec122849c6 httpd:new "/run.sh" 40 minutes ago Up 40 minutes 0.0.0.0:32768->80/tcp test [root@localhost sshd]# ssh 20.0.0.149 -p 32770 The authenticity of host '[20.0.0.149]:32770 ([20.0.0.149]:32770)' can't be established. ECDSA key fingerprint is SHA256:LU81jNjOCKaiWrCsxTLPmx+YsUMVOBa2rG/XLXQsv9E. ECDSA key fingerprint is MD5:03:15:aa:8a:65:8a:cc:b4:fb:66:f8:f6:6c:89:84:7b. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[20.0.0.149]:32770' (ECDSA) to the list of known hosts. root@20.0.0.149's password: [root@8dafa05dc12f ~]# systemctl status sshd ● sshd.service - OpenSSH server daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2020-04-22 02:28:49 UTC; 33s ago Docs: man:sshd(8) man:sshd_config(5)
--privileged表示提權,使得容器真正具有root的權限
mkdir systemctl cd systemctl
建立Dockerfile
vim Dockerfile
FROM sshd:new MAINTAINER lokott@123.com ENV container docker #下面的命令是放在一個鏡像層中執行的,能夠減小鏡像層 #括號中的指令含義是遍歷進入的目錄文件,刪除除了systemd-tmpfiles-setup.service的全部文件,以後刪除一些其餘文件 RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \ rm -f /lib/systemd/system/multi-user.target.wants/*; \ rm -f /etc/systemd/system/*.wants/*; \ rm -f /lib/systemd/system/local-fs.target.wants/*; \ rm -f /lib/systemd/system/sockets.target.wants/*udev*; \ rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \ rm -f /lib/systemd/system/basic.target.wants/*; \ rm -f /lib/systemd/system/anaconda.target.wants/*; VOLUME [ "/sys/fs/cgroup" ] CMD ["/usr/sbin/init"]
構建運行及測試
[root@localhost systemctl]# docker build -t systemctl:new . [root@localhost systemctl]# docker run --privileged -it -v /sys/fs/cgroup/:/sys/fs/cgroup:ro systemctl:new /usr/sbin/init systemd 219 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN) Detected virtualization docker. Detected architecture x86-64. Welcome to CentOS Linux 7 (Core)! Set hostname to <e99fd581042a>. [ OK ] Reached target Paths. [ OK ] Reached target Local File Systems. [ OK ] Reached target Swap. [ OK ] Created slice Root Slice. [ OK ] Listening on Journal Socket. [ OK ] Created slice System Slice. Starting Create Volatile Files and Directories... [ OK ] Listening on Delayed Shutdown Socket. [ OK ] Reached target Slices. Starting Journal Service... [ OK ] Started Create Volatile Files and Directories. [ INFO ] Update UTMP about System Boot/Shutdown is not active. [DEPEND] Dependency failed for Update UTMP about System Runlevel Changes. Job systemd-update-utmp-runlevel.service/start failed with result 'dependency'. [ OK ] Started Journal Service. [ OK ] Reached target System Initialization. [ OK ] Started Daily Cleanup of Temporary Directories. [ OK ] Reached target Timers. [ OK ] Listening on D-Bus System Message Bus Socket. [ OK ] Reached target Sockets. [ OK ] Reached target Basic System. [ OK ] Reached target Multi-User System.
從新開啓一個終端進行測試
[root@localhost systemctl]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e99fd581042a systemctl:new "/usr/sbin/init" About a minute ago Up About a minute 22/tcp gifted_edison 8dafa05dc12f sshd:new "/usr/sbin/init" 6 minutes ago Up 6 minutes 0.0.0.0:32770->22/tcp hardcore_mccarthy c7991648efeb sshd:new "/usr/sbin/sshd -D" 27 minutes ago Up 27 minutes 0.0.0.0:32769->22/tcp jolly_ishizaka b7ec122849c6 httpd:new "/run.sh" 46 minutes ago Up 46 minutes 0.0.0.0:32768->80/tcp test [root@localhost systemctl]# docker exec -it gifted_edison /bin/bash [root@e99fd581042a /]# systemctl status sshd ● sshd.service - OpenSSH server daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; disabled; vendor preset: enabled) Active: inactive (dead) Docs: man:sshd(8) man:sshd_config(5) [root@e99fd581042a /]# systemctl start sshd [root@e99fd581042a /]# systemctl status sshd ● sshd.service - OpenSSH server daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; disabled; vendor preset: enabled) Active: active (running) since Wed 2020-04-22 02:36:18 UTC; 1s ago Docs: man:sshd(8) man:sshd_config(5) Main PID: 51 (sshd) CGroup: /docker/e99fd581042af009c4a15e9ab7bdd231c0052056051a1b18e9996f57eb7f2c6b/system.slice/sshd.service └─51 /usr/sbin/sshd -D Apr 22 02:36:18 e99fd581042a systemd[1]: Starting OpenSSH server daemon... Apr 22 02:36:18 e99fd581042a sshd[51]: WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several problems. Apr 22 02:36:18 e99fd581042a sshd[51]: Server listening on 0.0.0.0 port 22. Apr 22 02:36:18 e99fd581042a sshd[51]: Server listening on :: port 22. Apr 22 02:36:18 e99fd581042a systemd[1]: Started OpenSSH server daemon. #開啓sshd服務後進行訪問宿主機測試成功 [root@e99fd581042a /]# ssh 20.0.0.149 -p 22 The authenticity of host '20.0.0.149 (20.0.0.149)' can't be established. ECDSA key fingerprint is SHA256:pT/8N0H/tNaMm4Zqh7u28Jm5EtmDkidSaih4lWzFIQY. ECDSA key fingerprint is MD5:16:47:40:1f:40:1b:34:e9:ff:f9:15:7b:0b:f4:02:8b. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '20.0.0.149' (ECDSA) to the list of known hosts. root@20.0.0.149's password: Last login: Wed Apr 22 10:35:20 2020 from 20.0.0.149 [root@localhost ~]# exit 登出 Connection to 20.0.0.149 closed. [root@e99fd581042a /]# exit exit
本文回顧了Dockerfile,結合三個案例(httpd服務、sshd服務、systemd服務)來深刻理解Dockerfile構建鏡像的過程。其中咱們須要理解的是
一、每一個服務都須要有本身的目錄和文件
二、Dockerfile的分層和中間緩存鏡像和容器的建立和刪除特色
三、--privileged的做用
四、體會整個從構建鏡像、建立運行容器到測試驗證的過程
謝謝閱讀!