容器的概念
什么是容器(一个容器就是启了一个进程
容器就是在系统里的一个进程
)
• 容器技术已经成为应用程序封装和交付的核心技术
• 容器技术的核心有以下几个内核技术组成:
– CGroups(Control Groups)-资源管理
– NameSpace-进程隔离(命名空间)
让你感知不到你是在一个笼子里,给你砌上墙
– SELinux安全
限制容器的一些文件能不能访问
• 由于是在物理机上实施隔离,启动一个容器,可以像
启动一个进程一样快速
什么是Docker
Docker是完整的一套容器管理系统
• Docker提供了一组命令,让用户更加方便直接地使
用容器技术,而不需要过多关心底层内核技术
Docker 相当于libvirtd 这个角色
虚拟化:kvm ---qemu----libvirtd
Docker特性
相比于传统的虚拟化技术,容器更加简洁高效
• 传统虚拟机需要给每个VM安装操作系统
• 容器使用的共享公共库和程序
容器和虚拟化比起来,容器不需要装操作系统,是容器的最大优势,启动速度快简洁高效,也是劣势因为操作系统是固定的!
虚拟化 容器
Guest OS Docker
其实这缺一层libvirtd
Hypervisor Host OS
支持虚拟化的支持表示(KVM,QEMU,libvirtd) (表示不要KVM硬件仿真)
Infrastructure 硬件层 Infrastructure 硬件层
Host OS :表示不需要kvm 硬件仿真,没有硬件概念,就是一个进程!
实际上libvirtd 和Docker是一层
它把libvirtd归纳到Hypervisor这一层了
容器优点:没有操作系统,统一由Docker进程来管理!
Docker的缺点
• 容器的隔离性没有虚拟化强
• 共用Linux内核,安全性有先天缺陷
• SELinux难以驾驭
• 监控容器和容器排错是挑战
部署Docker
安装前准备
• 需要64位操作系统
• 至少RHEL6.5以上的版本,强烈推荐RHEL7
• 关闭防火墙(不是必须)Docker 会自动的管理系统的防火墙,所以在安装Docker的时候要把系统的防火墙干掉!
Docker 也会接管网络的一部分,所以网络的也要干掉Network!
准备2台虚拟机内存各4G
2台都安装
1.安装软件包:(docker_imges.zip)
配置自定义yum源
– docker-engine
– docker-engine-selinux
2.安装yum install docker-engine
3.验证:
systemctl start docker.service
Ifconfig
4.查看版本:
docker version
Docker使用
Docker有两个概念,一个叫镜像,一个叫容器!
虚拟机里也有两个概念,一个是模版,一个是实例!
模版:就是启动实例的模版,模版在后端保存所启动实例的文件和所需数据!
在Docker里镜像的概念和模版的概念一样!
在虚拟机里除了模版,还有一个启动的虚拟机叫实例,在Docker里启动的容器,叫容器!
镜像:是启动容器的模版,是核心!
什么是镜像
• 在Docker中容器是基于镜像启动的
• 镜像是启动容器的核心
• 镜像采用分层设计
• 使用快照的COW技术,确保底层数据不丢失
镜像(后端盘)
Thin R/W layer 容器(前端盘)
公共的后端盘,有无数个前端盘,可以用这个后端盘快速的镜像出无数个前端盘!
虚拟机的后端盘是自己做的,
Docker的容器后端盘是哪里来的 ?
有2种方案
1.自己做,挺麻烦
2.容器的镜像从官方下载!
3.下一层是上一次的后端盘,永远只读
Docker的命令
docker 的命令跟yum的命令挺像的!
yum search bash (这是yum搜索包的方式)
docker search centos (这是docker 搜索镜像的方式)
docker images (查看有什么镜像) 添加默认网关:ip route add default via 192.168.1.254或route add default gw 192.168.1.254 临时添加 软件包:dcoker_images.zip [root@171d6dd84557 /]# ps -ef 命令列表 查看镜像制作历史: 删除本地镜像: 修改镜像名称和标签(和软链接相似,ln) 容器常用命令 docker exec -it f387376c4c57 //容器ID /bin/bash 自定义镜像 Nginx redis httpd tomcat 镜像 镜像 镜像 镜像 Dockerfile 创建镜像: 编辑成镜像的方法有两种: 4.docker push 192.168.1.11:5000/busybox:latest 2.systemctl restart docker.service 主机卷的映射 在192.168.1.13服务器上做NFS共享: 5.exportfs -avr 在192.168.1.11服务器上: Docker网络架构(很重要) 最终怎么把docker容器发布到局域网里去! DEVICE="eth0:1" BOOTPROTO="static" 创建虚拟网桥(就是虚拟交换机) 1.cd /etc/sysconfig/network-scripts/ DEVICE="br" BOOTPROTO="static" 复用命令:创建容器,使用宿主机的端口 -p 宿主机端口:容器端口
docker help images (查看帮助)
docker images -a (显示所有镜像)
下载镜像(从镜像仓库中下载镜像)
[root@server0 ~]# docker help pull 查看帮助信息
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
[root@server0 ~]# docker pull rhel7
• 上传镜像(上传镜像到仓库)
[root@server0 ~]# docdocker help push
Usage: docker push [OPTIONS] NAME[:TAG]
[root@server0 ~]# docker push rhel7
搜索镜像:docker search busybox
下载镜像:docker pull busybox
镜像备份:docker save busybox:latest >busybox.tar
Busybox:latest 默认是latest标签,可以自己更改标签!
查看包:file busybox.tar
查看内容:tar tvf busybox.tar
传到192.168.1.12机子上:scp busybox.tar 192.168.1.12:/root/
恢复镜像备份:docker load
永久添加:/etc/sysconfig/network
GATEWAY=192.168.1.254
在docker01机器上解压: unzip docker_images.zip
导入镜像:cd docker_images/
导入:for i in *; do docker load <${i}; done
启动镜像
• 启动centos镜像生成一个容器
[root@server0 ~]# docker images
[root@server0 ~]# docker run -it centos bash
Docker run -it +镜像名:标签 +(容器里的命令)这里你是不知道容器里有什庅命令的?可以不写,有默认启动容器的命令!
-it:i是交互式的,t是分配一个终端
我在centos的镜像里所运行的命令!
启动一个容器就是启动一个进程,运行一个命令!
• 开启另一个终端(查看容器信息)
[root@server0 ~]# docker ps
启动centos镜像:docker run -it centos /bin/bash
进入容器:
[root@171d6dd84557 /]#vi /etc/yum.repos.d/local.repo
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 00:26 ? 00:00:00 /bin/bash
root 62 1 0 00:31 ? 00:00:00 ps -ef
容器里Pid 进程为1,系统的老大进程
容器里有单独的Ip,隔离起来了,
虚拟机运行的进程,在物理机上看不见,在物理机上运行的进程,虚拟机上也看不见!
容器是共享的,容器里运行的命令,在系统里是可以看见的,但是系统里运行的命令,
容器里是看不见的!系统可以管理容器里的内容!
容器里所有硬件的相关操作都会受限制,因为硬件是和系统是共享的,不像虚拟机,有qemu仿真虚拟硬件!
查看正在运行的容器:docker ps
查看之前的容器:docker ps -a
简略显示:docker ps -aq q(只显示id)
docker run -it nginx #卡在那里了,nginx 是一个系统服务,启动之后就挂在那里了。
docker run -d nginx #表示以后台进程的方式启动nginx
-d 表示后台进程
-itd :前台进程,d后台服务都包括,但是有一个问题,就是不交互了,一启动就放在后台了,如何进入交互呢?用这个命令!
docker exec -it f387376c4c57 /bin/bash
容器启动进程,其实是分两种的:
1.一种是用户能交互使用的前台进程。如果启动一个前台程序,没有可交互式的终端,就和我们写脚本,但是什庅也没写一样!
2.还有一种是系统的服务, 后台进程!
镜像后面的命令是可以改变的 例:
docker run -it centos /bin/bash
docker run -it centos /usr/bin/python
• 命令列表
– docker images //查看镜像列表
– docker history //查看镜像制作历史
– docker inspect //查看镜像底层信息
– docker pull //下载镜像
– docker push //上传镜像
– docker rmi //删除本地镜像
– docker save //镜像另存为tar包
– docker load //使用tar包导入镜像
– docker search //搜索镜像
– docker tag //修改镜像名称和标签
docker history busybox
查看镜像底层信息
docker inspect centos
环境变量:
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
默认启动命令: "Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"/bin/bash\"]"
],
注意:启动容器时删除镜像会报错!
docker rmi centos
删除流程,先把容器删了,再删镜像
删除容器:docker rm +容器id #容器id用(docker ps -a 找)
查看i节点: ls -i busybox.tar
创建软链接:ln busybox.tar f1
查看i节点: ls -i *
修改镜像名称和标签
docker tag busybox:latest ooo:xxx
查看:docker images
命令列表
– docker run //运行容器
– docker ps //查看容器列表
– docker stop //关闭容器
– docker start //启动容器
– docker restart //重启容器
– docker attach|exec //进入容器
– docker inspect //查看容器底层信息
– docker top //查看容器进程列表
– docker rm //删除容器
docker inspect -f {{. NetworkSettings.IPAddress.}}找到需要查找的东西属于哪一级以点区分 最上层的{是第一个点然后往下匹配 +容器ID 可以写脚本时使用
批量删除容器: docker rm $(docker ps -qa)
批量关闭容器:docker stop $(docker ps -q)
把系统里所有关闭的和没有关闭的容器通通删掉:
2.for i in $(docker ps -qa); do docker stop ${i}; docker rm ${i}; done
rpm:就是redhat包管理!(RHEL,CentOs,fedora,)yum rpm
deb:是debian的包 (debina,ubuntu) apt-get dpkg
redhat debina
#------------------------------------------#
RHEL,CentOS debina
fedora ubuntu
安装 yum apt-get
管理 rpm dpkg
#------------------------------------------#
补充两个命令:dpkg apt-get
dpkg 和 rpm 相似
dpkg -l = rpm -qa
dpkg -S /usr/bin/lsns = rpm -qf /usr/bin/lsns
dpkg -L util-linux = rpm -ql util-linux
红帽装包: yum install httpd
debina装包:apt-get install apache2
ctrl +z 进程终止放入后台 bg
exec:在容器里执行一个命令,如果这个命令是交互式的,就分给我一个交互终端,如果不是交互式的,执行完就推出了!
f387376c4c57:容器id
docker attach f38 不能exit退出,不能ctrl+c 中断 只能ctrl p q放入后台退出
如果是进程是交互的,就进去了,但是如果是后台服务,它就卡在那了。这就是attach.
还有一个缺点,如果进入容器了,exit退出时,它会把这个pid为1的进程干掉,pid为1的是上帝进程,相当于所有进程都干掉了 。
如果用attach进入容器,但不想容器结束,可以放在后台的方法:Ctrl +p +q
docker top 容器ID 查看容器里运行的命令
在容器里修改nginx 默认首页:
查找首页文件:
第一种方法:
dpkg -l | grep nginx
dpkg -L nginx
第二种方法:
nginx -h
nginx -t (判断配置文件的语法是否正确)
nginx -T (也是判断配置文件是否正确,但是会把配置文件输出的屏幕上)
nginx -T | grep root
cat /etc/nginx/nginx.conf
cd /etc/nginx/conf.d/
ls
grep root default.conf
修改首页:
vi /usr/share/nginx/html/index.html
docker 的核心应用是打包应用环境(封装应用的和程序交互的核心技术!)
docker commit d4b3f9d74b9b myos:latesst
commit :意思是把一个容器保存成一个镜像 docker
OS
• Dockerfile语法格式
– FROM:基础镜像
– MAINTAINER:镜像创建者信息
– EXPOSE:开放的端口
– ENV:设置变量
– ADD:复制文件到镜像
– RUN:制作镜像时执行的命令,可以有多个
– WORKDIR:定义容器默认工作目录
– CMD:容器启动时执行的命令,仅可以有一条CMD
Dockerfile 文件案例:第一个字母必须大写
Dockerfile 01
FROM centos:latest
#FROM 表示从centos的镜像修改
RUN rm -f /etc/yum.repos.d/
#RUN 表示在容器里运行一个命令
ADD local.repo /etc/yum.repos.d/local.repo
#ADD 表示把本地文件添加到容器里去
RUN yum install -y net-tools psmisc vim
Dockerfile 02
FROM myos:latest
CMD ["/usr/bin/python"]
#CMD 修改默认启用命令 有专门的格式,列表格式
Dockerfile 03
FROM myos
RUN yum install -y httpd
WORKDIR /var/www/html
#WORKDIR 表示永久的进入此目录中
RUN echo "hello nsd1804" >index.html
ENV EnvironmentFile=/etc/sysconfig/httpd
EXPOSE 80
#EXPOSE 监听端口80
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
创建Dockerfile
mkdir oo
cd oo
cp /etc/yum.repos.d/cloud.repo . 当前目录 .. 父目录
touch Dockerfile (D必须是大写)
vim Dockerfile
FROM centos:latest
RUN rm -f /etc/yum.repos.d/
ADD local.repo /etc/yum.repos.d/local.repo local.repo必须在当前目录下
RUN yum install -y net-tools psmisc vim
docker build -t myos:test .
封装ssh应用:
FROM myos
RUN yum -y install openssh-server
RUN echo 11 | passwd --stdin root
RUN sshd-keygen
ENV EnvironmentFile=/etc/sysconfig/sshd
CMD ["/usr/sbin/sshd", "-D"]
sshd-keygen 给服务创建的公私钥 在etc/ssh/
自定义镜像仓库
registry基本概念
• 共享镜像的一台服务器(镜像化的一台服务器)
Dockerfile
commit
自定义私有仓库
• 流程:
– docker pull registry
– vim /etc/docker/daemon.json
{
"insecure-registries" : ["192.168.1.10:5000"]
}
– docker run -d -p 5000:5000 registry
– docker tag 镜像 IP:5000/镜像:label
– docker push IP:5000/镜像:label
• 进入registry容器查看/etc/docker/registry/config.yml
创建私有仓库:
1.cd /etc/docker/
2.vim daemon.json
{
"insecure-registries": ["192.168.1.11:5000"]}
3.systemctl restart docker.service
for i in latest python sshd httpd; do docker tag myos:${i} 192.168.1.11:5000/myos:${i}; docker push 192.168.1.11:5000/myos:${i}; done
报错:
Get https://192.168.1.11:5000/v1/_ping: http: server gave HTTP response to HTTPS client
就是配置文件写错了! 或者没有重启服务!
验证:在192.168.1.12服务器上验证
1.vim /etc/docker/daemon.json
{
"insecure-registries": ["192.168.1.11:5000"]}
3.docker images
4.docker run -it 192.168.1.11:5000/myos:latest
扩展小知识:如何知道私有仓库里有什摩镜像?
使用API进行查看
curl http://192.168.1.11:5000/v2/_catalog
查看标签
curl http://192.168.1.11:5000/v2/busybox/tags/list
小问题;容器的数据存到哪里了?
虚拟机的数据存到虚拟硬盘文件里了
Docker 存储卷的映射
存储卷
卷的概念
• docker容器不保持任何数据
• 重要数据请使用外部卷存储(数据持久化)
• 容器可以挂载真实机目录或共享存储为卷
• 将真实机目录挂载到容器中提供持久化存储
[root@jacob ~]# docker run -v /data:/data -it centos bash
-v 前面是真机的目录,再后面是容器内的目录
我在一台机器上让多个容器共享一份数据,而且增删该查还是实时的,所有容器看见这个文件夹都是共享的!
比如:这个web服务器的数据经常变化,web服务器的配置也经常变化,我再启动web服务的配置的时候,我就可以把一个配置在我本地文件夹,我直接映射覆盖掉容器里的web服务的配置,这样的话一启动,就相当于我配置好的apache和nginx!
Web的网页怎么办呢?
可以在物理机上创建一个文件夹,在容器启动的时候,直接把这个数据也映射进去,-v这个参数可以映射好多次!
在一个机房里,局域网里,我怎么在多个容器里共享数据?
在一台服务器上做NFS,其它主机可以mount,NFS到本机的文件夹上,然后再可以映射到容器里的内部文件夹,只要NFS里的文夹一更改,整个机房的内容就都更改了。
共享存储
共享存储基本概念
• 一台共享存储服务器可以提供给所有Docker主机使用
• 共享存储服务器(NAS、SAN、DAS等)
• 如:
– 使用NFS创建共享存储服务器
– 客户端挂载NFS共享,并最终映射到容器中
使用共享存储的案例
服务器
– yum -y install nfs-utils
– vim /etc/exports
– systemctl start nfs
Docker主机1
192.168.xx.xx
• Docker主机
– mount挂载共享
– 运行容器时,使用-v选项映射磁盘到容器中
1.yum -y install nfs-utils
2.mkdir /var/webroot (把这个文件夹映射出去)
3.vim /etc/exports
/var/webroot *(rw,root_squash)
#默认的NFS是guest的用户,所以要添加root_squash
4.systemctl restart nfs
6.showmount -e 192.168.1.13
7.chmod 777 /var/webroot/
1.yum install -y nfs-utils
2.mount -t nfs 192.168.1.13:/var/webroot /mnt
3.df -h
4.showmount -e 192.168.1.13
5.rpcinfo 192.168.1.13
6.docker run -itd -v /mnt:/var/www/html 192.168.1.11:5000/myos:httpd (#改容器里的默认首页)
7.docker run -itd -v /mnt:/var/www/html 192.168.1.11:5000/myos:httpd
8.docker inspect 722 (查看容器ip)
9.curl -i http://172.17.0.3
mount -l | grep mnt
在 192.168.1.12服务器上:
1.yum install -y nfs-utils
2.mount -t nfs 192.168.1.13:/var/webroot /mnt
3.docker exec -it 014 /bin/bash
cd /var/www/html
echo haha > index.html
在192.168.1.11 服务器上:
1.curl -i http://172.17.0.3
Linux网桥(很重要)
#就是虚拟交换机
创建虚拟网卡
• 真实网卡配置文件
– cat /etc/sysconfig/network-scripts/ifcfg-eth0
• 虚拟网卡配置文件
– cat /etc/sysconfig/network-scripts/ifcfg-eth0:0
[root@jacob ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0:0
TYPE=Ethernet
BOOTPROTO=static
... ...
NAME=eth0:0
DEVICE=eth0:0
ONBOOT=yes
IPADDR=192.168.1.10
!!!创建虚拟网卡:
1.cd /etc/sysconfig/network-scripts/
2.cp ifcfg-eth0 ifcfg-eth0:1
3.vim ifcfg-eth0:1Generated by dracut initrd
ONBOOT="yes"
NM_CONTROLLED="no"
TYPE="Ethernet"
IPADDR="192.168.1.20"
PREFIX="24"
#GATEWAY="192.168.1.254" (只能有一个网关)
如果是DHCP只把名改一下就行DEVICE="eth0:1"
4.systemctl restart network
有两种方式创建虚拟交换机:
第一种:手动创建(不推荐)
第二种:使用docker
[root@jacob ~]# cat /etc/sysconfig/network-scripts/ifcfg-br0
TYPE=Bridge
BOOTPROTO=static
... ...
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=192.168.1.10
[root@jacob ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
BOOTPROTO=static
... ...
NAME=eth0
DEVICE=eth0
BRIDGE=br0
ONBOOT=yes
IPADDR=192.168.1.10
[root@jacob ~]# ~]# brctl show
手动创建虚拟交换机:
2.cp ifcfg-eth0 ifcfg-br
3.vim ifcfg-brGenerated by dracut initrd
ONBOOT="yes"
NM_CONTROLLED="no"
TYPE="Bridge"
IPADDR="192.168.1.20"
PREFIX="24"
#GATEWAY="192.168.1.254"
4.yum -y install bridge-utils
5.systemctl restart network
6.brctl show #查看虚拟交换机
Docker网络拓扑
Docker查看网络模式
docker network list
docker支持3种网络模式
bridge:桥接
host:仅主机
none:无网络
Docker 创建交换机
docker network
docker network create --help
docker network create --subnet 192.168.100.0/24 docker1
--subnet value :设置一个子网
docker network ls #查看
docker run -it --network docker1 myos
#使用 docker1 的虚拟交换机
Ifconfig
192.168.100.2
ping 172.17.0.1 #127.17.0.1是交换机(拼交换机是通的,但是下面的子网是不通的,做的是子网隔离)
交换机和交换机是隔离的,想通的话,弄在一个交换机上,不想通的话,弄两个交换机!
a和b交换机在一个子网上,他俩能通 ,c和d交换机在一个子网上,他俩能通。a和c不通!
想和哪个机器通,你就和那个机器插在同一交换机上! 网络隔离的套路就是(交换机)
两种方式创建网桥:
新建Docker网络模型
docker network create --driver bridge test01
查看默认Docker创建的网络模型
docker network create --subnet=172.30.0.0/16 test01
端口复用(核心)docker (快速的转移切换 打包应用环境)
客户端访问容器内的资源
• 默认容器通过SNAT可以访问外网
• 但外部网络的主机不可以访问容器内的资源
• 端口映射
– 使用端口映射可以实现外部网络访问容器内的资源(复用物理机的端口)
[root@jacob ~]# docker run -p 8080 80 -id nginx
//如:真实机IP为192.168.1.10,
使用-p映射真实机的8080端口到容器中的80端口
[root@client ~]# firefox http://192.168.1.10
docker run -d -v /var/data:/var/www/html -p 80:80 192.168.1.11:5000/myos:httpd
-p:把物理机的80端口,复用成容器的80端口!
cd /var/data
curl http://www.sohu.com/ -o index.html
如果虚拟机有很多需要管理就使用openstack
如果Docker有很多容器机器要管理就用K8S
1.K8s 1.openstack
2.docker 2.libvirt
3.Cgroup,namespace,selinux 3.kvm,qemu