Docker之容器
1、容器
2、容器相關命令
2.1、運行容器(docker run)
通過 docker run [options] image 命令來運行一個容器。
options 參數說明:
- -i:以交互形式運行容器。通常與 -t 同時使用。
- -t:為容器重新分配一個偽輸入終端。
- --name:為運行的容器指定名稱。如果不指定名稱,docker會為該容器隨機指定一個名稱。比如:docker run -it --name mytomcat tomcat
下面運行 centos 容器:

執行運行命令之后,可以看到 root 后面是容器的 id,此時說明 centos 容器已經啟動成功,并且此時是進入了該容器的輸入終端中。
2.1.1、啟動容器(docker start)
我們可以先通過 docker ps -a 命令來查看所有正在運行和之前運行過的容器,然后通過 docker start 容器ID 的命令來啟動已停止的容器。
使用示例:

2.1.2、重啟容器(docker restart)
正在運行的容器或者已經停止的容器都可以通過 docker restart 容器ID 命令來重啟容器。
使用示例:

2.1.3、以后臺形式運行容器(docker run -d)
-d 參數意思是以后臺模式啟動容器。
通過該參數運行容器,你會發現有些容器會自動退出。因為 docker 容器運行必須要有一個前臺進程,否則容器會自動退出,這個是 docker 的機制問題。
下面運行 centos 容器,運行過后通過 docker ps -a 命令可以發現已經自動退出了:

所以一般可以用 -d 參數時搭配 -it 參數一起使用,此時在運行容器時不會自動進入容器,但是容器也不會自動退出。

但是有些容器也不會自動退出,比如后臺運行 tomcat 容器。
2.1.4、指定訪問容器內網絡的端口(docker run -p)
容器中可以運行一些網絡應用,要想讓外部也可以訪問容器內運行的應用,可以通過 -P(隨機映射端口) 或 -p (指定端口) 參數來指定端口映射。
(1)當使用 -P 標記時,Docker 會隨機映射一個 49000~49900 的端口到內部容器開放的網絡端口。
比如:通過 docker run -it -P tomcat 我們運行一個 tomcat:

上面我們可以看到宿主機的 49154 端口映射到了 tomcat 的 8080 端口,此時我們通過訪問 宿主機ip:49154 可以看到 tomcat 的默認項目的首頁,或者可以直接在宿主機即虛擬機上通過訪問 localhost:49154 訪問 tomcat 的首頁。
訪問報 404 可參考:http://www.rzrgm.cn/wenxuehai/p/15154703.html#_label0_0
(2)-p(小寫)則可以指定要映射的IP和端口,但是在一個指定端口上只可以綁定一個容器。
語法格式:
docker run -p 宿主機端口:容器端口 鏡像
實例使用:比如我們運行 tomcat 容器,并且將本地宿主機的 8888 端口映射到容器上的 8080 端口(tomcat的默認端口都是8080)。

此時正常情況下我們通過訪問宿主主機的 ip:8888 即可訪問到 tomcat 的默認頁面:

訪問如果報 404 可參考:http://www.rzrgm.cn/wenxuehai/p/15154703.html#_label0_0
2.2、停止容器(exit、docker stop、docker kill)
如果我們進入了容器的終端,此時可以直接通過 exit 命令來退出并停止容器。exit 命令在退出容器的同時也關閉容器,進入docker容器后如果退出容器,容器就會變成 Exited 的狀態。
或者直接通過 ctrl+P+Q 快捷鍵來控制容器不停止只退出。

通過 stop 和 kill 命令也能關閉容器:
docker stop 容器id #正常關閉容器 docker kill 容器id #暴力關閉容器
2.3、查看運行的容器列表(docker ps)
可以通過 docker ps 命令來查看所有運行的容器。
docker ps # 查看當前正在運行的容器 docker ps -a # 查看當前運行和所有運行過的容器
docker ps -l #查看上一個運行的容器
示例如下:

可以看到查詢結果的列名中,CONTAINER ID 就是容器的 id,IMAGE 就是鏡像名稱,status 表示容器的狀態(exited表示已經退出停止,up表示正在運行),NAMES 就是容器的名稱。
2.4、重新進入容器(docker attach、docker exec)
在我們使用 -itd 命令來以后臺模式運行容器,或者是在運行容器時使用 ctrl + P +Q 來退出容器但不停止容器時,此時我們可以通過 docker attach 或者是 docker exec 命令來重新進入容器。
2.4.1、docker exec(推薦使用)
docker exec 命令可以在宿主機外直接對容器進行操作,當然也可以進入容器的終端。

如果從 exec 命令進入容器,然后退出容器的話,容器不會停止,所以一般推薦大家使用 docker exec 命令。
2.4.2、docker attach(進入后退出會導致容器停止)
docker attach 命令會直接進入該容器的終端中,并且如果從該命令進入,然后退出容器的話會導致容器停止。如下執行完 attach 命令后,可以看到終端名稱發生了改變:

2.5、刪除容器(docker rm)
docker rm 容器ID #刪除已停止運行的容器。如果該容器正在運行,可能會提示報錯 docker rm -f 容器ID #強制刪除容器,可刪除正在運行的容器。實際上就是先停止后刪除
使用示例:

2.6、查看容器日志(docker logs)
通過 docker logs 容器ID 命令可查看容器日志。通過加參數 docker logs -t -f 容器ID 可保持一直輸出容器最新日志在控制臺。
2.7、查看容器內運行的進程(docker top 容器id)
通過 docker top 容器id 命令可查看該容器內運行的進程:

2.8、查看容器內部細節(docker inspect 容器id)
通過 docker inspect 容器id 命令可查看該容器內部細節,可以看到是一個 json 格式數據:

2.9、復制容器內文件到宿主機(docker cp )
可通過 cp 命令將容器內的文件復制到本宿主機上來,語法如下:
docker cp 容器ID:容器內的絕對路徑 本宿主機路徑
#示例:
docker cp f429600985ba:/usr/aa.log /root
3、容器數據卷
3.1、容器數據卷基本介紹
當我們在使用 docker 容器的時候,會產生一系列的數據文件,這些數據文件在我們關閉 docker 容器后是會消失的。如果我們希望在 docker 容器運行過程中產生的部分數據保持持久化,我們可以使用數據卷。并且數據卷在容器之間是可以數據共享。
通俗地來說,docker 容器數據卷可以看成使我們生活中常用的u盤,它存在于一個或多個的容器中,由 docker 掛載到容器,但不屬于聯合文件系統,Docker 不會在容器刪除時刪除其掛載的數據卷。
特點:
- 數據卷可以在容器之間共享或重用數據。
- 數據卷中的更改可以直接生效。
- 數據卷中的更改不會包含在鏡像的更新中。
- 數據卷的生命周期一直持續到沒有容器使用它為止。
數據卷呈現給Docker容器的形式就是一個目錄,支持多個容器間共享,修改也不會影響鏡像。
添加數據卷的方式有兩種,第一種是直接通過命令行掛載,第二種是通過 dockerFile 添加:
3.2、命令行創建數據卷(docker run -it -v)
語法格式:
docker run -it -v 宿主機目錄的絕對路徑:容器內目錄的絕對路徑 鏡像名 #即運行一個容器,并將本地主機的一個指定目錄當做數據卷掛載在該容器上。-v:v是volume的縮寫
上面命令把一個本地主機的目錄當做數據卷掛載在容器上,如果上面指定的宿主機的目錄或者容器內的目錄不存在,則 docker 會自動創建該目錄。
實現了數據卷掛載之后,本地主機和容器指定的目錄之間就會實現數據共享。在主機或者容器上指定的目錄進行一系列的操作,這些操作都會同步到另一方。比如在容器內新建文件或者修改文件,則主機上對應的目錄下也會新建文件或者文件內容會被自動修改。
在掛載之后,即使容器停止了,宿主機上對數據卷做的內容修改還是會同步到容器內。(容器停止后,我們可以通過 docker ps -a 命令找到停止的容器,并且重新啟動該容器,就可以看到宿主機內在指定目錄進行的修改仍然會同步到該容器內指定的目錄下)
使用實例:
下面我們運行一個 centos 容器,并將主機內的某個目錄當做數據卷掛載在容器上:

上面可以看到,主機內的 /usr 目錄下一開始并沒有我們指定的 myData 目錄,我們在掛載了數據卷后重新查看 /usr 目錄下的文件,可以看到自動創建該目錄:

我們在主機或者容器上指定的目錄進行一系列的操作,你會發現,這些操作會同步到另一方。比如在容器內新建文件或者修改文件,則主機上對應的目錄下也會新建文件或者文件內容會被自動修改:

3.2.1、限制容器不能修改數據卷文件
我們在掛載的時候可以給數據卷加上權限,即限制容器內不能修改新增文件。只能宿主機單向地給數據卷添加修改內容,容器內新增或者修改文件內容都不會被允許,容器內只能查看文件。
docker run -it -v 宿主機目錄的絕對路徑:容器內目錄的絕對路徑:ro 鏡像名 #ro:意思是read only
3.2.2、查看數據卷掛載是否成功
如果我們不知道數據卷是否掛載成功時,我們可以通過 docker inspect 容器ID 命令來檢查數據卷的掛載結果。
上面的命令可以查看容器的詳細情況,命令返回的是JSON格式的字符串,運行命令之后我們在返回的JSON字符串中的 hostconfig.binds 屬性中可以看到在掛載時輸入的命令參數 (/宿主機絕對路徑目錄: /容器內目錄 ):

有時候在 hostconfig.binds 屬性中并不能看到掛載的目錄,此時我們可以通過以下命令來查看掛載的目錄。如下:
docker inspect 容器id | grep Mounts -A 20
輸出的信息中 Source 指的是宿主機的目錄,Destination 指的是容器內的目錄。
3.3、通過Dockerfile創建數據卷
我們可以通過 dockerfile 來定義創建一個鏡像時的指令,在這些指令里面指定該鏡像的數據卷。
使用示例:
我們在 /usr/dockerData/ 目錄下新建一個名為 Dockerfile 的文件,并將以下指令內容編寫進該文件:
FROM centos VOLUME ["/myContainerData1","/myContainerData2"] CMD echo "build success............." CMD /bin/bash
可以看到,上面我們指定容器內的兩個數據卷目錄。我們并沒有用 -v 命令來指定宿主機的數據卷目錄,這是因為 docker 考慮到宿主機目錄是依賴于特定的宿主機的,并不能保證所有的宿主機都存在這樣特定的目錄。因為沒有指定宿主機內數據卷的目錄,所以 docker 會為宿主機指定一個目錄作為數據卷的目錄。
執行結果:

然后就可以通過 dokcer build 命令來通過該 Dockerfile 文件來構建一個新的鏡像。語法結構如下:
docker build -f dockerfile文件的完整絕對路徑 -t 命名空間/鏡像名 . #最后的 . 代表本次執行的上下文路徑,不要漏掉無法構建成功
執行結果如下,執行過后可以看到本地就生成了一個新的鏡像:

通過跑該鏡像運行一個容器,然后進入該容器的目錄,可以看到根目錄下生成了兩個我們指定的數據卷的目錄:

通過 docker inspect 容器ID 命令查看容器信息,在 mounts.source 屬性中可以看到 docker 指定的宿主機內的數據卷目錄,該目錄和容器內指定的目錄是共享的。

3.3.1、出現cannot open directory問題
Docker掛載主機目錄Docker訪問出現cannot open directory :: Permission denied
解決辦法:在掛載目錄居多加一個-privileged=true參數即可,即最終 dockerfile 文件內容如下:
FROM centos VOLUME ["/myContainerData1","/myContainerData2"] --privileged=true CMD echo "build success............." CMD /bin/bash
3.4、數據卷容器(容器數據共享)
命名的容器掛載數據卷,其他的容器通過掛載這個父容器實現數據共享,掛載數據卷的容器,我們稱為數據卷容器。也就是說當一個容器掛載了數據卷,其他容器可以通過掛載(類似于繼承)這個容器的方式來實現共享這個數據卷的數據。
首先,我們建立父容器
docker run -it --name parentContainer 鏡像名 #我們通過具有掛載數據卷指令的dockerFile建立的鏡像來運行容器
上面通過一個具有掛載數據卷指令的 dockerfile 建立的鏡像來運行容器,該容器就掛載了一個指定的數據卷。
然后我們就可以 --volumes -from 命令來通過繼承父容器,以此可以建立多個子容器:
docker run -it --name sonContainer1 --volumes-from parentContainer 鏡像名
docker run -it --name sonContainer2 --volumes-from parentContainer 鏡像名
建立的這些子容器和父容器共享數據卷,當在宿主機或者是父容器或者是子容器的數據卷指定目錄下新增修改文件,對應的其他地方的指定目錄下的文件都會被同時修改。
容器之間配置信息的傳遞,數據卷的生命周期會一致持續到沒有容器使用它為止,換言之,只要有一個容器仍在使用該數據卷,該數據卷一直都可以進行數據共享。假設我們把父容器停止運行,兩個字容器之間依舊可以進行數據共享,而且通過繼承子容器生成的新容器,一樣可以與子容器進行數據共享,這就是docker容器間的數據傳遞共享。

浙公網安備 33010602011771號