Centos7 Docker基本特性入門實踐-2

續CentOS 7 Docker基本特性入門實踐-1

構建Image

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

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內容如下所示:

#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:

docker build -t hello-world

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

  • 編寫Dockerfile

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

mkdir mydockerbuild
cd mydockerbuild
vi Dockerfile

在Dockerfile中輸入如下內容:

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的命令:

docker build -t docker-whale .

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

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文件的絕對路徑,構建命令如下所示:

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,使用類似下面的命令:

docker pull mysql:5.5

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

  • 查看構建的Image

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

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中運行這個應用,執行命令:

docker run docker-whale

運行結果,如下所示:

______________________________
/ 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 Container時,通過命令行直接向Container內部應用傳遞參數值,命令行如下所示:

docker run docker/whalesay cowsay boo
docker run docker/whalesay cowsay boo-boo

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

  • 查看Docker Container

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

docker ps -a
docker container ps -a
docker container ls -a

示例結果,如下所示:

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,可以執行如下命令查看(下面的命令都是等價的):

docker ps
docker container ps
docker container ls

Docker網絡

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

docker network ls

結果如下所示:

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網絡功能,看如何將Container網絡連接起來。

  • 創建Docker網絡

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

docker network create -d bridge my-bridge-network

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

fc19452525e5d2f5f1fc109656f0385bf2f268b47788353c3d9ee672da31b33a

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

docker network ls

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

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網絡,可以執行如下命令:

docker network inspect bridge

執行結果,如下所示:

[
    {
        "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",
相關文章
相關標籤/搜索