docker
docker架构
c/s架构,分为docker client,docker daemon,docker register。彼此之间基于http或https进行通信。docker采用分层构建,依赖于特定的文件系统。
docker daemon包括containers和images
当client执行诸如docker build,docker pull,docker run等指令时,docker daemon首先会查看images中是否有该镜像,如果有就直接创建或启动,如果没有就会去register上下来该镜像然后创建或启动指定的容器。
container的状态有:running,stopped,paused,created,deleted;使用docker container ps或docker ps命令可以查看容器的状态;创建容器:docker create或docker run命令。
restful概念:一种分布式程序开发调用的API,一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
docker container
安装docker
配置yum源
1 | [root@mariadb yum.repos.d]#wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo |
安装docker
1 | [root@mariadb yum.repos.d]#yum -y install docker-ce |
由于docker的官方镜像时国外服务器,有可能比较慢,此时可以借助国内的镜像加速器进行加速,例如使用阿里云的docker镜像加速器。(需要注册阿里云账号)
登录阿里云的主站点dev.aliyun.com,登录自己的账号,在产品与服务上找到容器镜像服务,然后点到镜像加速器就可以看到自己的加速器地址。按照操作文档的提示修改daemon配置文件后即可使用。
docker常用命令
images:
- pull:下载镜像
- push:上传镜像
- rm:删除镜像
- tag:给镜像打标签
container
创建容器
- docker create
- docker run
-t,–tty 指定一个终端
-i,–interactive 交互式
–name string 指定容器的名字
–rm 容器停止时删除该容器
-d 后台运行,并打印容器的ID
删除容器
- docker container rm name或docker rm name,删除容器时,容器内部的数据都会丢失,慎用。
在容器内执行命令
docker container exec [选项] 容器 命令
- docker container exec -it redis /bin/sh 在redis内部以交互式的方式打开一个终端,运行/bin/sh程序
- docker container exec redis netstat -ntl 在redis容器内部执行netstat -ntl命令,执行完命令后吧结果输出到当前终端,并退出容器。
查看容器的详细信息
- docker container inspect container… 查看一个或多个容器的详细信息
查看容器资源占用情况
- docker container stats container-name
查看容器内运行的所有进程的相关信息
- docker container top container-name
进入某container
docker container attach cotainer-name
logs
- docker container logs [options] container
使用docker管理容器
使用docker search 关键词可以搜索想要使用的仓库,仓库分为顶层仓库(官方维护)和属于某组织或个人的仓库,也可以在docker官方站点搜索仓库https://hub.docker.com/
下载redis镜像
1 | [root@mariadb docker]#docker pull redis:4-alpine |
基于下载的image启动一个容器
1 | $ docker run --name redis -d redis:4-alpine |
docker images
docker镜像含有启动容器所需要的文件系统及其内容,因此,其用于创建并启动docker容器。
image采用分层构建机制,最底层为bootfs,其次为rootfs
- bootfs:用于系统引导的文件系统,包括BootLoader和kernel,容器启动完成后会被卸载以节约内存资源。
- rootfs位于bootfs之上,表现为dicker容器的根文件系统
传统模式中,系统启动时,内核挂载rootfs时会首先将其挂载为”只读”模式,完整性自检完成后将其重新挂在为读写模式。
docker中,rootfs由内核挂载为”只读”模式,而后通过”联合挂载”技术额外挂载一个”可写”层。
Aufs
advanced multi-layered unification filesystem : 高级多层同一文件系统
用于为linux文件系统实现”联合挂载”
aufs时之前的unionfs的重新实现
dicker最初使用aufs作为容器文件系统层,它目前仍作为存储后端之一来支持
aufs的竞争产品时overlayfs,后者自从3.18版本开始被合并到linux内核
docker的分层镜像,除了aufs,还有btrfs、devicemapper和vfs等
- 在Ubuntu系统下,docker默认使用Ubuntu的aufs,而在早期centos7上,用的是devicemapper。
docker registry
启动容器时,docker daemon会试图从本地获取相关的镜像,本地镜像不存在时,其将从registry重下载该镜像并保存到本地。
自制镜像
创建自己的container后,在container上做了修改之后可以基于该container创建image,在创建image时不要停止container
- docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
例如:docker container commit redis myimg/redis:v0.1
自制镜像后,可以将自制的镜像推到个人docker账号的仓库中
docker image push name[:tag]
给已有的镜像打标签
- docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
docker网络的实现
封闭式网络
- docker run -it –rm –network none –name tinyweb1 busybox
上述命令以busybox为image创建一个封闭式网络的container tinyweb1,此container只有lo接口。
bridge网络
bridge网络可以实现不同的容器共用一个网络名称空间,而除了网络空间之外,其余的空间都是相互隔离的,这就能实现将amp分别放在不同的容器中运行,而让各自只监听127.0.0.1网址,依然能彼此通信。
示例
1 | [root@mariadb ~]#docker run -it --rm --network bridge --name tinyweb1 busybox |
说明,上述分别创建了两个容器,在容器tinyweb1上运行httpd服务,容器joinedc1指定network为与tinyweb1共享网络,此时在容器joinedc1上访问127.0.0.1,能够访问容器tinyweb1上的httpd服务,说明两个容器在使用同一网络空间,而使用ps aux查看两个容器上运行的服务不同,说明两个容器仅共享网络空间,这就能实现上述所说的在不同的容器中运行amp,mp仅监听127.0.0.1地址,依然能实现彼此之间的通信的功能。
host网络
1 | [root@mariadb ~]#docker run --name tinyweb1 -it --rm --network host busybox |
使用该命令创建的container和宿主机共用一个网络名称空间。
此外,docker创建container时还支持直接注入hosts解析和dns服务器,
- –add-host list Add a custom host-to-IP mapping (host:ip)
- –dns list Set custom DNS servers
- –dns-search list Set custom DNS search domains
docker在创建container时,还可以指定将container的某个端口映射至主机的某个端口上,这就要使用-p选项,-p的使用格式有四种:
-p, –publish list Publish a container’s port(s) to the host
- -p < containerPort> 将指定的容器端口映射至主机所有地址的一个动态端口
- -p < hostPort>:< containerPort> 将容器端口映射至指定的主机端口
- -p < ip>::< containerPort> 将指定的容器端口映射至主机指定ip的动态端口
- -p < ip>:< hostPort>:< containerPort> 将指定的容器端口映射至主机指定ip的端口
其中”动态端口”指的是随机端口,具体的映射结果可使用dicker port命令查看
创建网络名称空间
docker可以手动创建网络名称空间,然后将container加入指定的网络名称空间
[root@mariadb ~]#docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which copying the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
1 | [root@mariadb ~]#docker network create --subnet 10.10.0.0/24 mybr0 |
此外,还可以将容器connect至指定的network上,此时相当于container上多了一块网卡,还可已使用disconnect命令将container从指定的接口上拔下来。
[root@mariadb ~]#docker network connect --help
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
--alias strings Add network-scoped alias
for the container
--ip string IPv4 address (e.g.,
172.30.100.104)
--ip6 string IPv6 address (e.g.,
2001:db8::33)
--link list Add link to another container
--link-local-ip strings Add a link-local address
for the container
示例
1 | [root@mariadb ~]#docker container exec -it web /bin/sh |
docker自带的bridge桥的ip时172.17.0.1,这个默认的ip也是可以修改的,在/etc/docker/daemon.json文件中定义
1 | [root@mariadb ~]#cat /etc/docker/daemon.json |
重启docker后生效。
docker存储卷
docker镜像是由多个只读层叠加而成,启动容器时,docker会加载只读镜像层并在镜像栈顶部添加一个读写层
如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即”写时复制(COW)”机制。
关闭并重启容器,其数据不受影响;但删除docker容器,则其更改将会全部丢失,此时存在以下问题:
- 存储于联合文件系统中,不易于宿主机访问
- 容器间数据共享不便
- 删除容器其数据会丢失
此时,就需要引入卷(volunme)来解决这些问题,卷是容器上的一个或多个”目录”,此类目录可绕过联合文件系统,与宿主机上的某目录”绑定(关联)”,此volunme就类似一个传送门,可以让container和宿主机之间传输文件。
1 | [root@mariadb ~]#docker run --name web -v /mydata -it --rm busybox |
此时创建的container会自动生成/mydata目录,此目录映射到宿主机上的一个目录,即实现了容器和宿主机之间的文件共享,使用rm命令删除container时,宿主机上的卷是不会删除的,这就实现了在container生命周期结束时,container中的数据依然保留。但是此时的宿主机上的目录是自动生成的,可以使用如下方法指定宿主机的目录。
1 | [root@mariadb ~]#docker run --name web -v /data/volumes/v1:/mydata -it --rm busybox |
使用上述命令创建的容器,容器中的/mydata目录和宿主机上的/data/volumes目录之间共享目录,如果此时让另一个容器仍然映射到/data/volumes目录,就可以实现容器之间共享目录的功能,相当于将宿主机上的目录挂在到容器上。
–volume-from container选项可以实现容器之间目录的共享
1 | [root@mariadb ~]#docker run --name web --volumes-from web -it --rm busybox |
实验:使用docker以容器化方式运行lamp+WordPress架构
创建一个mysql容器,其数据目录使用卷的方式放在宿主机上,并在mysql上创建WordPress专用的数据和账号
1 | [root@docker ~]#docker image pull mysql:latest |
这里有一点需要注意,就是本次实验室用的是mysql的最新版本即8.x版本的,而8.x版本默认的认证方式是caching_sha2_password而非mysql_native_password。这会导致WordPress连接数据库失败,解决办法有以下两种。
第一种:修改my.cnf文件更改认证方式并重启mysql
1 | [root@docker ~]#vi my.cnf |
第二种:兼容新老版本的认证方式
1 | mysql> alter user wpuser@'172.17.0.%' identified by 'centos' password expire never; #修改加密规则 |
创建一个centos容器,运行httpd+php
1 | [root@docker ~]#docker image pull centos:7 #从registry拉取centos7的image |
使用lvs做前端负载均衡器,就可以管理该WordPress站点
1 | [root@docker wp]#yum -y install ipvsadm |
此时,在浏览器输入vip,就可以登入管理自己的WordPress站点,实验完毕。