天天看點

四、【Docker筆記】Docker容器

容器是Docker的另一個核心概念,容器就是鏡像的一個運作執行個體,隻是它具有一個可寫的檔案層,而鏡像是一個隻讀的檔案。

一、建立容器

1、建立容器

我們可以使用 docker create 指令來建立一個容器。需要注意的是,此時建立的容器處于停止狀态,若想讓這個容器運作,則需要使用 docker start 指令。

# 0. 檢視本地有哪些鏡像
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              4e5021d210f6        2 weeks ago         64.2MB

# 1. 建立容器(第一步)
$ sudo docker create -ti ubuntu:latest
bb9c6f31d79d40f10e2fefbde17af35cd8457746211f214479258accab86dbc0

# 2. 檢視所有容器,此時容器狀态為 Created
$ sudo docker ps -a
CONTAINER ID   IMAGE         COMMAND      CREATED      STATUS   PORTS    NAMES
bb9c6f31d79d  ubuntu:latest  "/bin/bash" 7 seconds ago Created       flamboyant_almeida

# 3. 運作容器(第二步)
$ sudo docker start bb9c6f31d79d
bb9c6f31d79d

# 4. 檢視容器,此時容器狀态為UP
$ sudo docker ps -a
CONTAINER ID   IMAGE         COMMAND      CREATED      STATUS     PORTS    NAMES
bb9c6f31d79d  ubuntu:latest  "/bin/bash" 7 seconds ago UP 5 seconds   flamboyant_almeida
           

2、建立并啟動容器

在上一小節中,我們運作一個容器需要做兩步走,先建立再運作。其實這兩步,我們可以使用 docker run 這一個指令來代替上面的兩個步驟。

# 0. 檢視所有容器
$ sudo docker ps -a
CONTAINER ID   IMAGE         COMMAND      CREATED      STATUS     PORTS    NAMES
bb9c6f31d79d  ubuntu:latest  "/bin/bash" 7 seconds ago UP 5 seconds   flamboyant_almeida

# 1. 運作一個容器,并立刻退出
$ sudo docker run ubuntu /bin/echo 'Hello World...'
Hello World...

# 2. 檢視容器
 docker ps -a
CONTAINER ID   IMAGE       COMMAND      CREATED      STATUS       PORTS    NAMES
924e13b84e9f  ubuntu  "/bin/echo 'Hello Wo…" 6s ago  Exited (0) 4 s ago loving_shannon
bb9c6f31d79d  ubuntu:latest  "/bin/bash" 7 seconds ago UP 5 seconds   flamboyant_almeida
           

當然,我們也可以在運作容器的時候,進入到容器内部,對容器進行操作。

# 0. 運作容器并進入
$ sudo docker run -t -i ubuntu:latest /bin/bash
root@c6198d442bf9:/#

# 1. 對容器進行操作
root@c6198d442bf9:/# pwd
/
root@c6198d442bf9:/# ps
   PID TTY          TIME CMD
     1 pts/0    00:00:00 bash
    10 pts/0    00:00:00 ps
root@c6198d442bf9:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 2. 退出容器
root@c6198d442bf9:/# exit
exit

# 3. 檢視剛才的容器狀态為Exited
$ sudo docker ps -a
           

3、容器的守護态運作

其實大多數時候,我們運作容器後都不會一直處于容器操作狀态的,會讓容器在作業系統背景運作,此時的容器就是處于守護态運作。這種啟動方式就是在 docker run 運作時添加一個 -d 參數來實作。

# 在背景運作一個容器,該容器每一秒列印一串字元
$ sudo docker run -d ubuntu:latest /bin/bash -c "while true; do echo hello world; sleep 1; done"
60b6384109fd350bc97040039277058428ffc0f7492cc22338f95be8357ea482

# 檢視目前正在運作的容器
$ sudo docker ps
CONTAINER ID      IMAGE    COMMAND         CREATED             STATUS      PORTS    NAMES
60b6384109fd ubuntu:latest "/bin/bash -c 'while…"8 seconds ago  Up 6 seconds keen_swirles
           

從上面的狀态可以看到目前容器處于 UP狀态,那麼如何檢視該容器是否在列印字元串呢?可以使用 docker logs指令。

# 檢視目前容器的輸出資訊
$ sudo docker logs 60b6384109fd
hello world
hello world
hello world
....
           

二、終止容器

當容器運作了一段時間後,對于該容器我們不再需要了,那麼就需要終止容器,可以使用 docker stop 指令來終止一個正在運作的容器,文法為:docker stop [-t|--time[=10]]。它的執行邏輯為:首先會向容器發送SIGTERM信号,等待一段時間後(預設10s),再發送SIGKILL信号終止容器。除了我們直接終止容器,當Docker容器中指定的應用終結時,容器也會自動的終止。在上一小節中,當我們處于容器中時,用 exit 指令退出容器也會将容器給終止。

# 終止我們上一小節中正在運作的守護态容器
$ sudo docker stop 60b6384109fd
60b6384109fd

# 此時檢視正在運作的容器已經沒有了
$ sudo docker ps
...
           

當終止容器後,一段時間後,我們希望将剛才終止的容器再次啟動,則使用 docker start 指令。

# 0. 檢視目前終止的容器
$ sudo docker ps -a -q
60b6384109fd

# 1. 将終止的容器再次啟動
$ sudo docker start 60b6384109fd
60b6384109fd

# 2. 檢視目前正在運作的容器,發現 60b6384109fd 該容器狀态又處于 UP
$ sudo docker ps
           

若我們希望将一個正在運作的容器重新開機,則可使用 docker restart 指令。

# 重新開機容器
$ sudo docker restart 60b6384109fd
           

三、進入容器

在守護态運作容器時,此時容器處于作業系統的背景運作,此時我們想進入容器内部進行操作,可以通過以下集中方式。

1、attach指令

該指令時Docker自帶的一個指令。此指令存在一個缺點,即當我們打開多個視窗進入容器中,當其中一個視窗在操作容器,其他視窗也會将這些操作資訊給同步的顯示,若此時其中一個視窗處于阻塞狀态,則所有視窗都不可操作容器。若在容器中執行 exit 指令,則容器終止運作。

# 進入上一節中運作運作态容器中
$ sudo docker attach c6198d442bf9 #(容器ID或容器名稱)
root@c6198d442bf9:/#
           

2、exec指令

該指令是 Docker1.3版本新提供的,可有效解決 attach指令存在的問題。

# 進入正在運作的容器内部,哪怕在容器内執行 exit 退出容器,此時容器也不會終止
$ sudo docker exec -ti c6198d442bf9 /bin/bash
root@c6198d442bf9:/#
           

3、nsenter工具

該工具在 util-linux包2.23版本中,若沒有該包則需要安裝。同時,使用該工具連接配接容器,需要知道容器的程序的PID。

# 0. 查詢目前運作态的容器
$ sudo docker ps
#得到容器ID為 bb9c6f31d79d

# 1. 查詢該容器的PID
$ sudo echo PID=$(docker inspect --format "{{ .State.Pid}}" bb9c6f31d79d)
PID=1525

# 2. 通過nsenter工具進入容器
$ sudo nsenter --target 1525 --mount --uts --ipc --net --pid
root@bb9c6f31d79d:/#

# 3. 使用 exit 退出容器後,容器不終止
           

四、删除容器

對于确定不在需要的容器,可以将其删除,注意删除容器之前将容器給終止。文法:docker rm [options] container [container...],可以一次删除多個容器。options選項包含:

-f,--force=false 強行終止并删除一個運作中的容器(不推薦使用)

-l,--link=false 删除容器的連接配接,但保留容器

-v,--volumes=false 删除容器挂載的資料卷

# 0. 檢視所有容器
$ sudo docker ps -a
60b6384109fd    Exited (137) 47 minutes ago
c6198d442bf9    Exited (0) 30 minutes ago
924e13b84e9f    Exited (0) About an hour ago
bb9c6f31d79d    Up About an hour

# 1. 删除終止的容器
$ sudo docker rm 60b6384109fd c6198d442bf9 924e13b84e9f
60b6384109fd
c6198d442bf9
924e13b84e9f

# 2. 二次檢視所有容器
$ sudo docker ps -a
bb9c6f31d79d    Up About an hour

# 3. 删除正在運作的容器(錯誤做法)
$ sudo docker rm bb9c6f31d79d
Error response from daemon: You cannot remove a running container bb9c6f31d79d40f10e2fefbde17af35cd8457746211f214479258accab86dbc0. Stop the container before attempting removal or force remove

# 4. 強制删除正在運作的容器
$ sudo docker rm -f bb9c6f31d79d
bb9c6f31d79d

# 5. 至此,所有容器删除完成
$ sudo docker ps -a
null
           

五、導入和導出容器

1、導出容器

導出容器即将一個已經建立的容器導出到一個檔案,不管此時容器是否處于運作中,都可以使用 docker export 指令來導出。

# 0. 建立并啟動一個容器,建立一個容器但不啟動
$ sudo docker run -tid ubuntu:latest /bin/bash
4418f9c3e13a30e551a2a33d2e2c7cf73a122688aa09ca86a97f4ee8885d74a7
$ sudo docker create ubuntu:latest
4f3f1fe5bd66125b5e2c6693cefec4c403d396d5c2bd678f8371c38131611ddf

# 1. 将兩個容器導出
$ sudo docker export 4f3f1fe5bd66 > no_run_container.tar
$ sudo docker export 4418f9c3e13a > run_container.tar

# 說明:此時這兩個容器對應的tar,我們就可以将其放到其他機器上通過導入來使用。這即實作了容器的遷移。
           

2、導入容器

對于容器導出的檔案,我們可以使用 docker import 指令來導入,使其成為鏡像。

# 0. 導入檔案,成為鏡像
$ cat run_container.tar | sudo docker import - test/ubuntu:v1.0
sha256:0f5b15a68f7640467f842635ec567bbd97dfc9485ff3d0eb083c6ad0781d7b3b

# 1. 檢視鏡像
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test/ubuntu         v1.0                0f5b15a68f76        4 seconds ago       64.2MB
           

說明:在前面我們使用過一個 docker load 指令來導入檔案。這兩者都可以實作導入,不過load體積更大,導入的鏡像存儲檔案更徹底,而import導入的隻是一個容器快照,它将丢棄所有的曆史記錄和中繼資料資訊。