Docker 101(一) --- 容器

weixin_34320159發表於2017-03-31

隨著雲端計算服務,Docker容器類工具也開始大行其道。雖然早有耳聞,一直不瞭解其應用場景。最近折騰應用的服務化。伺服器和應用遷移過程中,手動處理的方式太low。想到如何藉助Docker部署和釋出應用,或許是一個比較好的方式。下面是Docker初探的一些手記。可以大致熟悉docker的概念和操作。

安裝

Docker早期的版本,對於mac非常不友好。安裝還需要配合virtraulbox虛擬機器。最新的版本則只需要安裝一個dmg。然後神馬docker enginedocker-composedocker-machine都一應盡有了。

安裝完畢docker之後,點選docker的app即可啟動。執行docker info命令可以查docker的安裝和執行狀況。

映象和容器

使用docker饒不過兩個概念,映象和容器。為了易於理解,暫且把映象看成一個作業系統,只不過這個作業系統是靜態的,還沒有執行的檔案。實際上映象是特殊的檔案系統,充分利用了UnionFS技術的分成儲存架構。所謂的容器,可以理解為執行時的映象。

假如啟動了虛擬機器來安裝軟體,為了防止安裝有問題的軟體,先打了一個快照進行備份。然後每安裝一個軟體,就打一個快照備份。這些備份的檔案,就可以看成是一個個映象。如果某個軟體有問題,你需要從快照中恢復系統。選擇一個快照(映象)之後恢復系統,這個恢復的就可以看成是容器,即執行時的映象。

當然,docker實際上實現的映象和容器,並不是上述虛擬機器快照的方式。只不國他們的使用方式和效果類似罷了,初次接觸docker,暫且這麼理解。

安裝映象

既然映象是一些檔案,那麼從什麼地方獲取這些檔案呢?Docker的公司提供了一個集中式的倉庫---docker hub,儲存了大量官方或三方的映象檔案。這個網站就類似github一樣,可以自定義倉庫,然後push或者pull映象檔案。下面安裝一個最簡單的linux系統的映象。

執行docker images即可檢視本地匯入docker的映象。如果全新安裝docker,那麼首次執行該命令將看不到任何映象檔案。

☁  docker  docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

使用docker pull可以下載並匯入一個映象

☁  docker  docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
7520415ce762: Pull complete
Digest: sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f
Status: Downloaded newer image for busybox:latest
☁  docker  docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              00f017a8c2a6        2 weeks ago         1.11 MB

docker pull 命令會向倉庫網站請求映象檔案,預設是(docker hub)。下載完畢之後可以看到我們匯入了busybox的映象。映象一般由倉庫,標籤,映象id,大小等資訊。每一個映象檔案都是一個倉庫,可以給這個倉庫打tag。映象id是映象的唯一識別符號,不能重複。引用映象既可以其映象id,也可以使用倉庫:標籤的方式,例如busybox:latest,預設的標籤都是latest。當不寫標籤的時候,docker會指預設的標籤。

啟動容器

載入映象之後,我們就可以建立並啟動容器了。使用docker run命令啟動容器。

☁  docker  docker run --name hello -it busybox /bin/sh
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # echo 'hello world'
hello world

run命令有不少引數,--name表示給容器起一個名字以方便我們識別和引用。-it其實是兩個引數,分別指--interactive--tty,表示開啟一個互動式的終端服務,就行登入遠端伺服器一樣登入容器。

run 命令會檢查本地的映象,如果本地沒有就會去映象倉庫(預設是docker hub)中下載,然後再啟動容器。

容器狀態

重啟的狀態大致分為三種種,建立(Created), 執行(Up),退出(Exited)。開啟另外一個命令列,使用docker ps命令檢視容器的狀態。

☁  docker  docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
3d8f08bef033        busybox             "/bin/sh"           3 minutes ago       Up 3 minutes                            hello

可以看見和檢視映象一樣類似。每個容器也有一個容器唯一標識的id,既可以使用容器id也可以使用nama引數引用容器。此時的容器狀態是正在執行。

使用docker stop 命令停止容器

☁  docker  docker stop hello
hello
☁  docker  docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
☁  docker  docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                       PORTS               NAMES
3d8f08bef033        busybox             "/bin/sh"           5 minutes ago       Exited (137) 8 seconds ago                       hello
☁  docker  docker ps -a -q
3d8f08bef

停止容器之後,可以給ps命令新增-a-q引數,前者用來檢視所有容器的狀態,包含已經退出執行的容器(Exited)。後者可以返回容器的id。當需要批量刪除容器的時候,這個id引數很重要。

-it方式登入容器的終端,執行exit也會退出並停止容器。

容器有停止,當然就有啟動,重啟。

☁  docker  docker start 3d8f08bef033
3d8f08bef033
☁  docker  docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
3d8f08bef033        busybox             "/bin/sh"           8 minutes ago       Up 2 seconds                            hello
☁  docker  docker restart hello
hello

上面演示了除了容器name之外,使用容器的id引用容器。

容器刪除

建立了執行的容器,可以啟動也可以關閉。當容器不再使用的時候,我們可以刪除容器。刪除容器前,務必保證先關閉容器,否則刪除失敗。

☁  docker  docker rm hello
Error response from daemon: You cannot remove a running container 3d8f08bef03361155c062acc08ee0a7cfd9bc2d3914d1627e14f192ca409fc50. Stop the container before attempting removal or use -f
☁  docker  docker stop hello
hello
☁  docker  docker rm hello
hello
☁  docker  docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

進入容器

我們啟動了容器,有時候啟動了容器,然後還需要進入容器做一些動作。下面再建立一個新的容器:

☁  docker  docker run --name app -it busybox /bin/sh
/ # 
/ # exit
☁  docker  docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
☁  docker  docker start app
app
☁  docker  docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
7ece3ac215e3        busybox             "/bin/sh"           About a minute ago   Up 2 seconds                            app
☁  docker  docker exec -it app /bin/sh
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
☁  docker  docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
7ece3ac215e3        busybox             "/bin/sh"           2 minutes ago       Up About a minute                       app

使用exit退出容器,然後再用start命令啟動容器,最後使用exec命令進入容器,最後再退出。exec進入再退出和run進入退出不一樣,前者不會關閉容器,後者會關閉容器。當然,如果容器尚未啟動,docker exec是無法進入容器。

容器建立與守護執行方式

我們使用docker run命令建立並啟動了容器。其實還有一個命令只建立容器,但不啟動容器。

☁  docker  docker create --name newapp busybox  echo "hello new app"
3c5b2e39e2203052b8ee72742a1ed06f65e4c71244c98f64f8fd778bc050e171
☁  docker  docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
☁  docker  docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
3c5b2e39e220        busybox             "echo 'hello new app'"   7 seconds ago       Created                                 newapp
☁  docker  docker logs newapp
☁  docker  docker start newapp
newapp
☁  docker  docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
3c5b2e39e220        busybox             "echo 'hello new app'"   28 seconds ago      Exited (0) 3 seconds ago                       newapp
☁  docker  docker logs newapp
hello new app

上面的命令中,首先使用docker create建立了一個新的容器newapp,同時傳遞一個sh執行命令echo "hello new app"。剛建立的時候,看不到執行的容器的狀態,實際上容器建立之後尚未啟動,只是Created狀態,因此也無法中docker logs中看到容器的輸出。

當我們啟動容器的時候,執行了echo命令,因此可以看到logs有執行的輸出。可是容器執行完畢echo命令之後,就退出了。這其實很好理解,例如我們執行一個指令碼,指令碼執行完畢自然就退出了。只不過現在執行的指令碼在容器中而已,完成任務軟體自然就退出。除非容器中的指令碼或者軟體命令是以非daemon方式執行,或者執行一個永不退出的命令。

☁  docker  docker create --name always_run busybox  tail -f /dev/null
c5c6bb0acbee5d3037558defdaa54968cca3f94083dc765603caa1095f5d7466
☁  docker  docker ps -a
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS               NAMES
c5c6bb0acbee        busybox             "tail -f /dev/null"   4 seconds ago       Created                                 always_run
☁  docker  docker start always_run
newapp
☁  docker  docker ps
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS               NAMES
c5c6bb0acbee        busybox             "tail -f /dev/null"   12 seconds ago      Up 3 seconds                            always_run

上面介紹的只是容器內軟體的執行方式。實際上docker的run命令要比create常用,而run命令執行建立容器並執行,我們會登入這個容器中,一旦exit,容器就停止了。如果需要啟動容器的時候,還需要再執行start命令,為此可以給docker指定引數,讓docker的程式以daemon方式執行。

☁  docker  docker run --name deamon_app -d busybox /bin/sh -c "while true; do echo hello world; sleep 1; done"
4fb992fa3dce0c46ddabda4493924a5f0ff2c01a5cb72c1951ce6496fcb81c4f
☁  docker  docker logs -f deamon_app
hello world
hello world
hello world

檢視容器的執行狀態

docker ps可以看見docker的容器列表及其大致狀態。此外,docker還提供了statstop用來檢視docker的容器的更詳細狀態:

☁  docker  docker top deamon_app
PID                 USER                TIME                COMMAND
13253               root                0:00                /bin/sh -c while true; do echo hello world; sleep 1; done
13275               root                0:00                sleep 1
☁  docker  docker stats deamon_app
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
deamon_app          0.06%               480 KiB / 1.952 GiB   0.02%               578 B / 648 B       0 B / 0 B           2
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
deamon_app          0.05%               468 KiB / 1.952 GiB   0.02%               578 B / 648 B       0 B / 0 B           2
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS

top可以檢視docker裡容器執行的程式狀態,stats則可以看到更詳細的資訊,包含CPU,記憶體,網路等。並且top只能檢視執行的容器,stats沒有限制。

關於容器更詳細的狀態,可以使用docker inspect命令。

總結

Docker其實是一種基於LXC實現的軟體虛擬化技術。主要由倉庫,映象和容器組成完整的軟體構建方式。倉庫是儲存docker映象的檔案庫,映象是分層的包含完成作業系統的檔案,可以理解為作業系統的快照。容器則是基於映象建立的作業系統執行環境。容器的狀態分為Created,Up,Eixited。

我們介紹了不少命令用於操作容器。接下來,再探索一下關於映象相關的操作。

相關文章