docker学习笔记
1.首先修改yum源,安装最新版的docker.
(1)国外yum源。 vim yum.repo [dockerrepo] name=Docker Repository baseurl=https://yum.dockerproject.org/repo/main/centos/7/ enabled=1 gpgcheck=1 gpgkey=https://yum.dockerproject.org/gpg
安装最新的 yum install docker-engine -y
(2)清华yum源: wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
yum makecache fast yum install docker-ce
(3)删除docker yum remove docker docker-common docker-selinux docker-engine
2.docker国外官方地址 https://yum.dockerproject.org/repo/main/centos/7/Packages/
yum clear all yum clear metadata
3.进入这个网站:daocloud.io 下载docker国内加速器: curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://05c79768.m.daocloud.io
4.docker容器里起不来服务的原因: 虚拟话半解耦状态导致docker里起不来服务。
5.解耦和半解耦: ************************* namespace:命名空间 (1)名词解释 藕合:同一个空间内双方产生冲突 解耦:同一个空间内不会产生冲突 (2)虚拟化的分类 1》程序虚拟化:一个docker上装两个或多个nginx
2》解耦状态下的虚拟化:KVM/VM 两台主机完全不会有冲突
3》半解耦状态下的虚拟话:docker
6.添加: **一个程序运行主要依靠:** (1)linux:lib库文件 windows:dll链接库文件 (2)驱动程序,驱动硬件工作
**库文件和驱动程序的区别:** 对系统或软件操作的叫做库文件,对硬件操作的叫做驱动程序,就是内核释放一段二进制代码。
7.虚拟化,就是硬件资源的分割
8.内存的体现:/proc 伪文件系统有两个: proc和sys
开启一个httpd服务, ls /proc/16741 就是内存里的东西
程序要运行要操作硬件,要把对所有的硬件的指令集和占用硬件的资源存到内存里。
9.解耦状态: 所有东西都没有重复,任何东西都没有公用的地方。 半解耦: 有部分共同的一起用,其他的独立 完全解耦状态: 就是各自都是独立,没有重复。
10.docker公用的原理: (1)docker程序和物理机公用驱动程序和lib库文件,还有可能共同使用一个文件,如在docker开一个nginx,那么物理机也开一个,但是在内存里只会有一个nginx文件,所以他们共同使用一个文件。
(2)docker是一个文件夹,将所以驱动程序做个软连接,然后将物理机的东西都连接进去,把目录结构也放进去,将物理机都连接进去,叫bootfs,bootfs物理机提供的。
(3)docker 是物理机公用一个内核,只要有bootfs和rootfs 就可以直接在这个容器里装软件了,这个软件就会以为这是一个系统,有lib库,有驱动程序,各种目录结构,而系统会认为这就是一个文件夹,这种状态叫半解耦。可以安装其他的系统,但并不是整个的系统。
(4)半解耦状态:内存里共生的东西都会共用。 解耦状态:就是所有的虚拟机都不会产生冲突,有自己单独的体系。
***********************
11.docker需要哪些解耦状态(需要单独隔离) docker存在的目的:就是在一个系统里运行相同的程序。
PID: id UTS:主机名和域名 IPC:信号量/消息列队/共享内存(可以共同读内存,不能共同写) NET:网络设备/网络栈/端口等 NS: 挂载点(文件系统) USER: 用户和组 bug: 权限不能隔离。
同一个程序想在一起运行的时候就放在相同的一个命名空间里且没有冲突 可以起别名,上边的几项值没有冲突,自己是唯一,就可以共同运行。
namespace:(命名空间) 想让两个程序共同工作,就要放在同一个空间里,且没有冲突,以上的6项没有冲突。 空间范围怎么看,看编号,如果编号都一样,说明在一个空间范围工作,如果不一样就说明被隔离了。
12.查看消息列队 ipcs -q查看 ipcmk -Q ipcs -q
脚本的作用: docker隔离(想相当于是一个程序开两个子进程,运行相同的服务,然后有6项需要单独隔离) 例子: 主机名隔离: 列队隔离:
vim fork_example.c #define _GNU_SOURCE #include <sys/types.h> #include <sys/wait.h> #include <stdio.h> #include <sched.h> #include <signal.h> #include <unistd.h>
#define STACK_SIZE (1024 * 1024)
static char child_stack[STACK_SIZE]; char* const child_args[] = { "/bin/bash", NULL };
int child_main(void* args) { printf("在子进程中!\n"); sethostname("Change Namespace",12); execv(child_args[0],child_args); return 1; }
int main() { printf("程序开始:\n"); int child_pid = clone(child_main, child_stack +STACK_SIZE, CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD, NULL); waitpid(child_pid, NULL, 0); printf("已退出\n"); return 0; }
gcc -Wall fork_example.c && ./a.out
echo $$ 输出当前shell的pid 通过这个脚本在一个系统里开了两个进程,然后输出的当前的shell环境的pid不相同,一个是2786,而一个是1,那么这个1呢本来就是init的总进程的id号,怎么会被一个bash环境输出呢,所以这个1是共享了内存里system.d的总进程号了,所以这是有问题的,这个时候就引出了一个内存挂载,也叫传播性挂载,这是因为mount的挂载是有传播性的,将物理机的/proc传播给了子进程,也引出了主从挂载。 mount -t proc proc /proc/
13.pid隔离引出的mount挂载: ****************** 在隔离pid的时候出现的问题: mount传播性挂载。 mount挂载分类: (1)mount 主从挂载主可以给从传,从不可以给主传 如:mount namespace (2)/bin master——slave /bin/ mount 共享挂载 (3)/lib share——share /lib mount 私有挂载,双方不要传播(隔离)
/proc private——private /proc (4)mount 不可绑定是挂载(没有操作,逻辑概念) /root unbindable
14.mount挂载语法: man mount /--make-slave mount --make 主挂载 mount --make-shared mountpoint 共享挂载 mount --make-slave mountpoint 从挂载 mount --make-private mountpoint 私有挂载 mount --make-unbindable mount --make-rshared mountpoint 不可挂载 删除挂载: mount --make-rslave mountpoint mount --make-rprivate mountpoint mount --make-runbindable mountpoint
实验挂载: 1.将主挂载到物理机上,将从挂载到子进程中,然后发现主可以传播给从,从不能传播给主。 mount -t proc proc /proc mount --make-slave -t proc proc /proc
2.将从挂载到物理机上,将主挂载到子进程上,发现情况与上正好相反,真实环境中物理机作为从,这样就不会将内存的里的/proc目录下的东西给子进程或者是docker容器了,这样子进程就是独立的了,其实这个环境一个私有传播就可解决,现在就是想说明主从复制也可以。
添加: 要将物理机作为slave,虚拟机作为master 1,先做物理做主,虚拟机做从,物理机可以传给虚拟机,会影响 2.物理做从,虚拟机做主,物理机就不会传播到虚拟机,虚拟机就是一个全新的
15.容器里起不来服务的原因: 虚拟机的第一个进程,1应该是/bin/bash 而并不是1是system.d的,所以容器里起不来system.d的或者是systemctl的程序,因为1号进程是错的,所以在容器里用源码包。 物理机上开机运行的1是system.d的pid. 解决方案: 因为pid,所以mount;因为mount,所以1号进程错误;因为隔离pid,所以隔离/proc目录;mount的主从挂载,导致1号进程不能互相传播;所有导致不能用system.d和systemctl启动程序, 所以让docker容器里的1号进程,成为systemd和init 1,而不是/bin/bash生成的那个。
16.容器起服务实验: 1.首先拉取一个centos镜像, docker search centos docker pull centos 2.创建一个容器,然后进去安装httpd服务,看能不能起来服务。 docker images docker run -itd 2d194b392dd1 /bin/bash docker ps docker exec -it 2d194b392dd1 /bin/bash 3.创建一个提权的容器,然后进去安装httpd服务,看是否可以启动服务。 docker images docker run --restart always -d --name='23' --privileged 2d194b392dd1 /sbin/init docker ps docker exec -it 23 /bin/bash 验证:就可以在docker容器里启动服务,
网络隔离: ******************* 一个docker就是一个空间 点到点的隔离,容器间的隔离。 docker0 docker交换机,然后可以进行连接。 veth必须是成对的。 5:docker0 全局编号,唯一的 ip netns add test_ns //创建一个远端,以后docker容器就是他 ip netns exec test_ns ip link list //查看网络配置 ip netns exec test_ns ping 127.0.0.1 //测试内部 ping ip netns exec test_ns ip link set dev lo up //开启分装 ip netns exec test_ns ping 127.0.0.1 //docker里面是通的
ip link add veth0 type veth peer name veth1 //建立连接本地和远端,网线是一对 ip link set veth1 netns test_ns //veth1放到远端 ip netns exec test_ns ifconfig veth1 10.1.1.1 //给v1配置IP地址 ifconfig veth0 10.1.1.2 //给自己配置ip地址 ping 10.0.0.1 @接到全局网卡的14上 ip netns exec test_ns ip link list //查看绑定的网卡 验证: 防火墙和route都隔离了, route ip netns exec test_ns route ip netns exec test_ns iptables -L iptables -L