# 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 執行過程中不會執行,而當此鏡像被其他鏡像當作基礎鏡像使用時,將會被觸發執行。