CentOS 7 Docker基本特性


Docker是一個開源的應用容器引擎,開發人員可以非常容易地打包已經開發好的應用,同時將應用相關的依賴包也打包到這樣一個可移植的容器中,然后發布到任意的Linux主機系統上。Docker是基於Linux Container(LXC)技術實現的一個輕量級虛擬化解決方案,用戶可以直接使用容器(Container),來構建自己的應用程序,應用開發人員無需將注意力集中在容器的管理上。Docker的目標是“Build, Ship and Run Any App, Anywhere”,這說明了使用Docker能夠實現應用運行的可移植性、便捷性,對開發人員非常友好,只要你的應用是基於Docker進行構建和部署的,在任何時候任何支持Docker的Linux發行版操作系統上都可以運行你的應用程序。
Docker是基於Go語言開發的, 代碼開源,可以在Github上查看對應的源碼:https://github.com/docker/docker.git

基本構架

Docker基於Client-Server架構,Docker daemon是服務端,Docker client是客戶端。Docker的基本架構,如下圖所示:
docker-architecture
上圖中,除了展現了Docker的Client、Server、Containers、Images、Registry之間的關系,我們主要說明Docker daemon和Docker client,關於其他組件我們后面詳述:

  • Docker daemon

Docker daemon運行在宿主機上,它是一個long-running進程,用戶通過Docker client與Docker daemon進行交互。

  • Docker client

Docker client為用戶提供了與Docker daemon交互的接口,在安裝Docker的時候就已經安裝,可以通過docker命令來操作。一個Docker client可以與同一個宿主機上的Docker daemon交互,也可以與遠程的Docker daemon進行交互。

基本概念

Registry
Registry是一個服務,它負責管理一個或多個Repository(倉庫),而Repository還包含公共倉庫(Public Repository)和私有倉庫(Private Repository)。默認的Registry是Docker Hub,它管理了按照不同用途分類的很多公共倉庫,任何人都可以到Docker Hub上查找自己需要的Image,或者可以使用docker search命令來搜索對應Image,例如我們查詢關鍵詞hadoop,示例命令如下所示:

1
docker search hadoop

查詢結果如下所示:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
NAME                             DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
sequenceiq/hadoop-docker         An easy way to try Hadoop                       428                  [OK]
sequenceiq/hadoop-ubuntu         An easy way to try Hadoop on Ubuntu             40                   [OK]
uhopper/hadoop                   Base Hadoop image with dynamic configurati...   16                   [OK]
ruo91/hadoop                     Apache hadoop 2.x - Pseudo-Distributed Mode     12                   [OK]
harisekhon/hadoop                Apache Hadoop (HDFS + Yarn, tags 2.5 - 2.7)     8                    [OK]
gelog/hadoop                     Use at your own risk.                           5                    [OK]
athlinks/hadoop                  Distributed Highly Available Hadoop Cluste...   3                    [OK]
dockmob/hadoop                   Docker images for Apache Hadoop (YARN, HDF...   3                    [OK]
uhopper/hadoop-resourcemanager   Hadoop resourcemanager                          3                    [OK]
harisekhon/hadoop-dev            Apache Hadoop (HDFS + Yarn) + Dev Tools + ...   3                    [OK]
izone/hadoop                     Hadoop 2.7.3 Ecosystem fully distributed, ...   3                    [OK]
uhopper/hadoop-namenode          Hadoop namenode                                 2                    [OK]
singularities/hadoop             Apache Hadoop                                   2                    [OK]
uhopper/hadoop-datanode          Hadoop datanode                                 2                    [OK]
uhopper/hadoop-nodemanager       Hadoop nodemanager                              2                    [OK]
lewuathe/hadoop-master           Multiple node hadoop cluster on Docker.         2                    [OK]
robingu/hadoop                   hadoop 2.7                                      1                    [OK]
mcapitanio/hadoop                Docker image running Hadoop in psedo-distr...   1                    [OK]
takaomag/hadoop                  docker image of archlinux (hadoop)              1                    [OK]
ymian/hadoop                     hadoop                                          0                    [OK]
2breakfast/hadoop                hadoop in docker                                0                    [OK]
ading1977/hadoop                 Docker image for multi-node hadoop cluster.     0                    [OK]
meteogroup/hadoop                Apache™ Hadoop® in a docker image.              0                    [OK]
hegand/hadoop-base               Hadoop base docker image                        0                    [OK]
elek/hadoop                      Base image for hadoop components (yarn/hdfs)    0                    [OK]

上面可以看到,與hadoop相關的Image都被列出來了,可以根據自己的需要選擇對應的Image下載並構建應用。

Image
Docker Image是Docker Container的基礎,一個Image是對一個Root文件系統的執行變更操作的有序集合,也包括在運行時一個Container內部需要執行的參數的變化。
一個Image是靜態的、無狀態的,它具有不變性。如果想要修改一個Image,實際是重新創建了新的Image,在原來Image基礎上修改后的一個副本。所以,往往我們制作一個Image的時候,可以基於已經存在的Image來構建新的的Image,然后Push到Repository中。

Repository
一個Repository是Docker Image的集合,它可以被Push到Registry而被共享,在Docker Hub就可以看到很多組織或個人貢獻的Image,供大家共享。當然,你也可以將自己構建的Image Push到私有的Repository中。在Repository中不同的Image是通過tag來識別的,例如latest 、5.5.0等等。

Container
Container是一個Docker Image的運行時實例,從一個Image可以創建多個包含該應用的Container。一個Container包含如下幾個部分:

  • 一個Docker Image
  • 執行環境
  • 一個標准指令的集合

安裝啟動Docker

我使用了CentOS 7操作系統,可以非常容易地安裝Docker環境。假設,下面我們都是用root用戶進行操作,執行如下命令進行准備工作:

1
2
3
4
5
6
7
yum install -y yum-utils
yum-config-manager \
     --add-repo \
 
https: //docs .docker.com /engine/installation/linux/repo_files/centos/docker .repo
 
yum makecache fast

上面首先安裝了yum-utils,它提供了yum-config-manager管理工具,然后安裝了最新穩定版本的Repository文件,最后更新yum的package索引。
安裝最新版本的Docker,當前是1.13.1,執行如下命令:

1
sudo yum -y install docker-engine

首次安裝docker-engine,輸出類似如下日志信息:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
  * base: mirrors.btte.net
  * extras: mirrors.btte.net
  * updates: mirrors.btte.net
Resolving Dependencies
--> Running transaction check
---> Package docker-engine.x86_64 0:1.13.1-1.el7.centos will be installed
--> Processing Dependency: docker-engine-selinux >= 1.13.1-1.el7.centos for package: docker-engine-1.13.1-1.el7.centos.x86_64
--> Running transaction check
---> Package docker-engine-selinux.noarch 0:1.13.1-1.el7.centos will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
=================================================================================================================================================================================================================
  Package                                                  Arch                                      Version                                                 Repository                                      Size
=================================================================================================================================================================================================================
Installing:
  docker-engine                                            x86_64                                    1.13.1-1.el7.centos                                     docker-main                                     19 M
Installing for dependencies:
  docker-engine-selinux                                    noarch                                    1.13.1-1.el7.centos                                     docker-main                                     28 k
 
Transaction Summary
=================================================================================================================================================================================================================
Install  1 Package (+1 Dependent package)
 
Total download size: 19 M
Installed size: 65 M
Downloading packages:
warning: /var/cache/yum/x86_64/7/docker-main/packages/docker-engine-selinux-1.13.1-1.el7.centos.noarch.rpm: Header V4 RSA/SHA512 Signature, key ID 2c52609d: NOKEY             ] 1.2 MB/s | 944 kB  00:00:14 ETA
Public key for docker-engine-selinux-1.13.1-1.el7.centos.noarch.rpm is not installed
(1/2): docker-engine-selinux-1.13.1-1.el7.centos.noarch.rpm                                                                                                                               |  28 kB  00:00:01    
(2/2): docker-engine-1.13.1-1.el7.centos.x86_64.rpm                                                                                                                                       |  19 MB  00:00:04    
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                                                                            4.5 MB/s |  19 MB  00:00:04    
Retrieving key from https://yum.dockerproject.org/gpg
Importing GPG key 0x2C52609D:
  Userid     : "Docker Release Tool (releasedocker) <docker@docker.com>"
  Fingerprint: 5811 8e89 f3a9 1289 7c07 0adb f762 2157 2c52 609d
  From       : https://yum.dockerproject.org/gpg
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
   Installing : docker-engine-selinux-1.13.1-1.el7.centos.noarch                                                                                                                                              1/2
libsemanage.semanage_direct_install_info: Overriding docker module at lower priority 100 with module at priority 400.
restorecon:  lstat(/var/lib/docker) failed:  No such file or directory
warning: %post(docker-engine-selinux-1.13.1-1.el7.centos.noarch) scriptlet failed, exit status 255
Non-fatal POSTIN scriptlet failure in rpm package docker-engine-selinux-1.13.1-1.el7.centos.noarch
   Installing : docker-engine-1.13.1-1.el7.centos.x86_64                                                                                                                                                      2/2
   Verifying  : docker-engine-selinux-1.13.1-1.el7.centos.noarch                                                                                                                                              1/2
   Verifying  : docker-engine-1.13.1-1.el7.centos.x86_64                                                                                                                                                      2/2
 
Installed:
   docker-engine.x86_64 0:1.13.1-1.el7.centos                                                                                                                                                                    
 
Dependency Installed:
   docker-engine-selinux.noarch 0:1.13.1-1.el7.centos                                                                                                                                                            
 
Complete!

可見,Docker已經成功安裝。下面,我們就可以啟動Docker了,執行如下命令,啟動Docker(Docker Engine):

1
systemctl start docker

可以查看一下當前系統上的進程,執行ps -ef | grep docker確認Docker已經啟動:

1
2
3
root       2717      1  8 21:52 ?        00:00:00 /usr/bin/dockerd
root       2723   2717  1 21:52 ?        00:00:00 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc
root       2920   2645  0 21:52 pts/0    00:00:00 grep --color=auto docker

下面,我們驗證一下,Docker啟動了,應該就可以在一個Container中運行一個准備好的應用,執行如下命令:

1
docker run hello-world

基於一個名稱為hello-world的Image,啟動Container並運行它,啟動過程如下所示:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
78445dd45222: Pull complete
Digest: sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
Status: Downloaded newer image for hello-world:latest
 
Hello from Docker!
This message shows that your installation appears to be working correctly.
 
To generate this message, Docker took the following steps:
  1. The Docker client contacted the Docker daemon.
  2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
  3. The Docker daemon created a new container from that image which runs the
     executable that produces the output you are currently reading.
  4. The Docker daemon streamed that output to the Docker client, which sent it
     to your terminal.
 
To try something more ambitious, you can run an Ubuntu container with:
  $ docker run -it ubuntu bash
 
Share images, automate workflows, and more with a free Docker ID:
 
 
For more examples and ideas, visit:
 

首先可以看到,因為本地沒有下載過該Image,所以會先從Docker Hub上下載,對應的tag是latest。另外,也可以看到提示信息“Hello from Docker! ”,表示我們的環境配置沒問題,可以啟動Container運行應用程序。這里,還給出了運行我們這個名稱為hello-world的示例Image在Container中運行過程中,Docker的基本運行機制如下所示:

  1. Docker Client連接到Docker daemon
  2. Docker daemon從Docker Hub上下載名稱為hello-world的Image
  3. Docker daemon基於這個Image創建了一個新的Container,並運行應用程序,輸出“Hello from Docker!”
  4. Docker daemon將結果輸出到Docker Client,也就是我們的終端上

現在,我們可能想知道hello-world這個Image是如何構建,才能夠最終在我們的Docker Container中運行,請看下文。

構建Image

通過創建Dockerfile可以構建Image,Docker會從一個Dockerfile中讀取一系列指令來構建Image。一個Dockerfile是一個文本文件,它包含了一組能夠運行的命令行,這些命令行就組裝成了一個Docker Image。
下面,我們看一下前面提到的名稱為hello-world的Image是如何構建,可以在Github上看到該Image的代碼,鏈接在這里:https://github.com/docker-library/hello-world
hello-world一定對應一個Dockerfile,內容如下所示:

1
2
3
FROM scratch
COPY hello /
CMD [ "/hello" ]

上面這3條命令,就對應着hello-world這個Image:
第一行,FROM命令:是從一個已知的基礎Image來構建新的Image,這里scratch是一個顯式指定的空Image;
第二行,COPY命令:是將指定的新文件或目錄,拷貝到Container中指定的目錄下面,這里講hello這個可執行文件復制到Container中的根路徑/下面;
第三行,CMD命令:是運行指定的命令行,包含指定的命令名稱、參數列表
可見,上面的hello可執行文件是已經構編譯好的文件,它是從一個C程序文件(Github鏈接:https://github.com/docker-library/hello-world/blob/master/hello.c)編譯而來的,源碼文件hello.c內容如下所示:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <sys/syscall.h>
 
#ifndef DOCKER_IMAGE
     #define DOCKER_IMAGE "hello-world"
#endif
 
#ifndef DOCKER_GREETING
     #define DOCKER_GREETING "Hello from Docker!"
#endif
 
const char message[] =
     "\n"
     DOCKER_GREETING "\n"
     "This message shows that your installation appears to be working correctly.\n"
     "\n"
     "To generate this message, Docker took the following steps:\n"
     " 1. The Docker client contacted the Docker daemon.\n"
     " 2. The Docker daemon pulled the \"" DOCKER_IMAGE "\" image from the Docker Hub.\n"
     " 3. The Docker daemon created a new container from that image which runs the\n"
     "    executable that produces the output you are currently reading.\n"
     " 4. The Docker daemon streamed that output to the Docker client, which sent it\n"
     "    to your terminal.\n"
     "\n"
     "To try something more ambitious, you can run an Ubuntu container with:\n"
     " $ docker run -it ubuntu bash\n"
     "\n"
     "Share images, automate workflows, and more with a free Docker ID:\n"
     "\n"
     "For more examples and ideas, visit:\n"
     "\n" ;
 
void _start() {
     //write(1, message, sizeof(message) - 1);
     syscall(SYS_write, 1, message, sizeof (message) - 1);
 
     //_exit(0);
     syscall(SYS_exit, 0);
}

編譯生成可執行文件hello,然后可以使用Docker的build命令來構建生成Image:

1
docker build -t hello-world

現在,hello-world是如何構建Image的就已經非常清楚了。下面,我們通過參考官網的用戶指南,編寫一個Dockerfile來制作一個Image,了解如何實現自己的應用:

  • 編寫Dockerfile

首先,創建一個單獨的目錄來存放我們將要構建的Dockerfile文件:

1
2
3
mkdir mydockerbuild
cd mydockerbuild
vi Dockerfile

在Dockerfile中輸入如下內容:

1
2
3
FROM docker /whalesay :latest
RUN apt-get -y update && apt-get install -y fortunes
CMD /usr/games/fortune -a | cowsay

上面FROM命令表示,Docker基於該docker/whalesay:latest來構建新的Image,這個Image在Docker Hub上,鏈接在這里:https://hub.docker.com/r/docker/whalesay/,對應的源碼可以看Github:https://github.com/docker/whalesay。RUN命令行表示安裝fortunes程序包,最后的CMD命令指示將運行/usr/games/fortune命令。

  • 構建Image

保存上述3行命令到文件中,在當前mydockerbuild目錄中執行構建Image的命令:

1
docker build -t docker-whale .

構建過程,輸出信息如下:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
Sending build context to Docker daemon 2.048 kB
Step 1/3 : FROM docker/whalesay:latest
  ---> 6b362a9f73eb
Step 2/3 : RUN apt-get -y update && apt-get install -y fortunes
  ---> Running in bfddc2134d23
Ign http://archive.ubuntu.com trusty InRelease
Get:1 http://archive.ubuntu.com trusty-updates InRelease [65.9 kB]
Get:2 http://archive.ubuntu.com trusty-security InRelease [65.9 kB]
Hit http://archive.ubuntu.com trusty Release.gpg
Get:3 http://archive.ubuntu.com trusty-updates/main Sources [485 kB]
Get:4 http://archive.ubuntu.com trusty-updates/restricted Sources [5957 B]
Get:5 http://archive.ubuntu.com trusty-updates/universe Sources [220 kB]
Get:6 http://archive.ubuntu.com trusty-updates/main amd64 Packages [1197 kB]
Get:7 http://archive.ubuntu.com trusty-updates/restricted amd64 Packages [20.4 kB]
Get:8 http://archive.ubuntu.com trusty-updates/universe amd64 Packages [516 kB]
Get:9 http://archive.ubuntu.com trusty-security/main Sources [160 kB]
Get:10 http://archive.ubuntu.com trusty-security/restricted Sources [4667 B]
Get:11 http://archive.ubuntu.com trusty-security/universe Sources [59.4 kB]
Get:12 http://archive.ubuntu.com trusty-security/main amd64 Packages [730 kB]
Get:13 http://archive.ubuntu.com trusty-security/restricted amd64 Packages [17.0 kB]
Get:14 http://archive.ubuntu.com trusty-security/universe amd64 Packages [199 kB]
Hit http://archive.ubuntu.com trusty Release
Hit http://archive.ubuntu.com trusty/main Sources
Hit http://archive.ubuntu.com trusty/restricted Sources
Hit http://archive.ubuntu.com trusty/universe Sources
Hit http://archive.ubuntu.com trusty/main amd64 Packages
Hit http://archive.ubuntu.com trusty/restricted amd64 Packages
Hit http://archive.ubuntu.com trusty/universe amd64 Packages
Fetched 3745 kB in 55s (67.1 kB/s)
Reading package lists...
Reading package lists...
Building dependency tree...
Reading state information...
The following extra packages will be installed:
   fortune-mod fortunes-min librecode0
Suggested packages:
   x11-utils bsdmainutils
The following NEW packages will be installed:
   fortune-mod fortunes fortunes-min librecode0
0 upgraded, 4 newly installed, 0 to remove and 92 not upgraded.
Need to get 1961 kB of archives.
After this operation, 4817 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu/ trusty/main librecode0 amd64 3.6-21 [771 kB]
Get:2 http://archive.ubuntu.com/ubuntu/ trusty/universe fortune-mod amd64 1:1.99.1-7 [39.5 kB]
Get:3 http://archive.ubuntu.com/ubuntu/ trusty/universe fortunes-min all 1:1.99.1-7 [61.8 kB]
Get:4 http://archive.ubuntu.com/ubuntu/ trusty/universe fortunes all 1:1.99.1-7 [1089 kB]
debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin:
Fetched 1961 kB in 5s (340 kB/s)
Selecting previously unselected package librecode0:amd64.
(Reading database ... 13116 files and directories currently installed.)
Preparing to unpack .../librecode0_3.6-21_amd64.deb ...
Unpacking librecode0:amd64 (3.6-21) ...
Selecting previously unselected package fortune-mod.
Preparing to unpack .../fortune-mod_1%3a1.99.1-7_amd64.deb ...
Unpacking fortune-mod (1:1.99.1-7) ...
Selecting previously unselected package fortunes-min.
Preparing to unpack .../fortunes-min_1%3a1.99.1-7_all.deb ...
Unpacking fortunes-min (1:1.99.1-7) ...
Selecting previously unselected package fortunes.
Preparing to unpack .../fortunes_1%3a1.99.1-7_all.deb ...
Unpacking fortunes (1:1.99.1-7) ...
Setting up librecode0:amd64 (3.6-21) ...
Setting up fortune-mod (1:1.99.1-7) ...
Setting up fortunes-min (1:1.99.1-7) ...
Setting up fortunes (1:1.99.1-7) ...
Processing triggers for libc-bin (2.19-0ubuntu6.6) ...
  ---> 98403143b081
Removing intermediate container bfddc2134d23
Step 3/3 : CMD /usr/games/fortune -a | cowsay
  ---> Running in 8831a7231adc
  ---> 08d234c4ee26
Removing intermediate container 8831a7231adc
Successfully built 08d234c4ee26

或者,可以通過-f選項,直接指定Dockerfile文件的絕對路徑,構建命令如下所示:

1
docker build -f ~ /mydockerbuild/Dockerfile -t docker-whale .

這樣我們自己的Image就構建好了,名稱為docker-whale。下面,看下構建我們這個Image的基本流程流程:

  1. Docker檢查確保當前Dockerfile中是否有需要build的內容
  2. Docker檢查是否存在whalesay這個Image
  3. Docker會啟動一個臨時的容器6b362a9f73eb,來運行whalesay這個image。在這個臨時的Container中,Docker會執行RUN這行命令,安裝fortune程序包
  4. 一個新的中間container被創建8831a7231adc,在Dockerfile中增加了一個CMD層(Layer),對應一個Container,然后中間container8831a7231adc被刪除

我們在構建一個Image時,會自動下載依賴的Docker Image,其實也可以預先下載對應的Image,使用類似下面的命令:

1
docker pull mysql:5.5

這樣就可以下載MySQL 5.5的Image到本地。

  • 查看構建的Image

查看當前image列表,其中包含我們剛剛構建好的Image,執行docker images命令,結果如下所示:

1
2
3
4
5
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker-whale        latest              08d234c4ee26        9 minutes ago       256 MB
ubuntu              latest              f49eec89601e        5 weeks ago         129 MB
hello-world         latest              48b5124b2768        6 weeks ago         1.84 kB
docker/whalesay     latest              6b362a9f73eb        21 months ago       247 MB

第一個docker-whale,就是我們自己創建的。

  • 啟動Docker Container

接着,基於我們已經構建好的Image,在Docker Container中運行這個應用,執行命令:

1
docker run docker-whale

運行結果,如下所示:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
______________________________
/ IBM:                         \
|                              |
| I've Been Moved              |
|                              |
| Idiots Become Managers       |
|                              |
| Idiots Buy More              |
|                              |
| Impossible to Buy Machine    |
|                              |
| Incredibly Big Machine       |
|                              |
| Industry's Biggest Mistake   |
|                              |
| International Brotherhood of |
| Mercenaries                  |
|                              |
| It Boggles the Mind          |
|                              |
| It's Better Manually         |
|                              |
\ Itty-Bitty Machines          /
  ------------------------------
     \
      \
       \    
                     ##        .          
               ## ## ##       ==          
            ## ## ## ##      ===          
        /""""""""""""""""___/ ===      
   ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~  
        \______ o          __/          
         \    \        __/            
           \____\______/  

另外,我們可以進入到Docker Hub:https://hub.docker.com,創建一個自己的賬號,然后創建自己的Image,當然也可以找到各種免費共享的Image,可以基於這些Image來構建自己的Image。Docker Hub頁面,如下所示:
docker-hub
下面是一個例子,可以在啟動Docker Container時,通過命令行直接向Container內部應用傳遞參數值,命令行如下所示:

1
2
docker run docker /whalesay cowsay boo
docker run docker /whalesay cowsay boo-boo

可以看到,輸出的內容根據啟動Container傳遞的參數值而變化。

  • 查看Docker Container

查看當前主機上所有狀態的Docker Container,可以執行如下命令(下面的命令都是等價的):

1
2
3
docker ps -a
docker container ps -a
docker container ls -a

示例結果,如下所示:

1
2
3
4
5
6
7
8
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
5ab157767bbd        training/postgres   "su postgres -c '/..."   6 seconds ago       Up 5 seconds        5432/tcp            pgdb
da91889d6313        training/postgres   "su postgres -c '/..."   49 seconds ago       Up 2 seconds        5432/tcp            webappdb
5d86616e9a1d        docker-whale        "/bin/sh -c '/usr/..."   24 minutes ago       Exited (0) 7 seconds ago                             elastic_mcnulty
abec6410bcac        docker/whalesay     "cowsay boo"             27 minutes ago       Exited (0) 27 minutes ago                            upbeat_edison
72d0b2bb5d6a        training/postgres   "su postgres -c '/..."   4 hours ago         Up 4 hours          5432/tcp            db
fc9b0bb6ae8e        ubuntu              "/bin/bash"              4 hours ago         Up 4 hours                              networktest
fc9b0bb6ae8e        ubuntu              "/bin/bash"              7 days ago           Exited (255) 3 days ago                              networktest

查看當前運行中的Container,可以執行如下命令查看(下面的命令都是等價的):

1
2
3
docker ps
docker container ps
docker container ls

Docker網絡

Docker支持Container之間通過網絡互連,提供了兩種網絡Driver,分別為Bridge和Overlay,我們也可以實現自己的網絡Driver插件來管理我們的Docker Container網絡。目前,有很多Docker網絡的解決方案,如Flannel、Weave、Pipework、libnetwork等,感興趣可以深入研究一下。
在安裝Docker Engine之后,會包含三個默認的網絡,可以通過如下命令查看當前所有的網絡:

1
docker network ls

結果如下所示:

1
2
3
4
NETWORK ID          NAME                DRIVER              SCOPE
b92d9ca4d992        bridge              bridge              local
6d33880bf521        host                host                local
a200b158f39c        none                null                local

名稱為host的網絡,表示宿主機的網絡,如果啟動Docker Container指定該網絡,則Container與宿主機使用相同的Network Namespace,也就是啟動的Container的網絡會使用宿主機的網卡、IP、端口。
在啟動Docker Container時,如果我們沒有顯式指定網絡名稱,Docker會使用默認的bridge網絡。這種網絡模式下,Docker會為Container創建一個獨立於宿主機的Network Namespace,並使用獨立的IP段,Container連接到一個虛擬網橋上,默認是docker0網橋。虛擬網橋與交換機的工作方式類似,啟動的Docker Container連接到虛擬網橋上,這就構成了一個二層網絡。
為了更加直觀說明,我們參考了網上的一個Docker網絡的結構圖,如下圖所示:
docker-networking
下面,通過Docker網絡功能,看如何將Container網絡連接起來。

  • 創建Docker網絡

創建一個Docker網絡,名稱為my-bridge-network,執行如下命令:

1
docker network create -d bridge my-bridge-network

創建的結果,輸出了新建Docker網絡的ID,如下所示:

1
fc19452525e5d2f5f1fc109656f0385bf2f268b47788353c3d9ee672da31b33a

上面fc19452525e5d2f5f1fc109656f0385bf2f268b47788353c3d9ee672da31b33a就是新創建網絡my-bridge-network的ID,可以通過如下命令查看:

1
docker network ls

當前主機上存在的所有Docker網絡信息,如下所示:

1
2
3
4
5
NETWORK ID          NAME                DRIVER              SCOPE
b92d9ca4d992        bridge              bridge              local
6d33880bf521        host                host                local
fc19452525e5        my-bridge-network   bridge              local
a200b158f39c        none                null                local
  • 查看一個Docker網絡

查看一個Docker網絡的詳細信息,查看默認的bridge網絡,可以執行如下命令:

1
docker network inspect bridge

執行結果,如下所示:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[
     {
         "Name": "bridge",
         "Id": "2872de41fddddc22420eecad253107e09a305f3512ade31d4172d3b80723d8b6",
         "Created": "2017-03-05T21:46:12.413438219+08:00",
         "Scope": "local",
         "Driver": "bridge",
         "EnableIPv6": false,
         "IPAM": {
             "Driver": "default",
             "Options": null,
             "Config": [
                 {
                     "Subnet": "172.17.0.0/16",
                     "Gateway": "172.17.0.1"
                 }
             ]
         },
         "Internal": false,
         "Attachable": false,
         "Containers": {
             "5ab157767bbd991401c351cfb452d663f5cd93dd1edc56767372095a5c2e7f73": {
                 "Name": "pgdb",
                 "EndpointID": "e0368c3219bcafea7c2839b7ede628fa67ad0a5350d150fdf55a4aa88c01c480",
                 "MacAddress": "02:42:ac:11:00:02",
                 "IPv4Address": "172.17.0.2/16",
                 "IPv6Address": ""
             },
             "da91889d63139019bbdcc6266704fb21e0a1800d0ae63b3448e65d1e17ef7368": {
                 "Name": "webappdb",
                 "EndpointID": "422ab05dd2cbb55266964b31f0dd9292688f1459e3a687662d1b119875d4ce44",
                 "MacAddress": "02:42:ac:11:00:03",
                 "IPv4Address": "172.17.0.3/16",
                 "IPv6Address": ""
             }
         },
         "Options": {
             "com.docker.network.bridge.default_bridge": "true",
             "com.docker.network.bridge.enable_icc": "true",
             "com.docker.network.bridge.enable_ip_masquerade": "true",
             "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
             "com.docker.network.bridge.name": "docker0",
             "com.docker.network.driver.mtu": "1500"
         },
         "Labels": {}
     }
]

通過上面結果信息可以看到,當前bridge網絡的ID為2872de41fddddc22420eecad253107e09a305f3512ade31d4172d3b80723d8b6,在該Docker網絡內部運行中的Container有2個,分別為pgdb和webapp,他們在Container內部的IP地址分別為172.17.0.2和172.17.0.3,因為在同一個bridge網絡中,所以共享相同的IP地址段。
或者,我們也可以格式化輸出某個Container所在網絡的設置,執行如下命令:

1
docker inspect -- format = '{{json .NetworkSettings.Networks}}'  pgdb

輸出結果如下所示(結果格式化過):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
{
     "bridge": {
         "IPAMConfig": null,
         "Links": null,
         "Aliases": null,
         "NetworkID": "2872de41fddddc22420eecad253107e09a305f3512ade31d4172d3b80723d8b6",
         "EndpointID": "e0368c3219bcafea7c2839b7ede628fa67ad0a5350d150fdf55a4aa88c01c480",
         "Gateway": "172.17.0.1",
         "IPAddress": "172.17.0.2",
         "IPPrefixLen": 16,
         "IPv6Gateway": "",
         "GlobalIPv6Address": "",
         "GlobalIPv6PrefixLen": 0,
         "MacAddress": "02:42:ac:11:00:02"
     }
}

可見和上面的命令類似,能輸出Docker網絡bridge的基本信息。

  • 斷開Container網絡

可以斷開一個Container的網絡,來將一個Container從一個Docker網絡中移除,只需要指定網絡名稱和Container名稱即可(或者Container的ID),命令如下所示:

1
2
3
docker network disconnect bridge pgdb
docker network disconnect bridge 5ab157767bbd991401c351cfb452d663f5cd93dd1edc56767372095a5c2e7f73
  • 連通處於兩個子網中的Docker Container

下面,運行一個Web application,默認使用bridge網絡:

1
docker run -d --name myweb training /webapp python app.py

通過命令:

1
docker inspect -- format = '{{json .NetworkSettings.Networks}}'  myweb

可以查看該應用連接網絡的狀況,如下所示(結果格式化過):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
{
     "bridge": {
         "IPAMConfig": null,
         "Links": null,
         "Aliases": null,
         "NetworkID": "2872de41fddddc22420eecad253107e09a305f3512ade31d4172d3b80723d8b6",
         "EndpointID": "a4e66b540e632c346f345c7972617ccdfaa4ef36eefbdc3a298d524b5cf13897",
         "Gateway": "172.17.0.1",
         "IPAddress": "172.17.0.4",
         "IPPrefixLen": 16,
         "IPv6Gateway": "",
         "GlobalIPv6Address": "",
         "GlobalIPv6PrefixLen": 0,
         "MacAddress": "02:42:ac:11:00:04"
     }
}

或者,獲取直接Container的IP地址,執行命令:

1
docker inspect -- format = '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' myweb

結果如下:

1
172.17.0.4

接着,我們再在my-bridge-network網絡中啟動一個Container,名稱為mydb,執行如下命令:

1
docker run -d --name mydb --network my-bridge-network training /postgres

查看mydb應用連接網絡的狀態(結果格式化過):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
{
     "my-bridge-network": {
         "IPAMConfig": null,
         "Links": null,
         "Aliases": [
             "fbfbad9e0bd3"
         ],
         "NetworkID": "fc19452525e5d2f5f1fc109656f0385bf2f268b47788353c3d9ee672da31b33a",
         "EndpointID": "49c7afbf24be165b98ea29dbfd7b1e2c0eecd9c1ef16a7efde00ab92d0563985",
         "Gateway": "172.18.0.1",
         "IPAddress": "172.18.0.2",
         "IPPrefixLen": 16,
         "IPv6Gateway": "",
         "GlobalIPv6Address": "",
         "GlobalIPv6PrefixLen": 0,
         "MacAddress": "02:42:ac:12:00:02"
     }
}

應用mydb所在網絡為my-bridge-network,IP地址為172.18.0.2。
下面,測試從我們的mydb應用所在Container,連接到myweb應用所在的Container(,實際是跨了2個子網,即從my-bridge-network網絡連接到bridge網絡)。執行如下命令,使得可以在默認的bridge網絡中的Container連接到my-bridge-network中的Container,執行如下命令:

1
docker network connect my-bridge-network myweb

這樣,就可以進入到在my-bridge-network網絡中的mydb應用所在Container中,通過ping命令,來ping另一個默認bridge網絡中myweb應用:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@localhost mydockerbuild] # docker exec -it mydb bash
root@fbfbad9e0bd3:/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:12:00:02
           inet addr:172.18.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
           inet6 addr: fe80::42:acff:fe12:2 /64 Scope:Link
           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
           RX packets:36 errors:0 dropped:0 overruns:0 frame:0
           TX packets:14 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:0
           RX bytes:3530 (3.5 KB)  TX bytes:1124 (1.1 KB)
 
lo        Link encap:Local Loopback
           inet addr:127.0.0.1  Mask:255.0.0.0
           inet6 addr: ::1 /128 Scope:Host
           UP LOOPBACK RUNNING  MTU:65536  Metric:1
           RX packets:26 errors:0 dropped:0 overruns:0 frame:0
           TX packets:26 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:1
           RX bytes:2274 (2.2 KB)  TX bytes:2274 (2.2 KB)
root@fbfbad9e0bd3:/ # ping myweb
PING myweb (172.18.0.3) 56(84) bytes of data.
64 bytes from myweb.my-bridge-network (172.18.0.3): icmp_seq=1 ttl=64 time =0.318 ms
64 bytes from myweb.my-bridge-network (172.18.0.3): icmp_seq=2 ttl=64 time =2.06 ms
64 bytes from myweb.my-bridge-network (172.18.0.3): icmp_seq=3 ttl=64 time =0.506 ms
64 bytes from myweb.my-bridge-network (172.18.0.3): icmp_seq=4 ttl=64 time =0.404 ms
^C
--- myweb ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min /avg/max/mdev = 0.318 /0 .822 /2 .061 /0 .718 ms

可見,在不同Docker網絡的兩個Container之間的網絡是連通的。

Docker Data Volumes

一個Data Volume是在一個或多個Container里面的特定的目錄,它能夠繞過Union Filesystem,提供持久化或共享數據的特性。
添加一個Data Volume,執行如下命令:

1
docker run -d -P --name vweb - v /webapp training /webapp python app.py

添加一個Data Volume,使用-v選項,目錄名為/webapp,該目錄是在Container內部的目錄,可以通過執行命令docker inspect vweb查看當前Container中對應的信息,如下所示:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
[
     {
         "Id" : "fcea99542d4d2838102fc4b627c68a201b868d85f229722325d83968b32c8b33" ,
         "Created" : "2017-03-05T16:53:12.614318467Z" ,
         "Path" : "python" ,
         "Args" : [
             "app.py"
         ],
         "State" : {
             "Status" : "running" ,
             "Running" : true ,
             "Paused" : false ,
             "Restarting" : false ,
             "OOMKilled" : false ,
             "Dead" : false ,
             "Pid" : 7555,
             "ExitCode" : 0,
             "Error" : "" ,
             "StartedAt" : "2017-03-05T16:53:13.380982103Z" ,
             "FinishedAt" : "0001-01-01T00:00:00Z"
         },
         "Image" : "sha256:6fae60ef344644649a39240b94d73b8ba9c67f898ede85cf8e947a887b3e6557" ,
         "ResolvConfPath" : "/var/lib/docker/containers/fcea99542d4d2838102fc4b627c68a201b868d85f229722325d83968b32c8b33/resolv.conf" ,
         "HostnamePath" : "/var/lib/docker/containers/fcea99542d4d2838102fc4b627c68a201b868d85f229722325d83968b32c8b33/hostname" ,
         "HostsPath" : "/var/lib/docker/containers/fcea99542d4d2838102fc4b627c68a201b868d85f229722325d83968b32c8b33/hosts" ,
         "LogPath" : "/var/lib/docker/containers/fcea99542d4d2838102fc4b627c68a201b868d85f229722325d83968b32c8b33/fcea99542d4d2838102fc4b627c68a201b868d85f229722325d83968b32c8b33-json.log" ,
         "Name" : "/vweb" ,
         "RestartCount" : 0,
         "Driver" : "overlay" ,
         "MountLabel" : "" ,
         "ProcessLabel" : "" ,
         "AppArmorProfile" : "" ,
         "ExecIDs" : null,
         "HostConfig" : {
             "Binds" : null,
             "ContainerIDFile" : "" ,
             "LogConfig" : {
                 "Type" : "json-file" ,
                 "Config" : {}
             },
             "NetworkMode" : "default" ,
             "PortBindings" : {},
             "RestartPolicy" : {
                 "Name" : "no" ,
                 "MaximumRetryCount" : 0
             },
             "AutoRemove" : false ,
             "VolumeDriver" : "" ,
             "VolumesFrom" : null,
             "CapAdd" : null,
             "CapDrop" : null,
             "Dns" : [],
             "DnsOptions" : [],
             "DnsSearch" : [],
             "ExtraHosts" : null,
             "GroupAdd" : null,
             "IpcMode" : "" ,
             "Cgroup" : "" ,
             "Links" : null,
             "OomScoreAdj" : 0,
             "PidMode" : "" ,
             "Privileged" : false ,
             "PublishAllPorts" : true ,
             "ReadonlyRootfs" : false ,
             "SecurityOpt" : null,
             "UTSMode" : "" ,
             "UsernsMode" : "" ,
             "ShmSize" : 67108864,
             "Runtime" : "runc" ,
             "ConsoleSize" : [
                 0,
                 0
             ],
             "Isolation" : "" ,
             "CpuShares" : 0,
             "Memory" : 0,
             "NanoCpus" : 0,
             "CgroupParent" : "" ,
             "BlkioWeight" : 0,
             "BlkioWeightDevice" : null,
             "BlkioDeviceReadBps" : null,
             "BlkioDeviceWriteBps" : null,
             "BlkioDeviceReadIOps" : null,
             "BlkioDeviceWriteIOps" : null,
             "CpuPeriod" : 0,
             "CpuQuota" : 0,
             "CpuRealtimePeriod" : 0,
             "CpuRealtimeRuntime" : 0,
             "CpusetCpus" : "" ,
             "CpusetMems" : "" ,
             "Devices" : [],
             "DiskQuota" : 0,
             "KernelMemory" : 0,
             "MemoryReservation" : 0,
             "MemorySwap" : 0,
             "MemorySwappiness" : -1,
             "OomKillDisable" : false ,
             "PidsLimit" : 0,
             "Ulimits" : null,
             "CpuCount" : 0,
             "CpuPercent" : 0,
             "IOMaximumIOps" : 0,
             "IOMaximumBandwidth" : 0
         },
         "GraphDriver" : {
             "Name" : "overlay" ,
             "Data" : {
                 "LowerDir" : "/var/lib/docker/overlay/59f20340fa5232f5b13300a715b6d422acc32d21385f48336cead00c3227c63a/root" ,
                 "MergedDir" : "/var/lib/docker/overlay/9c602e4263c42984824b7f1e3c62416cb6056332e6447e65c3d08de7c1f50cd6/merged" ,
                 "UpperDir" : "/var/lib/docker/overlay/9c602e4263c42984824b7f1e3c62416cb6056332e6447e65c3d08de7c1f50cd6/upper" ,
                 "WorkDir" : "/var/lib/docker/overlay/9c602e4263c42984824b7f1e3c62416cb6056332e6447e65c3d08de7c1f50cd6/work"
             }
         },
         "Mounts" : [
             {
                 "Type" : "volume" ,
                 "Name" : "228bc2018d65523797450822a068550fb8afbdf6ca2e4010a32cbb36961e3d5f" ,
                 "Source" : "/var/lib/docker/volumes/228bc2018d65523797450822a068550fb8afbdf6ca2e4010a32cbb36961e3d5f/_data" ,
                 "Destination" : "/webapp" ,
                 "Driver" : "local" ,
                 "Mode" : "" ,
                 "RW" : true ,
                 "Propagation" : ""
             }
         ],
         "Config" : {
             "Hostname" : "fcea99542d4d" ,
             "Domainname" : "" ,
             "User" : "" ,
             "AttachStdin" : false ,
             "AttachStdout" : false ,
             "AttachStderr" : false ,
             "ExposedPorts" : {
                 "5000/tcp" : {}
             },
             "Tty" : false ,
             "OpenStdin" : false ,
             "StdinOnce" : false ,
             "Env" : [
                 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
             ],
             "Cmd" : [
                 "python" ,
                 "app.py"
             ],
             "Image" : "training/webapp" ,
             "Volumes" : {
                 "/webapp" : {}
             },
             "WorkingDir" : "/opt/webapp" ,
             "Entrypoint" : null,
             "OnBuild" : null,
             "Labels" : {}
         },
         "NetworkSettings" : {
             "Bridge" : "" ,
             "SandboxID" : "3f2f86ae96ec76c08e8841c7b8eb75e586000397a8acef9a0098ddf02f2c7da7" ,
             "HairpinMode" : false ,
             "LinkLocalIPv6Address" : "" ,
             "LinkLocalIPv6PrefixLen" : 0,
             "Ports" : {
                 "5000/tcp" : [
                     {
                         "HostIp" : "0.0.0.0" ,
                         "HostPort" : "32768"
                     }
                 ]
             },
             "SandboxKey" : "/var/run/docker/netns/3f2f86ae96ec" ,
             "SecondaryIPAddresses" : null,
             "SecondaryIPv6Addresses" : null,
             "EndpointID" : "39693d7b104dab973e7ed27d16bb71b290be39aa83cce5e78f8b80de35309c5a" ,
             "Gateway" : "172.17.0.1" ,
             "GlobalIPv6Address" : "" ,
             "GlobalIPv6PrefixLen" : 0,
             "IPAddress" : "172.17.0.5" ,
             "IPPrefixLen" : 16,
             "IPv6Gateway" : "" ,
             "MacAddress" : "02:42:ac:11:00:05" ,
             "Networks" : {
                 "bridge" : {
                     "IPAMConfig" : null,
                     "Links" : null,
                     "Aliases" : null,
                     "NetworkID" : "2872de41fddddc22420eecad253107e09a305f3512ade31d4172d3b80723d8b6" ,
                     "EndpointID" : "39693d7b104dab973e7ed27d16bb71b290be39aa83cce5e78f8b80de35309c5a" ,
                     "Gateway" : "172.17.0.1" ,
                     "IPAddress" : "172.17.0.5" ,
                     "IPPrefixLen" : 16,
                     "IPv6Gateway" : "" ,
                     "GlobalIPv6Address" : "" ,
                     "GlobalIPv6PrefixLen" : 0,
                     "MacAddress" : "02:42:ac:11:00:05"
                 }
             }
         }
     }
]

從上面可以看到,在應用vweb所在Container內部的Data Volume為/webapp。
也可以mount一個宿主機的目錄,作為Docker Container的Data Volume:

1
docker run -d -P --name vvweb - v /src/webapp : /webapp training /webapp python app.py

上面命令行中,-v選項的值通過冒號分隔,前半部分是宿主機的目錄,而后半部分是Container中的相對目錄,並且要求宿主機的目錄一定包含Container中的Data Volume的路徑。
Docker的Data Volume默認是read-write模式,可以手動指定為只讀模型,執行如下命令:

1
docker run -d -P --name web - v /src/webapp : /webapp :ro training /webapp python app.py

另外,也可以創建一個用來存儲的Data Volume Container,便於多個Container中的應用共享數據。例如創建一個用來存儲數據庫數據的Data Volume Container,執行如下命令:

1
docker create - v /dbdata --name dbstore training /postgres /bin/true

創建了一個名稱為dbstore的Container。如果其他應用想要共享我們創建的用於存儲的Data Volume Container,可以在啟動應用Container的時候指定Data Volume,例如啟動下面兩個Container使用我們創建的dbstore作為共享Data Volume:

1
2
docker run -d --volumes-from dbstore --name db1 training /postgres
docker run -d --volumes-from dbstore --name db2 training /postgres

db1和db2這兩個Container共享我們創建的dbstore Data Volume Container,查看這兩個Container對應的Volume信息,執行如下命令行:

1
2
docker inspect db1
docker inspect db2

結果分別取出兩個Container的Mounts信息,對比發現內容是相同的,如下所示:

01
02
03
04
05
06
07
08
09
10
11
"Mounts": [
             {
                 "Name": "741950cc3ef8d901dc6cfdbebf8450082a0d22b07957f43bd0de73d05447b365",
                 "Source": "/var/lib/docker/volumes/741950cc3ef8d901dc6cfdbebf8450082a0d22b07957f43bd0de73d05447b365/_data",
                 "Destination": "/dbdata",
                 "Driver": "local",
                 "Mode": "",
                 "RW": true,
                 "Propagation": ""
             }
         ]

可見,只能作為Data Volume使用的Container,可以被其他多個應用所共享。

參考鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM