Docker核心技术(一)
初识Docker
基于Linux内核的Cgoup,NameSpace,以及Union FS等技术,对进程进行封装隔离,属于操作系统层面的虚拟技术,由于隔离的进程独立于宿主和其他的隔离的进程,因此也被称为容器。
Docker在容器的基础上,进行了进一步的封装,从文件系统,网络互联网到进程隔离等等,极大的简化了容器的创建和维护,使得Docker技术比虚拟机技术更为简便、快捷。
为什么要用Docker?它有哪些特性和优势?
它能更高效的利用系统资源、更快速的启动时间、一致的运行环境、更轻松的迁移、更轻松的维护和扩展
特性:安全性、隔离性、便携性、可配额
Docker与虚拟机的区别
容器操作
启动:
- docker run
-it 交互
-d 后台运行
-p 端口映射
-v 磁盘挂载 - 启动已终止的容器:docker start
- 停止容器:docker stop
- 查看容器进程:docker ps
- 查看容器细节:docker inspect [containerid]
- 进入容器:docker attach
docker exec - 通过 nsenter:
PID=$(docker inspect – format “{{.State.Pid}}”)[container])
$ nsenter --target $PID --mount --uts --ipc --net --pid - 拷贝文件至容器内:docker cp file [container:id]:/file-to-path
什么是 Dockerfile?
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
查看Dockerfile:
例:
FROM ubuntu ENV MY_SERVICE_PORT=80 ADD bin/amd64/httpserver/httpserver ENTRYPOINT /httpserver
将Dockerfile打包成镜像:
例:
docker build -t cncamp/httpserver:${tag}
docker push cncamp/httpserver:v1.0
运行容器:
例:
docker run -d cncamp/httpserver:v1.0
什么是NameSpace?
NameSpace是Linux内核用来隔离内核资源的方式。
NameSpace的特点:
- 系统可以为进程分配不同的 Namespace;
- 并保证不同的 Namespace 资源独立分配、进程彼此隔离,即不同的 Namespace 下的进程互不干扰 。
- 通过 Namespace 可以让一些进程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的资源。这两拨进程相互独立且隔离无法感知到对方的存在。具体的实现方式是把一个或多个进程的相关资源指定在同一个 namespace 中。
- 进程的数据结构实现
struct task_struct {
...
/* namespaces */
struct nsproxy *nsproxy;
...
}
- namespace的数据结构实现
struct nsproxy {
atomic_t count;
struct uts_namespace *uts_ns; struct ipc_namespace *ipc_ns; struct mnt_namespace *mnt_ns; struct pid_namespace
*pid_ns_for_children;
struct net *net_ns;
}
NameSpace的用途:
从 docker 实现者的角度考虑如何实现一个资源隔离的容器。可以通过 chroot 命令切换根目录的挂载点,从而隔离文件系统。为了在分布式的环境下进行通信和定位,容器必须要有独立的 IP、端口和路由等,这就需要对网络进行隔离。同时容器还需要一个独立的主机名以便在网络中标识自己。接下来还需要进程间的通信、用户权限等的隔离。最后,运行在容器中的应用需要有进程号(PID),自然也需要与宿主机中的 PID 进行隔离。也就是说这六种隔离能力是实现一个容器的基础,
名称 | 宏定义 | 隔离的资源 |
IPC | CLONE_NEWIPC | 信号量、共享内存和POSIX 消息队列 |
Network | CLONE_NEWNET | 网络设备,网络栈,端口等 |
Mount | CLONE_NEWNS | 文件挂载点 |
PID | CLONE_NEWPID | 进程编号 |
User | CLONE_NEWUSER | 用户和用户组 |
UTS | CLONE_NEWUTS | 主机名和NIS域名 |
NameSpace的常用操作:
- 查看当前系统的namespace:
lsns -t <type>
- 查看某进程的namespace:
ls -la /proc/<pid>/ns/
- 进入某namespace运行命令:
nsenter -t <pid> -n ip addr
- 在新network namespace 执行sleep指令:
unshare -fn sleep 60
- 查看进程信息
ps -ef|grep sleep
- 查看网络NameSpace
lsns -t net