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

1、docker 是什麼

Docker是一個開源的引擎,能夠輕鬆的爲任何應用建立一個輕量級的、可移植的、自給自足的容器。開發者在本身機器上編譯測試經過的容器能夠批量地在生產環境中部署,包括VMs(虛擬機)、bare metal、OpenStack 集羣和其餘的基礎應用平臺。這是docker的百度百科定義,看完這個好像並不能說明docker有什麼用,不要緊,對比一下就知道了,首先說明,這篇文章不會涉及很深奧的內容,旨在用通俗易懂的話語來闡述docke的優勢及其基礎用法。咱們都用過虛擬機吧,第一映像確定是笨重,啓動慢,固然功能上是徹底無可挑剔的,但這還不夠,因而docker橫空出世,還有什麼語言能比圖片更能說明一切呢?linux

docker
docker

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

2、docker安裝及基本配置

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

docker_settings
docker_settings

給須要共享的磁盤勾選,只有勾選了這個,容器才能訪問宿主機的文件,設置這個是須要管理員密碼的,沒設密碼的須要去設置管理員密碼,否則不能配置成功,接着就是配置鏡像加速了,docker容器是依賴鏡像(在docker裏面是image)建立的,鏡像是從遠程拉取的,就跟咱們從github上拉取代碼同樣的,衆所周知國內的網路想要拉取一個鏡像是多麼的不容易,因此就須要配置鏡像加速,在Daemon那一欄的Registry mirrors 中填上加速地址就好了,我習慣是使用阿里雲的 ' otsyn80i.mirror.aliyuncs.com ' 加速地址,一切都ok了以後就能夠開始了咱們喜歡的命令行敲命令了!docker

3、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]shell

 ->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 能夠查看到全部的 containerwindows

 ->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 出來的容器都是一個全新的centos

->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命令就能夠了。bash

->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 addr
bash: ip: command not found
[root@e1d843f7726f /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  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 0

lo: flags=73<UP,LOOPBACK,RUNNING>  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 經常使用於工做中統一系統運行環境的緣由。

4、把 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,多是由於速度快吧因此用着舒服了,惟一很差的就是那又臭又長的鏡像名稱有點難受。

5、結語

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

相關文章
相關標籤/搜索