還不明白 Docker 的鏡像跟容器?

一、docker 是什麼

還不明白 Docker 的鏡像跟容器?

docker

上面這張圖就很好的說明一切了,傳統的虛擬機是通過軟件把計算機的一個個硬件給模擬出來,之後再在模擬出的計算機中安裝系統,之後再在系統內部跑應用,就比如需要兩個應用,一個跑Nginx一個跑MySQL,那麼用虛擬機的話就要安裝兩次系統,宿主機也就是真實的非虛擬出來的計算機要保存這兩個虛擬的系統,佔用空間不說最主要的是給宿主機額外的開銷,這兩個虛擬機的系統都是需要cpu和內存資源的,再來看看docke,可看到的是它只在宿主機內安裝個Docker Engine就支持隔離多個應用,注意還是環境隔離的哦,少了兩個OS無疑是節約了巨大的資源,這兩個應用給我們的感覺就是跑在兩個不同的系統中一樣,兩者通信還要藉助特定網絡通信,但他們其實是共用的宿主機的系統,至於他們是怎麼做到隔離的這又是一個高深的話題了,看到docker有這麼多的優點是不是迫不及待的想要試一試了?

二、docker安裝及基本配置

在win7中安裝是要通過虛擬機來安裝的,在win10中就方便多了,linux下下載對應源碼編譯安裝即可,因為平時開發都是在win10上開發,故在這就簡單說一下win10安裝Docker for Windows後的配置吧,注意在win10中安裝docker for window需要有 Hyper-V 支持,不支持這個的也只能是安裝虛擬機來體驗docker了,安裝完後進入設置界面:

還不明白 Docker 的鏡像跟容器?

docker_settings

給需要共享的磁盤勾選,只有勾選了這個,容器才能訪問宿主機的文件,設置這個是需要管理員密碼的,沒設密碼的需要去設置管理員密碼,不然不能配置成功,接著就是配置鏡像加速了,docker容器是依賴鏡像(在docker裡面是image)創建的,鏡像是從遠程拉取的,就跟我們從github上拉取代碼一樣的,眾所周知國內的網路想要拉取一個鏡像是多麼的不容易,所以就需要配置鏡像加速,在Daemon那一欄的Registry mirrors 中填上加速地址就行了,一切都ok了之後就可以開始了我們喜歡的命令行敲命令了!

三、docker基本操作

 ->docker --version #查看版本 Docker version 17.09.0-ce, build afdb6d4

搜索一個image並且拉取下來

下載鏡像的命令非常簡單,使用docker pull命令即可。在docker的鏡像網站上面,鏡像都是按照"用戶名/鏡像名"的方式來存儲的。

可以使用docker images查看拉取下來的鏡像,其中IMAGE ID就是鏡像id,刪除鏡像時可以使用這個IMAGE ID刪除 docker rmi [IMAGE ID,REPOSITORY]

 ->docker search centos NAME DESCRIPTION STARS OFFICIAL AUTOMATED centos The official build of CentOS. 3824 [OK] ... ->docker pull centos #拉取鏡像 ->docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest a7876479f1aa 4 years ago 128MB ->docker rmi a7876479f1aa #刪除image

在docker容器中運行hello world,使用docker run創建一個容器,docker run之後就會產生一個容器並且保存起來,之後要運行就可以做直接運行容器而不用從新創建容器,這裡的容器就是 container,docker的容器可以理解為在沙盒中運行的進程。這個沙盒包含了該進程運行所必須的資源,包括文件系統、系統類庫、shell 環境等等。但這個沙盒默認是不會運行任何程序的。需要在沙盒中運行一個進程來啟動某一個容器。這個進程是該容器的唯一進程,所以當該進程結束的時候,容器也會完全的停止。

可以通過 docker ps 查看正在運行的容器,當我們運行docker run centos echo "hello word"後看到輸出 "hello word" 後再運行 docker ps 時沒有任何容器輸出出來,這是因為容器在運行完 echo "hello word" 後沒有運行任何進程,所以容器就退出了。通過 docker ps -a 可以查看到所有的 container

 ->docker run centos echo "hello word" #通過 centos 鏡像創建一個容器來輸出 "hello word" hello word ->docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e46ec634bbe1 centos "echo 'hello word'" 12 minutes ago Exited (0) 12 minutes ago

接下來就是給容器安裝一個簡單的程序。之前下載的是centos鏡像,所以可以使用 yum 命令來安裝程序。

備註:yum 命令執行完畢之後,容器就會停止,但對容器的改動不會丟失。但是從 image 重新 run 一個容器出來,之前安裝的程序並不存在,因為所有的修改都是針對容器 (container) 的,並不針對 image,所以從 image run 出來的容器都是一個全新的

->docker run centos yum -y install net-tools->docker ps -a #可以看到已經存在兩個 container CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2f1bbd6c30e3 centos "yum install -y ne..." 1 minutes ago Exited (0) 1 minute ago competent 35129633c933 centos "echo hello word" 1 minutes ago Exited (0) 1 minute ago dazzling

現在容器是有了,需要的程序也安裝好了,但就是隻有一個容器,不能運行又有什麼用,別急下面就來看看運行容器,但運行容器也有幾種方法,一種就是在創建容器的時候並運行,之前說過,容器要保持運行就需要一個活動的進程,當容器內所有的進程都退出了,那麼容器也就相應的停止了,所以要創建容器並保持運行容器的話很簡單,用ping命令就可以了。

->docker run centos ping lozz.cc PING lorencoll.coding.me (103.218.240.147) 56(84) bytes of data. 64 bytes from 103.218.240.147 (103.218.240.147): icmp_seq=1 ttl=37 time=16.0 ms 64 bytes from 103.218.240.147 (103.218.240.147): icmp_seq=2 ttl=37 time=16.4 ms Ctrl+C->docker ps #查看活動的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 10c5c2754279 centos "ping lozz.cc" About a minute ago Up About a minute jolly

有啟動就會有停止,停止可以用 docker stop container_id 命令來停止某個容器,好了現在開始講第二種啟動容器的方法,這種方法是在容器已經被創建的情況下使用的,我們知道每次 run 都是創建出一個新的容器,有的時候不需要創建,可以使用 docker start container_id 來啟動一個容器,這時就需要注意了,啟動後的容器沒活動的進程容器依然是會退出的,因為容器是從鏡像創建而來的,所以容器也是包含了創建這個容器的附加命令的,在 docker start 的時候又會從新執行一遍創建這個容器的附件命令,有點繞口是不是,敲一遍就知道了。

->docker ps #查看活動的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 10c5c2754279 centos "ping lozz.cc" 23 minutes ago Up 23 minutes jolly->docker ps -a #查看所有存在的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 10c5c2754279 centos "ping lozz.cc" 21 minutes ago Up 21 minutes jolly 2f1bbd6c30e3 centos "yum install -y ne..." 36 minutes ago Exited (0) 3 minute ago competent 35129633c933 centos "echo hello word" About hour ago Exited (0) hour ago dazzling# 嘗試啟動安裝了 net-tools 的容器,# -i 的意思是把信息輸出到控制檯中,沒有這個參數執行後就直接返回一個CONTAINER ID->docker start -i 2f1bbd6c30e3 Loaded plugins: fastestmirror, ovl Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.cn99.com Package net-tools-2.0-0.22.20131004git.el7.x86_64 already installed and latest version Nothing to do->docker ps #查看活動的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 10c5c2754279 centos "ping lozz.cc" 30 minutes ago Up 30 minutes jolly->docker stop 10c5c2754279 #停止執行ping命令的容器 10c5c2754279->docker start -i 10c5c2754279 #啟動執行ping命令的容器 PING lorencoll.coding.me (103.72.144.62) 56(84) bytes of data. 64 bytes from 103.72.144.62 (103.72.144.62): icmp_seq=1 ttl=37 time=15.1 ms 64 bytes from 103.72.144.62 (103.72.144.62): icmp_seq=2 ttl=37 time=16.3 ms 64 bytes from 103.72.144.62 (103.72.144.62): icmp_seq=3 ttl=37 time=16.8 ms Ctrl+C

從上面的提示就可以知道,這個 start 命令把之前創建命令 docker run centos yum -y install net-tools 中的 yum -y install net-tools 也執行了一遍,因為這個容器已經安裝過了 net-tools ,所以 yum 才提示不需要安裝,查看活動的容器中還是隻有之前的容器在運行。那麼現在有一個問題,我安裝 net-tools 的那個容器不能用了嗎,其實不然,這個容器之所以“不能用”只是因為創建的時候沒有指定合適的命令,要用它也是可以的,我們把他從新打包成一個 image 也就是鏡像,打包好了後再通過它生成容器就可以了,實際上這也符合 Docker 的應用隔離思想,把容器打包成鏡像的命令很簡單 docker commit container_id image_name,我的打包命令是 docker commit 2f1bbd6c30e3 lorenwe/centos_net_tools,這個命名是有規矩的,前面是 docker 的用戶id,如果想要把這個鏡像推送到 docker hub 這個名字就不能隨便命名了,如果不推送到 docker hub 就無所謂了,但也不能太隨便對不對。

->docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 10c5c2754279 centos "ping lozz.cc" About an hour ago jolly 2f1bbd6c30e3 centos "yum install -y ne..." About an hour ago competent 35129633c933 centos "echo hello word" About an hour ago dazzling->docker commit 2f1bbd6c30e3 lorenwe/centos_net_tools sha256:35f8073cede14473601d9f138a9815bc9ab5c7d97f914ca2f5ce910bd78b5750->docker images REPOSITORY TAG IMAGE ID CREATED SIZE lorenwe/centos_net_tools latest 35f8073cede1 23 seconds ago 277MB centos latest d123f4e55e12 2 weeks ago 197MB d4w/nsenter latest 9e4f13a0901e 14 months ago 83.8kB

就這麼簡單,一個新的鏡像(image)就創建好了,現在可以通過這個鏡像來做些有趣的事情了,依然是 docker run 命令,只不過這次多增加一些參數,如 docker run -itd --name my_net_tools lorenwe/centos_net_tools /bin/bash

其中參數 itd 分別是表示 ‘標準輸入給容器’,‘分配一個虛擬終端’,‘以守護進程方式運行(後臺)’, --name 自然是指定創建後容器的名稱了,/bin/bash 執行bash腳本,執行以上命令,就能創建一個後臺運行的容器了。

->docker run -itd --name my_net_tools lorenwe/centos_net_tools /bin/bash e1d843f7726f67d2635042695e2065b383736a341edd2e83753be9fabec03de0->docker ps #查看活動的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e1d843f7726f lorenwe/centos_net_tools "/bin/bash" 7 seconds ago my_net_tools 10c5c2754279 centos "ping lozz.cc" Up 25 minutes jolly

嗯,運行了,然後呢,當然是可以進入容器中玩玩呀,使用 docker attach container_id 進入Docker容器

->docker attach e1d843f7726f[root@e1d843f7726f /]# ip addrbash: ip: command not found[root@e1d843f7726f /]# ifconfigeth0: flags=4163 mtu 1500 inet 172.17.0.3 netmask 255.255.0.0 broadcast 0.0.0.0 ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet) RX packets 40 bytes 1900 (1.8 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0[root@e1d843f7726f /]#

這個因為這個容器是基於 centos 來的,而 docker 的基礎 centos 鏡像都是精簡版的,故很多命令沒有,比如這個 ip addr ,這也是之前選擇安裝 net-tools 的原因,因為安裝了這個就可以使用 ifconfig 來查看網卡配置。至此,是不是對 docker 有了一個基本的瞭解了呢,是不是突然來了一個靈感,比如想要搭建一個 Nginx 靜態服務器,步驟就是 pull 一個基礎鏡像下來,通過這個基礎鏡像 run 出一個容器後再容器內安裝上 Nginx 之後再從新打包成一個新的鏡像就可以了。實際上使用 docke 構建鏡像不會那樣去做,步驟繁瑣不說,還不是很靈活,畢竟之前構建的 lorenwe/centos_net_tools 鏡像也有277MB呢!分發起來不太方便,於是 Dockerfile 出現了,其作用就是通過特定的格式把一個鏡像描述出來,通過 docker 來構建出這個鏡像,描述的流程其實和之前的手動構建的流程差不多,通過同一個 Dockerfile 可以構建出一模一樣的環境,這也是 docke 常用於工作中統一系統運行環境的原因。

四、把 docker 推送到 docker hub

推送鏡像的命令很簡單,只需要 docker push image_name 就可以了,在把鏡像推送到 docker hub 之前還是有一些準備工作要做的,需要先去 docker hub 註冊一個賬號,之後再在 docker 中登入這個賬號就可以推送鏡像了。

->docker login #登入到 docker hub Login with your Docker ID to push and pull images from Docker Hub.  If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username (lorenwe): lorenwe Password: Login Succeeded # 現在就可推送鏡像到 docker hub->docker images REPOSITORY TAG IMAGE ID CREATED SIZE lorenwe/centos_net_tools latest 35f8073cede1 About an hour ago 277MB centos latest d123f4e55e12 2 weeks ago 197MB d4w/nsenter latest 9e4f13a0901e 14 months ago 83.8kB->docker push lorenwe/centos_net_tools The push refers to a repository [docker.io/lorenwe/centos_net_tools] d0ba94ecc37e: Pushed cf516324493c: Mounted from library/centos latest: digest: sha256:276814315437cf5d416ed4b5713fe10c914beaea96bcf583b786a6778c80830f size: 741

由於牆和 docker hub 的服務器離天朝遠的原因推送會很慢,成功後就能在 docker hub 的個人中心看到自己推送的鏡像了,以後想要在使用這個鏡像就可以直接 docker pull 就行了,也可以把鏡像推送到國內的容器鏡像服務平臺,比如我用的是阿里雲的容器Hub,可能是因為速度快吧所以用著舒服了,唯一不好的就是那又臭又長的鏡像名稱有點難受。

五、結語

docker 基礎到這一步已經是介紹的差不多了,寫這篇文章的目的就是用通俗易懂的語言及示例來講明 docker 鏡像與容器之間的關係,限於篇幅 docker 還有很多功能沒有介紹,日後有時間再來做後續的文章,例如 Dockerfile,docker 卷的共享和網絡通信等等都是一些特別有意思的功能,模擬構建一個可移植的分佈式的開發平臺已經不是夢了。


分享到:


相關文章: