本文剖析Docker内的基本指令
一、基礎指令
1.運作一個鏡像
[root@bogon ~]# docker run debian echo "Hello World"
Unable to find image 'debian:latest' locally
latest: Pulling from library/debian
3e17c6eae66c: Pull complete
Digest: sha256:2e43e863a4ab6e53caf87a37d01d8c144cdcb732ad1b944fcf45cbfd7248a02a
Status: Downloaded newer image for debian:latest
Hello World
提供一個容器中的shell
[root@bogon ~]# docker run -i -t debian /bin/bash
root@1bd73131a553:/# echo "Hello from Container-land!"
Hello from Container-land!
root@1bd73131a553:/# exit
exit
2.運作案例分析
1)docker pull
Docker Daemon從Docker Registry下載下傳指定的容器鏡像,并将鏡像儲存在本地Graph中。
流程分析:
A.Docker Client處理使用者發起的docker pull指令,解析完請求以及參數後,發送一個HTTP請求給Docker Server,HTTP請求方法為POST,請求URI為“/images/create?”+“xxx”;
B.Docker Server接收以上HTTP請求,并交給mux.Router,通過URL以及請求方式類型來确定執行該請求的具體handler;
C.mux.Router将請求路由分發至相應的handler;
D.在PostImageCreate這個handler中,建立并初始化一個名為“pull”的Job,之後觸發執行該Job;
E.這個Job在執行過程中執行pullRepository操作,即從Docker Registry中下載下傳相應的一個或多個Docker鏡像;
F.這個Job将下載下傳的Docker鏡像交給graphdriver管理;
G.graphdriver負責存儲Docker鏡像,一方面将鏡像存儲至本地檔案系統中,另一方面為鏡像建立對象,由Docker Daemon統一管理。
2)docker run
建立一個全新的Docker容器,并在容器中運作指定指令。
- 建立Docker容器對象,并為容器準備所需的rootfs;
- 建立容器的運作環境,運作使用者指令;
A.Docker Client處理使用者發起的docker run指令,解析完請求與參數之後,向Docker Server發送一個HTTP請求,HTTP請求方式為POST,請求URL為“/containers/create?”+“xxx”;(建立容器對象而非實際容器)
D.在PostContainersCreate這個handler中,建立并初始化一個名為“create”的Job,之後觸發執行該Job;
E.這個Job在執行過程中執行Container.Create操作,該操作需要擷取容器鏡像來為Docker容器準備rootfs,通過graphdriver完成;
F.graphdriver從Graph中擷取建立Docker容器rootfs所需要的所有鏡像;
G.graphdriver将rootfs的所有鏡像通過某種聯合檔案系統的方式加載至Docker容器指定的檔案目錄中;
H.若以上操作正常執行,沒有傳回錯誤或異常,則Docker Client收到Docker Server傳回狀态後,發起二次HTTP請求,URL為“/containers/”+container_ID+“/start”;(實作實體容器運作)
I.Docker Server接收以上HTTP請求,并交給mux.Router,通過URL以及請求方式類型來确定執行該請求的具體handler;
J.mux.Router将請求路由分發至相應的handler;
K.在PostContainersStart這個handler中,建立并初始化一個名為“start”的Job,之後觸發執行該Job;
L.這個Job執行需要完成一系列與Docker容器相關的資源配置工作;
M.networkdriver為指定的Docker容器配置設定網絡資源,防火牆規則
N.傳回名為“start”的Job,執行完一些輔助操作後,Job開始執行使用者指令,調用execdriver;
O.execdriver被調用,開始初始化Docker容器内部的運作環境,如命名空間、資源控制與隔離,以及使用者指令的執行,相應的操作轉交至libcontainer來完成;
P.libcontainer被調用,完成Docker容器内部的運作環境初始化,并最終執行使用者要求啟動的指令。
3.常用指令解析
1)啟動容器
[root@bogon ~]# docker run -h CONTAINER -i -t debian /bin/bash
root@CONTAINER:/#
-h 設定新的主機名(hostname)
2)檢視容器
為了測試,我将容器搞壞了
root@CONTAINER:/# mv /bin /basket
root@CONTAINER:/# ls
bash: ls: command not found
現在檢視狀态
[root@bogon ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8f64d43a4e26 debian "/bin/bash" 2 minutes ago Up 2 minutes competent_euclid
通過NAMES擷取容器資訊
[root@bogon ~]# docker inspect competent_euclid
[
{
"Id": "8f64d43a4e26dbe29626f82feb7aafc759fe805699f0f014aaf3b2be82790c82",
"Created": "2017-10-23T13:47:20.594553293Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 2662,
"ExitCode": 0,
"Error": "",
"StartedAt": "2017-10-23T13:47:20.855942407Z",
"FinishedAt": "0001-01-01T00:00:00Z"
...省略部分
過濾相關内容
[root@bogon ~]# docker inspect competent_euclid |grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
[root@bogon ~]# docker inspect --format {{ .NetworkSettings.IPAddress }} competent_euclid
Template parsing error: template: :1: unexpected unclosed action in command
<注意:括号内不要有空格>
[root@bogon ~]# docker inspect --format {{.NetworkSettings.IPAddress}} competent_euclid
172.17.0.2
容器内的改變
[root@bogon ~]# docker diff competent_euclid
A /basket (A表示新增檔案)
A /basket/vdir
A /basket/chgrp
A /basket/fgrep
A /basket/mv
A /basket/pidof
A /basket/rbash
...省略部分
D /bin (D表示被删除的檔案)
容器執行日志
[root@bogon ~]# docker logs competent_euclid
root@CONTAINER:/# mv /bin /basket
root@CONTAINER:/# ls
bash: ls: command not found
3)删除容器
檢視全部容器(包括已停止的)
[root@bogon ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8f64d43a4e26 debian "/bin/bash" 11 minutes ago Exited (127) 23 seconds ago competent_euclid
1bd73131a553 debian "/bin/bash" About an hour ago Exited (0) About an hour ago cranky_austin
重新啟動容器
docker start
删除容器
[root@bogon ~]# docker rm competent_euclid
competent_euclid
清理所有已停止的容器
[root@bogon ~]# docker ps -aq -f status=exited
1bd73131a553
69914367d6b4
74ef7227163a
5a1754f8433f
944c67e9d101
e0294c4a650a
[root@bogon ~]# docker rm -v $(docker ps -aq -f status=exited)
1bd73131a553
69914367d6b4
74ef7227163a
5a1754f8433f
944c67e9d101
e0294c4a650a
-v 當所有由Docker管理的資料卷已經沒有和任何容器關聯時,一律删除
[root@bogon ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
36c220e77949 busybox "/bin/ping webapp" 3 hours ago Created destination
4)建立一個全新的容器流程
[root@bogon ~]# docker run -it --name cowsay --hostname cowsay debian bash
root@cowsay:/# apt-get update
...
root@cowsay:/# apt-get install -y cowsay fortune
root@cowsay:/# /usr/games/fortune | /usr/games/cowsay
root@cowsay:/# exit
把容器轉成鏡像
[root@bogon ~]# docker commit cowsay test/cowsayimage
[root@bogon ~]# docker run test/cowsayimage /usr/games/cowsay "Moo"
二、通過Dockerfile建立鏡像
1.Dockerfile
[root@bogon ~]# cat Dockerfile
FROM debian:wheezy
RUN apt-get update && apt-get install -y cowsay fortune
2.鏡像、容器和聯合檔案系統之間的關系
聯合檔案系統(聯合挂載)—允許多個檔案系統疊加,并表現為一個單一的檔案系統;若有兩個檔案的路徑完全相同,則最後挂載的檔案覆寫之前的;
Docker支援多種不同的檔案系統,AUFS、Overlay、devicemapper、BTRFS、ZFS;
[root@bogon ~]# docker info
Containers: 2
Running: 0
Paused: 0
Stopped: 2
Images: 12
Server Version: 17.09.0-ce
Storage Driver: overlay <<<<<<<<
Backing Filesystem: xfs
Supports d_type: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Docker鏡像由多個不同的層(layer)組成,每一層都是一個隻讀的檔案系統;
Dockerfile裡的每一個指令都會建立一個新的層,這個層位于前一個層之上;
當一個鏡像被轉化成容器時,Docker引擎會在鏡像之上添加一個處于最上層的可讀寫檔案系統。(盡量将指令寫在一行來較少層的數量)
容器可處于:已建立(created)、重新開機中(restarting)、運作中(running)、已暫停(paused)、已退出(exited)
3.ENTRYPOINT
指定一個可執行檔案,處理傳給docker run的參數。
[root@bogon ~]# cat Dockerfile
FROM debian:wheezy
RUN apt-get update && apt-get install -y cowsay fortune
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
[root@bogon ~]# cat entrypoint.sh
#!/bin/bash
if [ $# -eq 0 ];then
/usr/games/fortune | /usr/games/cowsay
else
/usr/games/cowsay "$0"
fi
[root@bogon ~]# docker build -t test/cowsay-dockerfile .
[root@bogon ~]# docker run test/cowsay-dockerfile "Moo"
4.上傳鏡像
[root@bogon ~]# cat Dockerfile
FROM debian:wheezy
MAINTAINER hdlptz <[email protected]>
RUN apt-get update && apt-get install -y cowsay fortune
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
[root@bogon ~]# docker build -t hdlptz/cowsay:stable
[root@bogon ~]# docker push hdlptz/cowsay:stable
5.鏡像的命名空間
由鏡像名稱判斷:
- 以字元串和“/”開頭,如hdlptz/revealjs,屬于使用者命名空間(user namespace)
- 如debian或ubuntu的名稱,不包含字首或/,屬于根命名空間(root namespace)
- 以主機名或IP開頭的名稱,代表該鏡像來自第三方的寄存服務,包括公司自己搭建的寄存服務
三、Redis鏡像執行個體
[root@bogon ~]# docker pull redis
Using default tag: latest
latest: Pulling from library/redis
d13d02fa248d: Pull complete
a1846f364e39: Pull complete
dba901efed8c: Pull complete
b54b43b9d049: Pull complete
b5b9e2d5e9c6: Pull complete
7058d282fa00: Pull complete
Digest: sha256:07e7b6cb753f8d06a894e22af30f94e04844461ab6cb002c688841873e5e5116
Status: Downloaded newer image for redis:latest
[root@bogon ~]# docker run -v /data test/webserver
[root@bogon ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hubuser/webapp latest cbe52807fcad 7 hours ago 362MB
redis latest 1fb7b6c8c0d0 13 days ago 107MB
debian latest 874e27b628fd 13 days ago 100MB
ubuntu 14.04 dea1945146b9 5 weeks ago 188MB
busybox latest 54511612f1c4 5 weeks ago 1.13MB
[root@bogon ~]# docker run --name myredis -d redis
d07dd579ee128a9500b81507764edbcf81aef3281a22eee22fe04c74163c6986
[root@bogon ~]# docker run --rm -it --link myredis:redis redis /bin/bash
root@cbe4f668dba7:/data# redis-cli -h redis -p 6379
redis:6379> ping
PONG
redis:6379> set "docker" 1234
OK
redis:6379> get "docker"
"1234"
redis:6379> exit
root@cbe4f668dba7:/data# exit
exit
[root@bogon ~]# docker run --rm --volumes-from myredis -v $(pwd)/backup:/backup \
debian cp /data/dump.rdb /backup/
[root@bogon ~]# docker stop myredis
[root@bogon ~]# docker rm -v myredis
[root@bogon ~]# docker rm $(docker ps -aq)