续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,内容如下所示:
上面这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内容如下所示:
|
#define
DOCKER_IMAGE "hello-world"
|
|
#define
DOCKER_GREETING "Hello from Docker!"
|
|
"This
message shows that your installation appears to be working correctly.\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
try something more ambitious, you can run an Ubuntu container with:\n"
|
|
"
$ docker run -it ubuntu bash\n"
|
|
"Share
images, automate workflows, and more with a free Docker ID:\n"
|
|
"For
more examples and ideas, visit:\n"
|
|
//write(1,
message, sizeof(message) - 1);
|
|
syscall(SYS_write,
1, message, sizeof (message)
- 1);
|
编译生成可执行文件hello,然后可以使用Docker的build命令来构建生成Image:
|
docker
build -t hello-world
|
现在,hello-world是如何构建Image的就已经非常清楚了。下面,我们通过参考官网的用户指南,编写一个Dockerfile来制作一个Image,了解如何实现自己的应用:
首先,创建一个单独的目录来存放我们将要构建的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命令。
保存上述3行命令到文件中,在当前mydockerbuild目录中执行构建Image的命令:
|
docker
build -t docker-whale .
|
构建过程,输出信息如下:
|
Sending
build context to Docker daemon 2.048 kB
|
|
Step
1/3 : FROM docker/whalesay:latest
|
|
Step
2/3 : RUN apt-get -y update && apt-get install -y fortunes
|
|
--->
Running in bfddc2134d23
|
|
Fetched
3745 kB in 55s (67.1 kB/s)
|
|
Building
dependency tree...
|
|
Reading
state information...
|
|
The
following extra packages will be installed:
|
|
fortune-mod
fortunes-min librecode0
|
|
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.
|
|
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) ...
|
|
Removing
intermediate container bfddc2134d23
|
|
Step
3/3 : CMD /usr/games/fortune -a | cowsay
|
|
--->
Running in 8831a7231adc
|
|
Removing
intermediate container 8831a7231adc
|
|
Successfully
built 08d234c4ee26
|
或者,可以通过-f选项,直接指定Dockerfile文件的绝对路径,构建命令如下所示:
|
docker
build -f ~/mydockerbuild/Dockerfile -t docker-whale .
|
这样我们自己的Image就构建好了,名称为docker-whale。下面,看下构建我们这个Image的基本流程流程:
-
Docker检查确保当前Dockerfile中是否有需要build的内容
-
Docker检查是否存在whalesay这个Image
-
Docker会启动一个临时的容器6b362a9f73eb,来运行whalesay这个image。在这个临时的Container中,Docker会执行RUN这行命令,安装fortune程序包
-
一个新的中间container被创建8831a7231adc,在Dockerfile中增加了一个CMD层(Layer),对应一个Container,然后中间container8831a7231adc被删除
我们在构建一个Image时,会自动下载依赖的Docker Image,其实也可以预先下载对应的Image,使用类似下面的命令:
这样就可以下载MySQL 5.5的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,就是我们自己创建的。
接着,基于我们已经构建好的Image,在Docker Container中运行这个应用,执行命令:
运行结果,如下所示:
|
______________________________
|
|
|
Idiots Become Managers |
|
|
|
Impossible to Buy Machine |
|
|
|
Incredibly Big Machine |
|
|
|
Industry's Biggest Mistake |
|
|
|
International Brotherhood of |
|
|
------------------------------
|
|
/""""""""""""""""___/
===
|
|
~~~
{~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
|
另外,我们可以进入到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,可以执行如下命令(下面的命令都是等价的):
示例结果,如下所示:
|
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网络
Docker支持Container之间通过网络互连,提供了两种网络Driver,分别为Bridge和Overlay,我们也可以实现自己的网络Driver插件来管理我们的Docker Container网络。目前,有很多Docker网络的解决方案,如Flannel、Weave、Pipework、libnetwork等,感兴趣可以深入研究一下。
在安装Docker Engine之后,会包含三个默认的网络,可以通过如下命令查看当前所有的网络:
结果如下所示:
|
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网络,名称为my-bridge-network,执行如下命令:
|
docker
network create -d bridge my-bridge-network
|
创建的结果,输出了新建Docker网络的ID,如下所示:
|
fc19452525e5d2f5f1fc109656f0385bf2f268b47788353c3d9ee672da31b33a
|
上面fc19452525e5d2f5f1fc109656f0385bf2f268b47788353c3d9ee672da31b33a就是新创建网络my-bridge-network的ID,可以通过如下命令查看:
当前主机上存在的所有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网络的详细信息,查看默认的bridge网络,可以执行如下命令:
|
docker
network inspect bridge
|
执行结果,如下所示:
|
"Id":
"2872de41fddddc22420eecad253107e09a305f3512ade31d4172d3b80723d8b6",
|
|
"Created":
"2017-03-05T21:46:12.413438219+08:00",
|
|
"Subnet":
"172.17.0.0/16",
|
|
"5ab157767bbd991401c351cfb452d663f5cd93dd1edc56767372095a5c2e7f73":
{
|
|
"EndpointID":
"e0368c3219bcafea7c2839b7ede628fa67ad0a5350d150fdf55a4aa88c01c480",
|
|
"MacAddress":
"02:42:ac:11:00:02",
|
|
"IPv4Address":
"172.17.0.2/16",
|
|
"da91889d63139019bbdcc6266704fb21e0a1800d0ae63b3448e65d1e17ef7368":
{
|
|
"EndpointID":
"422ab05dd2cbb55266964b31f0dd9292688f1459e3a687662d1b119875d4ce44",
|
|
"MacAddress":
"02:42:ac:11:00:03",
|
|
"IPv4Address":
"172.17.0.3/16",
|
|
"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"
|
通过上面结果信息可以看到,当前bridge网络的ID为2872de41fddddc22420eecad253107e09a305f3512ade31d4172d3b80723d8b6,在该Docker网络内部运行中的Container有2个,分别为pgdb和webapp,他们在Container内部的IP地址分别为172.17.0.2和172.17.0.3,因为在同一个bridge网络中,所以共享相同的IP地址段。
或者,我们也可以格式化输出某个Container所在网络的设置,执行如下命令:
|
docker
inspect -- format = '{{json
.NetworkSettings.Networks}}' pgdb
|
输出结果如下所示(结果格式化过):
|
"NetworkID":
"2872de41fddddc22420eecad253107e09a305f3512ade31d4172d3b80723d8b6",
|
|
"EndpointID":
"e0368c3219bcafea7c2839b7ede628fa67ad0a5350d150fdf55a4aa88c01c480",
|
|
"IPAddress":
"172.17.0.2",
|
|
"GlobalIPv6PrefixLen":
0,
|
|
"MacAddress":
"02:42:ac:11:00:02"
|
可见和上面的命令类似,能输出Docker网络bridge的基本信息。
转载至:http://shiyanjun.cn/archives/1608.html