Docker基本管理
Docker的管理包括多个方面,例如镜像管理、容器管理、网络管理以及存储管理等。
镜像管理:介绍Docker镜像的查找、下载、列出、删除以及创建等
容器管理:介绍Docker容器的创建、启动、停止、运行、重新启动等管理操作
网络管理:介绍Docker容器的创建、连接、删除以及端口映射等操作
镜像管理
在Docker中,镜像是容器的模板。容器中的虚拟机都是以镜像为模板创建的。
查找镜像
Docker提供了docker search命令来查找远程镜像仓库中的镜像。例如:
xinzhe@node01:~$ sudo docker search mysql
下载镜像
找到合适的镜像之后,用户可以将其下载到本地电脑中,以便创建容器。Docker提供了docker pull命令下载镜像。例如
xinzhe@node01:~$ sudo docker pull ubuntu
通常情况下,镜像都是分层存储的。其中每一层都可以由不同的镜像共用。
在Docker的镜像管理中,标签发挥了重要的作用,用来区分同一个镜像的不同版本。
列出本地镜像
查看已经下载本地的镜像,命令为docker images,例如:
sudo docker images
删除镜像
删除镜像使用docker rmi命令,其中rmi中的字母i表示镜像。例如:
sudo docker rmi ubuntu
查看镜像
对于下载到本地的镜像文件,可以使用docker inspect命令来查看其详细信息,例如
sudo docker inspect mysql
构建镜像
构建Docker镜像有两种方法,其一是使用docker commit命令,其二是使用docker build命令和Dockerfile文件。
使用docker commit命令构建镜像的过程可以想象为是往版本控制系统里提交变更。先创建一个容器,并在容器里做出修改,最后再将修改结果提交为一个新的镜像。
以Ubuntu为例:
(1)以交互方式启动一个Ubuntu容器,执行如下命令:
xie@node01:~$ sudo docker run -i -t ubuntu /bin/bash
root@a36e407b3042:/#
其中的docker run表示启动一个容器,参数-i表示采用交互方式,-t表示为当前用户分配一个虚拟终端,后面为Ubuntu镜像名称,/bin/bash为要执行的命令。执行成功后,root为当前Ubuntu容器的用户,@符号后面的为容器的ID。
(2)在容器中安装Apache2
root@a36e407b3042:/# apt-get install -y apache2
(3)安装完成之后,接下来就是构建镜像
使用exit命令退出当前镜像,返回到Docker的管理界面。找到刚才使用的容器,执行如下命令:
sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a36e407b3042 ubuntu "/bin/bash" 35 minutes ago Exited (0) 11 seconds ago pensive_beaver
第一列为容器的ID。使用容器ID作为参数创建新的镜像,命令如下:
xie@node01:~$ sudo docker commit a36e407b3042 demo/webserver
sha256:bbf69edf5ab5a6c9deeebc6ef0fb5e1112aeb8c09f3cdf6229a5688a5066864e
其中的demo/webserver为新的镜像的名称。当docker commit命令执行完成之后,可以使用docker images命令查看镜像是否创建成功。
xie@node01:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
demo/webserver latest bbf69edf5ab5 About a minute ago 213MB
镜像标签管理
镜像的标签可以区分不同的版本,在语法上,标签和镜像名称之间通过冒号":"隔开。Docker提供了docker tag命令来设置镜像的标签,语法为:docker tar source_image[:tag] target_image[:tag]
例如:
root@node01:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
demo/webserver latest bbf69edf5ab5 15 hours ago 213MB
ubuntu latest f643c72bc252 7 weeks ago 72.9MB
mysql 5.7 42cdba9f1b08 3 months ago 448MB
hello-world latest bf756fb1ae65 12 months ago 13.3kB
root@node01:~# docker tag hello-world demo:hello-world
root@node01:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
demo/webserver latest bbf69edf5ab5 15 hours ago 213MB
ubuntu latest f643c72bc252 7 weeks ago 72.9MB
mysql 5.7 42cdba9f1b08 3 months ago 448MB
demo hello-world bf756fb1ae65 12 months ago 13.3kB
hello-world latest bf756fb1ae65 12 months ago 13.3kB
root@node01:~#
当然,还可以通过镜像ID来引用镜像。
容器管理
在Docker中,容器是提供服务的主体。
创建容器
容器是Docker提供网络服务的主体。在Docker中,用户可以通过两种方式来创建容器。首先,用户可以通过docker create命令来创建一个容器,创建的新容器处于停止状态。其次,docker run命令也可以创建一个新的容器,并且会启动该容器。语法如下:
docker create [options] images
用户可以通过options为容器指定相应的选项,用来设置新的容器。常用的选项有:
- –add-host=[]:指定主机到IP地址的映射关系,其格式为host:ip
- –dns=[]:为容器指定域名服务器
- –h:为容器指定主机名
- –i:打开容器的标准输入
- –u,–user=:创建用户
通常情况下,用户在创建容器时只要指定镜像名称及其版本即可。其他的都可以采用默认的选项。例如
root@node01:~# docker create centos
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
7a0437f04f83: Pull complete
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Downloaded newer image for centos:latest
9295b7f1dd54256d84217836679b6d515006843bb80f3b0856d8b61d8e8fb544
执行成功后,返回新容器的ID。
另外,还可以在docker create命令中,镜像可以指定标签或者版本号。如下:
docker create centos:latest
当本地电脑中不存在用户指定的镜像时,docker会自动搜索远程仓库。找到之后,会自动将其下载到本地,然后再创建容器。
docker run命令不仅可以创建容器,而且在创建容器之后,会立即启动该容器。语法和docker create类似。有两个选项需要注意:
- -t:为当前的容器分配一个命令行虚拟终端,以便于用户和容器交互,以该选项创建的容器可以称为交互式容器。
- -d:以该选项创建的容器称为后台型容器,新的容器保持在后台运行。
例如,创建一个名称为demo_centos的容器,创建之后立即启动该容器,并且进入交互模式:
docker run -i -t --name demo_centos centos /bin/bash
如果想要退出当前容器,直接执行exit即可。
创建一个后台型容器:
root@node01:~# docker run -d centos
f000edaf0cfb3787d78ab9c148cd1789068c57222a2c0f2dcda21b70e54b2fd3
root@node01:~#
查看容器
Docker提供了docker ps命令来查看当前系统中的容器:如下:
root@node01:~# docker ps ## 列出正在运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
注意,同一台宿主机上不允许存在有同名的容器,否则会冲突。
另外,带上参数 -a 可以列出当前系统中所有的容器,包括运行中的容器以及处于停止状态的容器。-f可以筛选符合条件的容器,示例如下:
root@node01:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f000edaf0cfb centos "/bin/bash" 6 minutes ago Exited (0) 6 minutes ago awesome_wilbur
f9f8f2139ebd centos "/bin/bash" 9 minutes ago Exited (0) 9 minutes ago demo_centos
9295b7f1dd54 centos "/bin/bash" 3 hours ago Created ecstatic_neumann
a36e407b3042 ubuntu "/bin/bash" 18 hours ago Exited (0) 18 hours ago pensive_beaver
235d02631723 hello-world "/hello" 19 hours ago Exited (0) 19 hours ago romantic_sinoussi
b90910f1cbc5 hello-world "/hello" 19 hours ago Exited (0) 19 hours ago heuristic_mirzakhani
360b0e70f946 mysql:5.7 "docker-entrypoint.s…" 2 months ago Exited (0) 2 months ago mysql
root@node01:~# docker ps -a -f name=mysql
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
360b0e70f946 mysql:5.7 "docker-entrypoint.s…" 2 months ago Exited (0) 2 months ago mysql
启动容器
对于处于停止状态的容器,可以通过docker start命令来启动,示例如下:
docker start mysql
除此之外,docker还支持restart。
停止容器
Docker提供了两个命令来停止处于运行态中的容器:docker stop和docker kill
- docker stop命令通过发送停止信号给容器,让其停止运行。某些情况下,会出现无法停止的现象,此时可以指定在强制停止容器前等待的时间,等待时间可以通过-t选项来指定,时间单位为秒。如果超过等待时间,系统会强制停止该容器。
root@node01:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
360b0e70f946 mysql:5.7 "docker-entrypoint.s…" 2 months ago Up 3 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
root@node01:~# docker stop -t 10 mysql
mysql
root@node01:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- docker kill命令用来强制终止某个容器,命令发送出KILL信号后,容器会立即终止运行。
root@node01:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
360b0e70f946 mysql:5.7 "docker-entrypoint.s…" 2 months ago Up 1 second 0.0.0.0:3306->3306/tcp, 33060/tcp mysql
root@node01:~# docker kill mysql
mysql
root@node01:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
删除容器
删除容器使用docker rm命令,参数为容器名称或者标识。例如:
docker rm f643c72bc252
注意:如果是正在运行的容器,需要首先将其停止,然后再删除。
网络管理
首先介绍Docker自身的4种网络工作方式,然后介绍一些自定义的网络模式
Docker网络原理
在Windows或者Linux系统中,当Docker安装完成之后,Docker都会在宿主机中创建一个虚拟网桥
,通过该网桥实现容器之间以及容器与外部网络的连接。通常情况下,虚拟网桥的名称为docker0。例如
root@node01:~# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 00:50:56:3b:fb:25 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:ac:bb:c5:21 brd ff:ff:ff:ff:ff:ff
网桥工作在OSI七层模型中的数据链路层。网桥是早期的两端口二层网络设备,用来连接不同网段。网桥就像一个中继器,从一端接收信号,送入另一端。网桥将网络中的多个网段在数据链路层连接起来。
在Docker中,各个容器是通过一个名称为docker0的虚拟网桥实现连接的。该虚拟网桥可以设置IP地址,相当于一个隐藏的虚拟网卡。
docker守护进程在一个容器中启动时,实际上它要创建网络连接的两端。一端是在容器中的网络设备,而另一端是在运行docker守护进程的主机上打开一个名为veth*的一个接口,用来实现docker0这个网桥与容器的网络通信。可以通过brctl命令来查看虚拟网桥docker0的信息,例如
root@node01:~# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242acbbc521 no
网络模式
Docker支持四种网络模式,网络模式可以在创建容器时就使用–network选项来指定。这四种模式分别是host、container、none以及bridge。
1.host模式
Docker使用了Linux的命名空间来进行资源隔离,如PID命名空间隔离进程,Mount命名空间隔离文件系统,Network命名空间隔离网络等。一个Network命名空间提供了一份独立的网络环境,包括网卡、路由、iptable规则等都与其他的Network命名空间隔离。一个Docker容器一般会分配一个独立的Network命名空间。但是,如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network命名空间,而是和宿主机共用一个Network命名空间,容器将不会虚拟出自己的网卡,配置自己的IP地址等,而是使用宿主机的IP和端口。
root@node01:~# docker run -d -t -i --network=host centos
5797e64e193d2d0610f027509bad36e9decc38014013ef87c0522dc21ac6e883
创建完成后,查看网络参数:
root@node01:~# docker exec 5797e64e193d2d0610f027509bad36e9decc38014013ef87c0522dc21ac6e883 ip a show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:50:56:3b:fb:25 brd ff:ff:ff:ff:ff:ff
inet 192.168.23.121/24 brd 192.168.23.255 scope global noprefixroute ens32
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fe3b:fb25/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:ac:bb:c5:21 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:febb:c521/64 scope link
valid_lft forever preferred_lft forever
root@node01:~#
实际上,这些网络信息正是主机的网络信息。
root@node01:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:50:56:3b:fb:25 brd ff:ff:ff:ff:ff:ff
inet 192.168.23.121/24 brd 192.168.23.255 scope global noprefixroute ens32
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fe3b:fb25/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:ac:bb:c5:21 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:febb:c521/64 scope link
valid_lft forever preferred_lft forever
root@node01:~#
2. container模式(容器模式)
容器模式指定新创建的容器和已经存在的一个容器共享一个Network命名空间,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP地址,而是和一个指定的容器共享IP地址、端口范围等。两个容器的进程可以通过共享网卡设备通信。
3. none模式(无模式)
这种模式下,Docker容器拥有自己的Network命名空间,但是,并不为Docker容器进行任何网络配置。也就是说,该Docker容器没有网卡、IP地址、路由等信息,需要自己添加。
4. bridge模式(桥接模式)
bridge模式是Docker默认的网络设置,该模式下会为每一个容器分配Network命名空间、设置IP地址等,并将一个主机上的Docker容器连接到一个虚拟网桥上。
Docker容器的互连
由于同一个主机中所有的容器都连接在同一个虚拟网桥docker0上,因此在默认情况下,同一主机中的容器之间是可以互相连接的。
root@node01:~# docker run -d -t -i --network=bridge centos
9283956b5d0ac3cb4602704aec4e75622b0cb8caa703b51b9b0e8088550d0dbf
root@node01:~# docker run -d -t -i --network=bridge centos
680eadfd68e698a8ccb4cbe47d8da4843d24a60a858089292eb18ab2b6e96267
root@node01:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
680eadfd68e6 centos "/bin/bash" 2 seconds ago Up 1 second nice_ellis
9283956b5d0a centos "/bin/bash" 4 seconds ago Up 3 seconds laughing_einstein
root@node01:~# docker exec 680eadfd68e6 ip a show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
root@node01:~# docker exec 9283956b5d0a ip a show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
22: eth0@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
root@node01:~#
这里两个容器的IP分别是172.17.0.3和172.17.0.2,可以使用ping命令测试是否与对方通信:
root@node01:~# docker exec 9283956b5d0a ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.128 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.063 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.081 ms
64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.110 ms
64 bytes from 172.17.0.3: icmp_seq=5 ttl=64 time=0.146 ms
64 bytes from 172.17.0.3: icmp_seq=6 ttl=64 time=0.072 ms
64 bytes from 172.17.0.3: icmp_seq=7 ttl=64 time=0.079 ms
^Z
[1]+ Stopped docker exec 9283956b5d0a ping 172.17.0.3
root@node01:~# docker exec 680eadfd68e6 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.051 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.071 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.055 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.059 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.079 ms
^Z
[2]+ Stopped docker exec 680eadfd68e6 ping 172.17.0.2
root@node01:~#
默认情况下,容器的IP地址是随机分配的,并且每次启动容器都可能发生变化。如果使用–ip选项为容器指定固定IP,则需要创建自定义网络。
容器与外部网络的互连
容器与外部网络的互连涉及两个方面:一是容器内部访问外部网络,二是外部网络访问容器内部。
由于容器通过自己的网络接口桥接到虚拟网桥docker0上,因此默认情况下,容器内部可以访问外部网络。
root@node01:~# docker exec 680eadfd68e6 ping -c 4 www.baidu.com
PING www.a.shifen.com (36.152.44.96) 56(84) bytes of data.
64 bytes from 36.152.44.96 (36.152.44.96): icmp_seq=1 ttl=127 time=26.1 ms
64 bytes from 36.152.44.96 (36.152.44.96): icmp_seq=2 ttl=127 time=24.8 ms
64 bytes from 36.152.44.96 (36.152.44.96): icmp_seq=3 ttl=127 time=30.8 ms
64 bytes from 36.152.44.96 (36.152.44.96): icmp_seq=4 ttl=127 time=52.4 ms
--- www.a.shifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 9ms
rtt min/avg/max/mdev = 24.785/33.498/52.359/11.115 ms
root@node01:~#
通常情况下,外部网络是不可以直接访问容器内部的。如果要访问容器提供的网络服务,就需要通过端口映射,也就是将主机的某个端口映射到容器的网络服务端口。通过端口映射,用户只要访问主机的指定端口就可以了。示例如下:
root@node01:~# docker run -itd -p 80:80 httpd
Unable to find image 'httpd:latest' locally
latest: Pulling from library/httpd
a076a628af6f: Pull complete
e444656f7792: Pull complete
0ec35e191b09: Pull complete
4aad5d8db1a6: Pull complete
eb1da3ea630f: Pull complete
Digest: sha256:2fab99fb3b1c7ddfa99d7dc55de8dad0a62dbe3e7c605d78ecbdf2c6c49fd636
Status: Downloaded newer image for httpd:latest
610f58f62bcb548abdbb45943a8da73ee19465ddb3f0a33654ed9a447531645f
root@node01:~#
通过浏览器访问主机的80端口。出现Apache HTTP Server默认页面:
至此,我们已经基本掌握了Docker的使用。