docker基础
云计算已经发展好些年了,作为运维,却接触不多。最近终于有时间可以研究一下docker了。
2、镜像管理
3、容器管理
4、管理应用程序数据
5、网络管理
那docker究竟是什么呢?
Docker是一个开源的应用容器引擎,使用Go语言开发,基于Linux内核的cgroup,namespace,Union FS等技术,对应用进程进行封装隔离,并且 独立于宿主机与其他进程,这种运行时封装的状态称为容器。 Docker早起版本实现是基于LXC,并进一步对其封装,包括文件系统、网络互联、镜像管理等方面,极大简化了容器管理。从0.7版本以后开始去 除LXC,转为自行研发的libcontainer,从1.11版本开始,进一步演进为使用runC和containerd。 Docker理念是将应用及依赖包打包到一个可移植的容器中,可发布到任意Linux发行版Docker引擎上。使用沙箱机制运行程序,程序之间相互隔离。
Containerd:是一个简单的守护进程,使用runC管理容器。向Docker Engine提 供接口。 Shim:只负责管理一个容器。 runC:是一个轻量级的工具,只用来运行容器。
- Namespaces
命名空间,Linux内核提供的一种对进程资源隔离的机制,例如进程、网络、挂载点等资源。
- CGroups
控制组,Linux内核提供的一种限制进程资源的机制;例如CPU、内存等资源。
- UnionFS
联合文件系统,支持将不同位置的目录挂载到同一虚拟文件系统,形成一种分层的模型。
以KVM举例,与Docker对比
- 启动时间
- Docker秒级启动,KVM分钟级启动。
- 轻量级
- 容器镜像大小通常以M为单位,虚拟机以G为单位。
- 容器资源占用小,要比虚拟机部署更快速。
- 性能
- 容器共享宿主机内核,系统级虚拟化,占用资源少,没有Hypervisor层开销,容器性能基本接近物理机;
- 虚拟机需要Hypervisor层支持,虚拟化一些设备,具有完整的GuestOS,虚拟化开销大,因而降低性能,没有容器性能好。
- 安全性
- 由于共享宿主机内核,只是进程级隔离,因此隔离性和稳定性不如虚拟机,容器具有一定权限访问宿主机内核,存在一定安全隐患。
- 使用要求
- KVM基于硬件的完全虚拟化,需要硬件CPU虚拟化技术支持;
- 容器共享宿主机内核,可运行在主流的Linux发行版,不用考虑CPU是否支持虚拟化技术。
场景一:节省项目环境部署时间
1. 单项目打包
2. 整套项目打包
3. 新开源技术试用
场景二:环境一致性
场景三:持续集成
场景四:微服务
场景五:弹性伸缩
一、linux安装docker。(本文仅提供centos7及ubuntu的安装方法,更多方式,请点击)
CentOS7 # 安装依赖包 yum install -y yum-utils device-mapper-persistent-data lvm2 # 添加Docker软件包源 yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # 更新yum包索引 yum makecache fast # 安装Docker CE yum install docker-ce # 启动 systemctl start docker # 卸载 yum remove docker-ce rm -rf /var/lib/docker
Ubuntu14.06/16.04 # 安装证书 sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-common # 添加Docker源的KEY curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - # 添加Docker软件包源 sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" # 更新apt包索引 sudo apt-get update # 安装 sudo apt-get install docker-ce # 卸载 sudo apt-get purge docker-ce sudo rm -rf /var/lib/docker
什么是镜像?
简单说,Docker镜像是一个不包含Linux内核而又精简的Linux操作系统。
镜像从哪里来?
Docker Hub是由Docker公司负责维护的公共注册中心,包含大量的容器镜像,Docker工具默认从这个公共镜像库下载镜像。 https://hub.docker.com/explore 默认是国外的源,下载会慢,建议配置国内镜像仓库:
# vi /etc/docker/daemon.json
{
"registry-mirrors": [ "https://registry.docker-cn.com"] }
镜像和容器的关系
镜像不是一个单一的文件,而是有多层构成。我们可以通过docker history 查 看镜像中各层内容及大小,每层对应着Dockerfile中的一条指令。Docker镜像默认存储在 /var/lib/docker/中。 容器其实是在镜像的最上面加了一层读写层,在运行容器里做的任何文件改动,都会写 到这个读写层。如果容器删除了,最上面的读写层也就删除了,改动也就丢失了。 Docker使用存储驱动管理镜像每层内容及可读写层的容器层。
存储驱动
镜像管理指令
指令 | 描述 |
ls | 列出镜像 |
build | 构建镜像来自Dockerfile |
history | 查看镜像历史 |
inspect | 显示一个或多个镜像详细信息 |
pull | 从镜像仓库拉取镜像 |
push | 推送一个镜像到镜像仓库 |
rm | 移除一个或多个镜像 |
prune | 移除未使用的镜像。没有被标记或被任何容器引用的。 |
tag | 创建一个引用源镜像标记目标镜像 |
export | 导出容器文件系统到tar归档文件 |
import | 导入容器文件系统tar归档文件创建镜像 |
save | 保存一个或多个镜像到一个tar归档文件 |
load | 加载镜像来自tar归档或标准输入 |
创建容器常用选项
管理容器常用命令
Volume
管理卷: # docker volume create nginx-vol # docker volume ls # docker volume inspect nginx-vol 用卷创建一个容器: # docker run -d -it --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx # docker run -d -it --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx 清理: # docker container stop nginx-test # docker container rm nginx-test # docker volume rm nginx-vol 注意: 1. 如果没有指定卷,自动创建。 2. 建议使用—mount,更通用。 官方文档:https://docs.docker.com/engine/admin/volumes/volumes/#start-a-container-with-a-volume
Bind Mounts
用卷创建一个容器: # docker run -d -it --name=nginx-test --mount type=bind,src=/app/wwwroot,dst=/usr/share/nginx/html nginx # docker run -d -it --name=nginx-test -v /app/wwwroot:/usr/share/nginx/html nginx 验证绑定: # docker inspect nginx-test 清理: # docker container stop nginx-test # docker container rm nginx-test 注意: 1. 如果源文件/目录没有存在,不会自动创建,会抛出一个错误。 2. 如果挂载目标在容器中非空目录,则该目录现有内容将被隐藏。 官方文档:https://docs.docker.com/engine/admin/volumes/bind-mounts/#start-a-container-with-a-bind-mount
搭建LNMP网站平台
1、自定义网络 docker network create lnmp 2、创建Mysql数据库容器
docker run -itd \
--name lnmp_mysql \
--net lnmp \
-p 3306:3306 \
--mount src=mysql-vol,dst=/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7 --character-set-server=utf8
3、创建所需数据库 docker exec lnmp_mysql sh \ -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e"create database wp"' 4、创建PHP环境容器 docker run -itd \ --name lnmp_web \ --net lnmp \ -p 88:80 \ --mount type=bind,src=/app/wwwroot,dst=/var/www/html richarvey/nginx-php-fpm 5、以wordpress博客为例测试 wget https://cn.wordpress.org/wordpress-4.7.4-zh_CN.tar.gz tar zxf wordpress-4.7.4-zh_CN.tar.gz -C /app/wwwroot # 浏览器测试访问 http://IP:88/wordpress
网络模式
Docker支持5种网络模式
bridge
默认网络,Docker启动后默认创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。
host
容器不会获得一个独立的network namespace,而是与宿主机共用一个。
none
获取独立的network namespace,但不为容器进行任何网络配置。
container
与指定的容器使用同一个network namespace,网卡配置也都是相同的。
自定义
自定义网桥,默认与bridge网络一样。
Linux IP信息包过滤原理:
Docker主要通过netfilter/iptables实现网络通信。 iptables由netfilter和iptables组成,netfilter组件是Linux内核集成的信息包过滤系统,它维护一个信息包过滤表,这个表用于控制信息包 过滤处理的规则集。而iptables只是一个在用户空间的工具,用于增删改查这个过滤表的规则。
容器访问外部 # iptables -t nat -nL Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0 外部访问容器 # iptables -t nat -nL Chain DOCKER (2 references) target prot opt source destination DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:88 to:172.18.0.2:80
容器网络访问原理
桥接宿主机网络与配置固定IP地址
临时生效: # 网桥名称 br_name=br0 # 添加网桥 brctl addbr $br_name # 给网桥设置IP ip addr add 192.168.0.211/24 dev $br_name # 删除已存在的eth0网卡配置 ip addr del 192.168.0.211/24 dev eth0 # 激活网桥 ip link set $br_name up # 添加eth0到网桥 brctl addif $br_name eth0 # 添加路由 ip route add default via 192.168.0.1 dev br0 还需要在Docker启动时桥接这个网桥: # vi /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -b=br0 # systemctl restart docker
永久生效: # vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 TYPE=Ethernet ONBOOT=yes BRIDGE=br0 # vi /etc/sysconfig/network-scripts/ifcfg-br0 DEVICE=br0 TYPE=Bridge ONBOOT=yes BOOTPROTO=static IPADDR=192.168.0.211 NETMASK=255.255.255.0 GATEWAY=192.168.0.1 DNS1=114.114.114.114
配置固定IP C_ID=$(docker run -itd --net=none ubuntu) C_PID=$(docker inspect -f '{{.State.Pid}}' $C_ID) # 创建network namespace目录并将容器的network namespace软连接到此目录,以便ip netns命令读取 mkdir -p /var/run/netns ln -s /proc/$C_PID/ns/net /var/run/netns/$C_PID # 添加虚拟网卡veth+容器PID,类型是veth pair,名称是vp+容器PID ip link add veth$C_PID type veth peer name vp$C_PID # 添加虚拟网卡到br0网桥 brctl addif br0 veth$C_PID # 激活虚拟网卡 ip link set veth$C_PID up # 设置容器网络信息 IP='192.168.0.123/24' GW='192.168.0.1' # 给进程配置一个network namespace ip link set vp$C_PID netns $C_PID # 在容器进程里面设置网卡信息 ip netns exec $C_PID ip link set dev vp$C_PID name eth0 ip netns exec $C_PID ip link set eth0 up ip netns exec $C_PID ip addr add $IP dev eth0 ip netns exec $C_PID ip route add default via 192.168.1.1
pipework工具配置容器固定IP git clone https://github.com/jpetazzo/pipework.git cp pipework/pipework /usr/local/bin/ docker run -itd --net=none --name test01 ubuntu pipework br0 test01 192.168.0.123/24@192.168.0.1