---
# System prepended metadata

title: Docker 使用容器(Container)

---

# Docker 使用容器(Container)


++docker 程序是否存在，功能是否正常++
`docker info`
++新建並啟動++
```
docker run hello-world  
docker run ubuntu /bin/echo 'Hello world'
```
++啟動一個 bash 終端，允許使用者進行互動++
`docker run -i -t ubuntu /bin/bash`
* -t 選項讓 Docker 分配一個虛擬終端（pseudo-tty）並綁定到容器的標準輸入上。
* -i 則讓容器的標準輸入保持打開。
 
++查看系統中的容器列表++
`docker ps -a`

只看執行中的
`docker ps`
++指定容器名稱++
有名稱方便重覆使用

`docker run --name my_ubuntu -i -t　-v $PWD/website:/var/www/html/website ubuntu /bin/bash`
* –name <指定名稱> : 可用字元 [a-zA-Z0-9_.-]。
* -v：掛載本地的目錄到容器中的目錄 - 重要的能力。在 Docker Toolbox 中只有 Users 目錄有權限。
* 
++啟動已終止容器++
`docker start my_ubuntu`
用 ID 也可以

`docker start ac3f3b5f0f4e`

++進入已啟動的容器++
重新啟動後，要 再進入 才能進行操作

`docker attach my_ubuntu`
* attach 會接到啟動時指定的 /bin/bash 實例。所以多個視窗同時 attach 到同一個容器的時候，所有視窗都會同步顯示。
* 從 stdin 中 exit， 會導致容器停止。

`docker exec -i -t my_ubuntu /bin/bash`
* 如果啟動時沒有下 /bin/bash，就要用 exec 去建立 bash 的實例。
* 從 stdin 中 exit， 不會導致容器停止。

++以守護態(Daemonized)執行++
`docker run -d --name my_ubuntu2 ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"`
* -d 參數 : 以守護態執行。
* -c 要執行的命令串。
* 只返回 ID。
* 輸出訊息不輸出到 Stdout 了。
* -p : 將容器內應甪程式的對外 port 對應到主機的 port，如 Oracle 為 -p 1521:1521

++取得容器的輸出訊息++
```
docker logs my_ubuntu2
docker logs -t -f --tail 10 my_ubuntu2
```
* -t : 加上時間。
* -f : 持續列出最新。
* –tail 10 : 只列最後 10 筆。
 
++停止容器++
`docker stop my_ubuntu2`

++查看容器內的進程++
`docker top my_ubuntu`
++容器的統計信息++
`docker stats my_ubuntu my_ubuntu2`
* 可以列表方式看到多個內容。

++取得容器的詳細資訊++
`docker inspect my_ubuntu`
* 配合 -f 或 –format 來選定結果，如以下取得 ip address

`docker inspect --format '{{ .NetworkSettings.IPAddress }}' my_ubuntu`
* –format 支持完整的 Go 語言模板。

++刪除容器++
`docker rm my_tmp_ubuntu`
* 加上 -f 參數 : 刪除執行中的容器。

++刪除全部容器++

> docker rm `sudo docker ps -a -q`
* -q : 只回容器 ID。

## 映像檔(Image) 及 倉庫(Repository)


++倉庫++
包括映像檔，層及關於映像檔的資訊(metadata)。

每個倉庫可以存放很多映像檔(不同版本)，如 ubuntu 12.04 16.04 18.04，利用 TAG 功能就可以指定到特定映像檔，如 ubuntu:16.04。

Docker Hub 的用戶倉庫命名由用戶名和倉庫名組成，如 john/shoppingweb; 頂層倉庫則只包含倉庫名，如 ubuntu。

列出映像檔
docker images
列出特定映像檔

docker images ubuntu
拉取映像檔
docker pull httpd
當 run 的時候本機還沒有所需的映像檔就會執行拉取。
查詢 Docker Hub 上可用映像檔
docker search aspnetcore
建立映像檔
用 docker commit 建立異動過的映像檔
如，在 my_ubuntu 中加入 apache2 後

docker commit 4aab3ce3cb76 user1/apache2
4aab3ce3cb76 : 容器 ID。
user1/apache2 : 用戶倉庫名。
commit 提交的只是建立時的映像檔和現在況態有差異的部份。
docker commit -m "Added apache" -a "Docker Newbee" 4aab3ce3cb76 user1/apache2:v2
-m : 說明訊息。
-a : 更新的使用者訊息。
已不推薦使用 docker commit 方法，最好用 Dockerfile。

用 Dockerfile 來構建映像檔
建立一個目錄做為構建環境。
編寫 Dockerfile 文字檔 : Dockerfile 由一系列指令和參數組成。
以 docker build 基於 Dockerfile 進行構建。
-t : 映像檔名稱
例子:

Dockerfile

# Version: 0.0.1　
FROM ubuntu:16.04
MAINTAINER John Wick "john@example.com"
RUN apt-get update && apt-get install -y nginx　
RUN echo 'Hi, I am in your container' > /usr/share/nginx/html/index.html　
EXPOSE 80
docker build

docker build -t="user1/static_web" .
最後的 . 指定 Dockerfile 在同目錄中。
Dockerfile 的路徑可以是 Git repository 根目錄 : git@github.com:user1/docker-static_web。
Dockerfile 可以在子目錄中且不用叫 Dockerfile : path/to/file。
錯誤處理
可以用 docker run 執行失敗的映像檔到已成功的部份，再手動執行出錯的命令做調試，找到正確的命令。

不使用暫存資料
構建過程中，沒問題的映像會被暫存下來以加快下次執行，如果要它重頭執行不用暫存資料，加上 --no-cache。

docker build --no-cache -t="user1/static_web" .
Dockerfile
Dockerfile 由一系列指令和參數組成。每條指令，如 FROM，都必須為大寫字母，且後面要跟隨一個參數：FROM ubuntu:14.04。
Dockerfile 中的指令會按順序從上到下執行，所以應該根據需要合理安排指令的順序。

每條指令都會創建一個新的文件層並對映像檔進行提交。Docker 大體上按照如下流程執行 Dockerfile 中的指令。

Docker 從基礎映像檔運行一個容器。
執行一條指令，對容器做出修改。
執行類似 docker commit 的操作，提交一個新的文件層。
Docker 再基於剛提交的映像檔運行一個新容器。
執行 Dockerfile 中的下一條指令，直到所有指令都執行完畢。
註解
以 # 開頭的就是註解內容

FORM
第一條指令必須是 FROM，也是唯一必填指令。
FROM 指定一個已經存在的映像檔，後續指令都將基於該映像檔進行，這個映像檔被稱為基礎映像檔(base iamge)。

FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>
如:
FROM ubuntu:14.04。

MAINTAINER
映像檔作者資訊

MAINTAINER <作者資訊>
如:
MAINTAINER John Wick
MAINTAINER John Wick “john@example.com”

RUN
在映像檔中執行命令

RUN <command>
RUN ["executable", "param1", "param2"]
RUN \：後面的命令其實是由 /bin/sh -c 來負責執行，所以，在映像檔中必須要有/bin/sh。
RUN [“executable”,”param1”,”param2”]：可以執行映像檔中任意一個可執行檔或命令，[]中的內容都會按照 JSON 字串的格式進行解析，因此只能使用雙引號 “。如用 bash 來執行:
RUN ["/bin/bash", "-c", "echo hello"]
命令產生的結果預設會被後續所有指令重用。
CMD
用來設定映像檔預設執行命令

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2
第 1 種用法：是推薦的用法，其設定的命令將作為容器啟動時的預設執行命令。
第 2 種用法：param 將作為 ENTERPOINT 的預設參數使用。
第 3 種用法：將後面的命令作為 shell 命令，依靠 /bin/sh –C 來執行。
可以有多個 CMD，但只有最後一個 CMD 會生效。
LABEL
用鍵值對的形式來向映像檔中添加元數據(metadata)

LABEL <key>=<value> <key>=<value> <key>=<value> ...
如：
LABEL version=”1.0”

執行完命令之後，同樣會產生一個新的文件層。
新值會覆蓋舊值。
可以用 Docker 的 inspec 命令查詢。
EXPOSE
通知 Docker 容器中哪些端口是應用程序開出來監聽

EXPOSE <port> [<port>...]
容器啟動時配合 -p 或 -P 參數外部網路才可以訪問到這個 port。
ENV
設定環境變量

ENV <key> <value>
ENV <key>=<value> ...
第 2 種用法：value 中存在空格時，需要使用「\」來進行轉義，如：ENV myDog=Rex\ The\ Dog \。
可以用 Docker 的 inspec 命令查詢。
COPY
向容器中指定路徑下添加文件

COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
src 指定的路徑必須存在於 Dockerfile 所在目錄
如果使用 STDIN 輸入 Dockerfile 內容，那麼 COPY 命令將失效
ADD
將 src 標記的文件，添加到容器中 dest 所標記的路徑中去

ADD <src>... <dest>
ADD ["<src>",... "<dest>"]
src 指定的路徑必須存在於 Dockerfile 所在目錄或指定外部 URL。
dest 是指向容器中的目錄，其路徑必須是絕對路徑，或相對於 WORKDIR 的相對路徑。
dest 有沒有以 “/“ 結尾會影響資料寫入的目的地。src 使用通配字元指定多個文件時，dest 必須以 “/“ 結尾的目錄。
ENTRYPOINT
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
設定容器運行時預設執行程序

第 2 種用法：將後面的命令作為 shell 命令，依靠 /bin/sh –C 來執行。
如，MySQL官方提供的Dockerfile :

...
COPY Docker-entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
EXPOSE 3306
CMD ["mysqld"]
當 mysql 容器運行時，自動執行 /entrypoint.sh，而參數則是 mysqld

VOLUMN
在容器內部創建一個指定名稱的掛載點

VOLUME ["/data"]
如果在 Dockerfile 中已經聲明了某個掛載點，那麼以後對此掛載點中文件的操作將不會生效。
因此，通常只會在 Dockerfile 的結尾處聲明掛載點。
USER
切換用戶身份。當執行完命令後，後面所有的命令都將以新用戶的身份來執行

USER daemon
WORKDIR
切換當前工作目錄

WORKDIR /path/to/workdir
影響到後續的 RUN、CMD、ENTRYPOINT、COPY和ADD指令中的路徑。
可以在 Dockerfile 中出現多次，但最終生效的路徑是所有 WORKDIR 指定路徑的疊加 (使用相對路徑時)。
只可以使用 ENV 設定的環境變量值。
ONBUILD
建立觸發命令集

ONBUILD [INSTRUCTION]
觸發命令集在當前 Dockerfile 執行過程中不會執行，而當此鏡像被其他鏡像當作基礎鏡像使用時，將會被觸發執行。