随着容器技术的发展,微服务架构被许多互联网公司推崇。docker作为一种容器的交付方式,可以实现快速交付,应用隔离,保持环境一致性等多方面的优点。这里对docker的操作做简单的介绍。
安装部署
docker的安装和配置非常简单,如果对版本没有要求在系统的默认镜像源中就有,可直接安装即可。
yum install docker -y
修改默认镜像源为国内的阿里镜像,使用阿里账号登录https://cr.console.aliyun.com 在"Docker Hub 镜像站点"中可以找到添加方式:
vim /usr/lib/systemd/system/docker.service
添加一行--registry-mirror的
ExecStart=/usr/bin/dockerd-current --registry-mirror=https://qxx96o44.mirror.aliyuncs.com \
启动docker:
systemctl daemon-reload systemctl start docker
使用docker daemon --help 可以查看后台启动进程的一些可配置参数。
Docker 常用管理命令
镜像管理
对于docker我们可以通过本地导入镜像的方式,或者直接从网络上的镜像仓库进行下载。
显示镜像 docker images
搜索镜像 docker search nginx
下载镜像 docker pull nginx
导出镜像 docker save nginx > /tmp/nginx.tar.gz
导入镜像 docker load < /tmp/nginx.tar.gz
删除镜像 docker rmi nginx
容器管理
当下载好一个镜像之后,下一步就是使用这个镜像来启动一个容器,启动容器我们使用docker run 命令,这里会自动创建并启动。
启动一个容器,并进入终端, 退出后容器停止
docker run -it nginx sh # -i -t 打开一个伪终端,打开标准输入, sh 执行的命令
如果要想退出终端后容器不停止,可以使用 组合键:ctrl + p + q
或者登录容器使用 exec 命令(退出登录后容器不终止):
docker exec -it con-name sh
也可以使用如下命令登录容器,但是与其他的登录者共享一个终端,能看到实时操作(退出会终止):
docker attach Con-name
如果你看不见shell提示符,按键盘方向键的上箭头。
启动容器,命名为test,并让其在后台运行:
docker run -d --name test centos bash -c "for n in {1..10};do echo up;sleep 1;done"
可以使用docker logs 查看容器的运行状态信息:
docker logs test docker logs test -f #实时查看日志
启动一个容器,命名为mynginx,退出后容器删除:
docker run -it --rm --name mynginx nginx bash
后台启动一个mynginx的容器
docker run -d --name mynginx nginx
查看容器的具体信息:
docker inspect Docker-Name
进入一个正在运行的容器,可以使用如下脚本(退出时需要注意,直接退出会终止容器):
#!/bin/bash pid=`docker inspect --format "{{.State.Pid}}" $1` nsenter -t $pid -m -u -i -n -p # nsenter的参数不能少
如果没有这个命令可以采用yum install util-linux -y进行安装。
停止一个容器:
docker stop mynginx
或者使用kill ID 的方式:
docker kill Docker-ID
杀死所有运行的容器:
docker kill $(docker ps -a -q)
查看所有容器(包含未运行的容器):
docker ps -a
删除所有的容器(强制删除正在运行的容器加-f 参数):
docker rm `docker ps --all|awk ‘{print $1}‘|grep -v "CONTAINER"`
容器端口管理
在启动容器的时候,如果不指定对应的参数,在容器外部是无法通过网络来访问容器内的网
络应用和服务的。当容器中运行一些网络应用,要让外部访问这些应用时,可以通过P或
者p参数来指定容器端口映射。当使用P(大写)时,docker会随机映射一个端口到容器内
部开放的端口
随机端口映射:
docker run --rm -it -P nginx
docker run --rm -it -p 127.0.0.1::80 nginx
指定端口:
docker run -it --rm -p 80:80 nginx # 第一个端口为宿主机端口,第二个为容器内部端口
绑定多个端口:
docker run --rm -it -p 82:80 -p 822:22 nginx
指定IP绑定端口:
docker run –rm it p 127.0.0.1:80:80 nginx
默认使用的是TCP协议,也可指定协议:
docker run –rm it p 127.0.0.1:80:80/udp nginx
网络功能
docker创建的容器默认是使用的NAT进行网络通信的,默认情况下创建的容器都在172.17.0.0/16的bridge网络中。
docker会在宿主机创建一个docker0的网卡,默认情况下自带三种网络:
# docker network ls NETWORK ID NAME DRIVER SCOPE 19d6580ec589 bridge bridge local 7d48677c86bc host host local 01b58b1cb415 none null local
host网络是在主机的网络堆栈上添加一个容器,使用host网络,主机和容器之间没有隔离。 例如,如果您使用主机网络运行在端口80上运行Web服务器的容器,则Web服务器可在主机端口80上使用。
host网络和none网络是无法直接配置的,我们可以配置和自定义bridge网络。
查看网络类型的具体说明:
docker network inspect bridge
内容会显示当前分配的容器网络地址。
当我们要创建一个基于某个网络的容器时,使用 docker run --network=<NETWORK> 指定
容器互联
您可以使用Docker链接功能来允许容器相互发现,并将有关一个容器的信息安全地传输到另一个容器。 通过引入Docker网络功能,您仍然可以创建链接,但它们在默认网桥和用户定义网络之间的行为方式不同,容器的互联需要通过容器的name来指定。
创建一个名为web的容器,将它与test容器互联:
docker run -d --link test --name web nginx
这样两个容器在默认的docker0中网络就打通了,其实也是利用DNS的主机和IP解析,在test容器中的/etc/hosts文件添加了web容器主机名解析配置。不过官方不推荐这样做,更好的做法是自定义一个bridge网络。
由于默认容器是以NAT方式接入宿主机网络的,所以这种方式只支持在同一台宿主机上的容器互联。
自定义网络
建议使用用户定义的bridge网络来控制哪些容器可以相互通信,还可以使用自动DNS解析容器名称到IP地址。 Docker提供了创建这些网络的默认网络驱动程序。 您可以创建一个新的桥接网络,覆盖网络或MACVLAN网络。 您还可以创建一个网络插件或远程网络进行完整的自定义和控制。
您可以根据需要创建任意数量的网络,并且可以在任何给定时间将容器连接到这些网络中的零个或多个网络。 此外,您可以连接并断开网络中的运行容器,而无需重新启动容器。 当容器连接到多个网络时,其外部连接通过第一个非内部网络以字母顺序提供网络连接。
Bridge 网络
Bridge网络是Docker中最常见的网络类型。 Bridge网络类似于桥接网络,但是与传统的桥接网络不通,docker的bridge网络添加了一些新功能并删除一些旧的功能。 以下示例创建一些桥接网络,并对这些网络上的容器执行一些实验。
系统默认的是172.17.0.1/16网段的,如果我们想要修改这个网段(即docker0地址)需要修改启动文件:
vim /usr/lib/systemd/system/docker.service
在ExecStart=区域,加上参数:
--bip=10.10.0.1/24 \
这里指定的网段必须以1结尾,不能使用0表示一个网段,否则服务无法启动。
查看默认的docker0网络:
# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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 2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 52:54:00:7f:52:5a brd ff:ff:ff:ff:ff:ff inet 192.168.20.231/24 brd 192.168.20.255 scope global ens3 valid_lft forever preferred_lft forever 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN link/ether 02:42:3d:be:20:1d brd ff:ff:ff:ff:ff:ff inet 10.10.0.1/24 scope global docker0 valid_lft forever preferred_lft forever 76: br-0d7cff84eda0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN link/ether 02:42:98:d5:cf:bf brd ff:ff:ff:ff:ff:ff inet 172.18.0.1/16 scope global br-0d7cff84eda0 valid_lft forever preferred_lft forever
创建一个自定义的bridge网络:
docker network create backend #默认会使用bridge驱动
# docker network inspect backend [ { "Name": "backend", "Id": "0d7cff84eda06d5648a9ec3b079b4f41dfad836a7ea15dbdd2e1521318d93478", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1/16" } ] }, "Internal": false, "Containers": {}, "Options": {}, "Labels": {} } ]
# docker network ls NETWORK ID NAME DRIVER SCOPE 0d7cff84eda0 backend bridge local 239f46f2ac1c bridge bridge local 7d48677c86bc host host local 01b58b1cb415 none null local
创建一个容器,并指定backend网络:
# docker run --network=backend -itd --name=ts-net centos 04ddbd92fea9c63f6ec54c7e63409054fabe1ae8a5d4ab4e4134722df9ca890c
查看自定义的网络状态:
# docker network inspect backend [ { "Name": "backend", "Id": "0d7cff84eda06d5648a9ec3b079b4f41dfad836a7ea15dbdd2e1521318d93478", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1/16" } ] }, "Internal": false, "Containers": { "04ddbd92fea9c63f6ec54c7e63409054fabe1ae8a5d4ab4e4134722df9ca890c": { "Name": "ts-net", "EndpointID": "0b9d8cdf461a4a623693b86cb465c624573ff466453e6a0d202bd40937bf23c4", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
启动到此网络的容器必须驻留在相同的Docker宿主机上。 网络中的每个容器都可以立即与网络中的其他容器进行通信。 虽然网络本身将容器与外部网络隔离开来。
用户自定义的bridge网络不支持link方式。可以使用之前介绍的端口映射或者使用expose的方式。