Skip to main content

第 1 章:建立管理與終止容器

啟動 docker run

例如,下面的命令輸出一個 “Hello World”,之後終止容器。

sudo docker run ubuntu:14.04 /bin/echo 'Hello world'

Hello world

這跟在本地直接執行 /bin/echo 'hello world' 相同, 幾乎感覺不出任何區別。

下面的命令則啟動一個 bash 終端,允許使用者進行互動。

sudo docker run -t -i ubuntu:14.04 /bin/bash

root@af8bae53bdd3:/#
  • -t 選項讓Docker分配一個虛擬終端(pseudo-tty)並綁定到容器的標準輸入上-i 則讓容器的標準輸入保持打開

在互動模式下,使用者可以透過所建立的終端來輸入命令,例如

ls

bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

當利用 docker run 來建立容器時,Docker 在後臺執行的標準操作包括:

  • 檢查本地是否存在指定的映像檔,不存在就從公有倉庫下載
  • 利用映像檔建立並啟動一個容器
  • 分配一個檔案系統,並在唯讀的映像檔層外面掛載一層可讀寫層
  • 從宿主主機設定的網路橋介面中橋接一個虛擬埠到容器中去
  • 從位址池中設定一個 ip 位址給容器
  • 執行使用者指定的應用程式
  • 執行完畢後容器被終止

啟動已終止容器 docker start

容器的核心為所執行的應用程式,所需要的資源都是應用程式執行所必需的。除此之外,並沒有其它的資源。可以在虛擬終端中利用 pstop 來查看程式訊息。

ps
PID TTY TIME CMD
1 ? 00:00:00 bash
11 ? 00:00:00 ps

可見,容器中僅執行了指定的 bash 應用。這種特點使得 Docker 對資源的使用率極高,是貨真價實的輕量級虛擬化。

常駐執行

更多的時候,需要讓 Docker 容器在後臺以常駐(Daemonized)形式執行。此時,可以透過新增 -d 參數來實作。

例以下面的命令會在後臺執行容器。

sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"

1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147

容器啟動後會回傳一個唯一的 id,也可以透過 docker ps 命令來查看容器訊息。

sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

1e5535038e28 ubuntu:14.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute insane_babbage

要取得容器的輸出訊息,可以透過 docker logs 命令。

sudo docker logs insane_babbage

hello world
hello world
hello world
. . .

進入容器

在使用 -d 參數時,容器啟動後會進入背景執行。 某些時候需要進入容器進行操作,有很多種方法,包括使用 docker attach 命令或 nsenter 工具等。

exec 命令

docker exec 是Docker內建的命令。下面示範如何使用該命令。

sudo docker run -idt ubuntu

243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550

sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
243c32535da7 ubuntu:latest "/bin/bash" 18 seconds ago Up 17 seconds nostalgic_hypatia

sudo docker exec -ti nostalgic_hypatia bash

attach 命令

docker attach 亦是 Docker 內建的命令。下面示例如何使用該命令。

sudo docker run -idt ubuntu

243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550

sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

243c32535da7 ubuntu:latest "/bin/bash" 18 seconds ago Up 17 seconds nostalgic_hypatia

sudo docker attach nostalgic_hypatia

按下 ctrl + P 然後 ctrl + Q 跳離容器,讓它繼續在背景執行。

但是使用 attach 命令有時候並不方便。當多個視窗同時 attach 到同一個容器的時候,所有視窗都會同步顯示。當某個視窗因命令阻塞時,其他視窗也無法執行操作了。

nsenter 命令

nsenter 安裝

nsenter 工具已含括在 util-linux 2.23 後的版本內。 如果系統中 util-linux 包沒有該命令,可以按照下面的方法從原始碼安裝。

cd /tmp; curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-; cd util-linux-2.24;

./configure --without-ncurses

make nsenter && sudo cp nsenter /usr/local/bin

nsenter 使用

nsenter 可以存取另一個程式的命名空間。nsenter 要正常工作需要有 root 權限。 很不幸,Ubuntu 14.4 仍然使用的是 util-linux 2.20。安裝最新版本的 util-linux(2.24)版,請按照以下步驟

wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz; tar xzvf util-linux-2.24.tar.gz

cd util-linux-2.24

./configure --without-ncurses && make nsenter

sudo cp nsenter /usr/local/bin

為了連線到容器,你還需要找到容器的第一個程式的 PID,可以透過下面的命令取得。

PID=$(docker inspect --format "{{ .State.Pid }}" <container>)

透過這個 PID,就可以連線到這個容器:

nsenter --target $PID --mount --uts --ipc --net --pid

下面給出一個完整的例子。

sudo docker run -idt ubuntu

243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550

sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

243c32535da7 ubuntu:latest "/bin/bash" 18 seconds ago Up 17 seconds nostalgic_hypatia

PID=$(docker-pid 243c32535da7)

10981

sudo nsenter --target 10981 --mount --uts --ipc --net --pid

更簡單的,建議大家下載 .bashrc_docker,並將內容放到 .bashrc 中。

wget -P ~ https://github.com/yeasy/docker_practice/raw/master/_local/.bashrc_docker;

echo "[ -f ~/.bashrc_docker ] && . ~/.bashrc_docker" >> ~/.bashrc; source ~/.bashrc

這個檔案中定義了很多方便使用 Docker 的命令,例如 docker-pid 可以取得某個容器的 PID;而 docker-enter 可以進入容器或直接在容器內執行命令。

echo $(docker-pid <container>)

docker-enter <container> ls

匯出容器

如果要匯出本地某個容器,可以使用 docker export 命令。

sudo docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

7691a814370e ubuntu:14.04 "/bin/bash" 36 hours ago Exited (0) 21 hours ago test

sudo docker export 7691a814370e > ubuntu.tar

這樣將匯出容器快照到本地檔案。

匯入容器快照

可以使用 docker import 從容器快照檔案中再匯入為映像檔,例如

cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0

sudo docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

test/ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB

此外,也可以透過指定 URL 或者某個目錄來匯入,例如

sudo docker import http://example.com/exampleimage.tgz example/imagerepo
  • 註:使用者既可以使用 docker load 來匯入映像檔儲存檔案到本地映像檔庫,也可以使用 docker import 來匯入一個容器快照到本地映像檔庫。這兩者的區別在於容器快照檔案將丟棄所有的歷史記錄和原始資料訊息(即僅保存容器當時的快照狀態),而映像檔儲存檔案將保存完整記錄,檔案體積也跟著變大。此外,從容器快照檔案匯入時可以重新指定標籤等原始資料訊息。

終止容器

可以使用 docker stop 來終止一個執行中的容器。

此外,當Docker容器中指定的應用終結時,容器也自動終止。 例如對於上一章節中只啟動了一個終端機的容器,使用者透過 exit 命令或 Ctrl+d 來退出終端時,所建立的容器立刻終止。

終止狀態的容器可以用 docker ps -a 命令看到。例如

sudo docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

ba267838cc1b ubuntu:14.04 "/bin/bash" 30 minutes ago Exited (0) About a minute ago trusting_newton

98e5efa7d997 training/webapp:latest "python app.py" About an hour ago Exited (0) 34 minutes ago backstabbing_pike

處於終止狀態的容器,可以透過 docker start 命令來重新啟動。

此外,docker restart 命令會將一個執行中的容器終止,然後再重新啟動它。

刪除容器

可以使用 docker rm 來刪除一個處於終止狀態的容器。 例如

sudo docker rm  trusting_newton

trusting_newton

如果要刪除一個執行中的容器,可以新增 -f 參數。Docker 會發送 SIGKILL 訊號給容器。

附註:透過 Docker Desktop 建立容器

  1. 我們要有一個映像檔來建立容器,可以透過 git 來下載或是瀏覽器直接下載

  2. 查看專案資料夾中的 Dockerfile

    • Dockerfile 描述將使用哪個映像檔,以及建立什麼樣的容器環境
  3. 設定映像檔

    • 在終端機中執行以下命令來建立映像檔
    • -t 標誌會以名稱標記您的映像, 還有 . 讓 Docker 知道在哪裡可以找到 Dockerfile
    cd /path/to/welcome-to-docker/
    docker build -t welcome-to-docker .
    • 提示
      • 要執行 Docker 命令,您必須使用終端機
        • 對於 Windows,選擇「開始」功能表,指定 cmd,然後選擇「命令提示字元」
        • 對於 Mac,選擇 Dock 中的 Launchpad 圖標,在搜尋欄位中指定終端 (terminal)
  4. 運行容器

    • 在 Docker Desktop 中,前往 Image 映像標籤
    • 在圖像旁邊,選擇運行
    • 展開可選設定,在主機連接埠中指定 8089,選擇運行
  5. 查看前端

附註:使用 Docker Hub 建立容器

Docker Hub 就是前面提到的 Registry 倉庫,可以在上面儲存與分享映像檔

  1. 搜尋映像檔
    1. 在 Docker Desktop 上搜尋 Docker Hub 映像:docker/welcome-to-docker
  2. 建立容器
    1. 運行 docker/welcome-to-docker 映像在主機連接埠中,指定 8090 選擇運行