diff --git a/README.md b/README.md index 0563952..b869f3d 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,7 @@ v0.1.4 本书最初源于[WaitFish](mailto:dwj_wz@163.com) 的 pdf内容,后来,[yeasy](github.com/yeasy) -根据最新的官方文档对内容进行了修订,并与作者[WaitFish] -(mailto:dwj_wz@163 -.com)协商,将内容开源,采用互联网合作的方式进行创作和维护。 +根据最新的官方文档对内容进行了修订,重写和增加了部分内容,并与作者[WaitFish](mailto:dwj_wz@163.com)协商,将内容开源,采用互联网合作的方式进行创作和维护。 在线阅读:[https://www.gitbook.io/book/yeasy/docker_practice](https://www.gitbook.io/book/yeasy/docker_practice) diff --git a/SUMMARY.md b/SUMMARY.md index 98e67bb..076a0d9 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -6,22 +6,23 @@ * [更容易部署和扩展](introduction/easy_deployment.md) * [效率更高](introduction/high_efficiency.md) * [快速部署也意味着更简单的管理](introduction/easy_management.md) -* [Docker的体系结构](arch/README.md) - * [内部组件](arch/internal.md) - * [image的工作原理](arch/image.md) - * [仓库](arch/repo.md) - * [容器](arch/container.md) - * [底层技术](arch/underly.md) +* [基本概念](basic_concept/README.md) + * [镜像](basic_concept/internal.md) + * [容器](basic_concept/container.md) + * [仓库](basic_concept/repository.md) * [安装](install/README.md) * [Ubuntu](install/ubuntu144.md) * [CentOS](install/centos.md) -* [image介绍](image/README.md) - * [获取mage](image/get.md) - * [查找image](image/search.md) - * [下载image](image/download.md) - * [创建自己的image](image/create.md) - * [上传image](image/push.md) - * [移除本地image](image/rmi.md) +* [镜像](image/README.md) + * [获取镜像](image/get.md) + * [查找镜像](image/search.md) + * [下载镜像](image/download.md) + * [创建镜像](image/create.md) + * [上传镜像](image/push.md) + * [移除镜像](image/rmi.md) + * [底层原理](image/internal.md) +* [容器](container/README.md) +* [仓库](repository/README.md) * [网络介绍](network/README.md) * [端口映射](network/port_mapping.md) * [docker中的容器互联-linking系统](network/linking.md) @@ -46,6 +47,7 @@ * [内核权限](container_security/kernel_capability.md) * [其他内核安全特性](container_security/other_feature.md) * [结论](container_security/summary.md) +* [底层实现](arch/README.md) * [实战案例](practice/README.md) * [部署本地仓库](practice/local_repo.md) * [使用 Supervisor来管理进程](practice/supervisor.md) diff --git a/arch/README.md b/arch/README.md index 79f0dd1..882acb0 100644 --- a/arch/README.md +++ b/arch/README.md @@ -1,4 +1,4 @@ -#架构 +##基本架构 docker采用了C/S架构,包括client端和daemon端。 docker daemon作为server端接受来自client的请求,并处理这些请求(创建、运行、分发容器)。 client端和server端既可以运行在一个机器上,也可通过socket或者RESTful API来进行通信。 @@ -7,4 +7,29 @@ client端和server端既可以运行在一个机器上,也可通过socket或 Docker daemon一般在宿主主机后台运行,等待接收来自client端的消息。 -Docker client 则为用户提供一系列可执行命令,用户用这些docker命令实现跟docker daemon交互。 \ No newline at end of file +Docker client 则为用户提供一系列可执行命令,用户用这些docker命令实现跟docker daemon交互。 + +##核心技术 +docker底层的2个核心技术分别是Namespaces和Control groups。 + +以下内容摘自InfoQ Docker,自1.20版本开始docker已经抛开lxc,不过下面的内容对于理解docker还是有很大帮助。 + +###pid namespace +不同用户的进程就是通过pid namespace隔离开的,且不同 namespace 中可以有相同pid。所有的LXC进程在docker中的父进程为docker进程,每个lxc进程具有不同的namespace。同时由于允许嵌套,因此可以很方便的实现 Docker in Docker。 + +###net namespace +有了 pid namespace, 每个namespace中的pid能够相互隔离,但是网络端口还是共享host的端口。网络隔离是通过net namespace实现的, 每个net namespace有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。这样每个container的网络就能隔离开来。docker默认采用veth的方式将container中的虚拟网卡同host上的一个docker bridge: docker0连接在一起。 + +###ipc namespace +container中进程交互还是采用linux常见的进程间交互方法(interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同 VM 不同的是,container 的进程间交互实际上还是host上具有相同pid namespace中的进程间交互,因此需要在IPC资源申请时加入namespace信息 - 每个IPC资源有一个唯一的 32 位 ID。 + +###mnt namespace +类似chroot,将一个进程放到一个特定的目录执行。mnt namespace允许不同namespace的进程看到的文件结构不同,这样每个 namespace 中的进程所看到的文件目录就被隔离开了。同chroot不同,每个namespace中的container在/proc/mounts的信息只包含所在namespace的mount point。 + +###uts namespace +UTS("UNIX Time-sharing System") namespace允许每个container拥有独立的hostname和domain name, 使其在网络上可以被视作一个独立的节点而非Host上的一个进程。 + +###user namespace +每个container可以有不同的 user 和 group id, 也就是说可以在container内部用container内部的用户执行程序而非Host上的用户。 + +Control groups主要用来隔离各个容器和宿主主机的资源利用。 diff --git a/arch/internal.md b/arch/internal.md deleted file mode 100644 index 65bdac2..0000000 --- a/arch/internal.md +++ /dev/null @@ -1,18 +0,0 @@ -##内部组件 -docker有三个内部组件 -* images(镜像 -* registries(仓库) -* containers(容器) - -### Images -docker images 就是一个只读的模板。比如:一个image可以包含一个完整的ubuntu的操作系统,里面仅安装了apache或者你需要的其它应用程序。 -images可以用来创建docker containers,docker提供了一个很简单的机制来创建images或者更新现有的images,你甚至可以直接从其他人那里下载一个已经做好的images来直接使用。 - -###Registries -Docker registries 也叫docker仓库,它有公有仓库和私有仓库2种形式,他们都可以用来让你上传和下载images。公有的仓库,即[Docker Hub](https://hub.docker.com),提供了一个数量庞大的image库供用户下载。当然,你也可以在自己的局域网内建一个自己的私有仓库。 - -*从这个意义上看,Docker Hub的功能跟GitHub类似。 - -###Containers -即docker容器,容器是从image镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。 -*image是只读的,container在启动的时候创建可写的一层作为最上层。 diff --git a/arch/underly.md b/arch/underly.md deleted file mode 100644 index e5685e0..0000000 --- a/arch/underly.md +++ /dev/null @@ -1,24 +0,0 @@ -##底层技术 -docker底层的2个核心技术分别是Namespaces和Control groups。 - -以下内容摘自InfoQ Docker,自1.20版本开始docker已经抛开lxc,不过下面的内容对于理解docker还是有很大帮助。 - -###pid namespace -不同用户的进程就是通过pid namespace隔离开的,且不同 namespace 中可以有相同pid。所有的LXC进程在docker中的父进程为docker进程,每个lxc进程具有不同的namespace。同时由于允许嵌套,因此可以很方便的实现 Docker in Docker。 - -###net namespace -有了 pid namespace, 每个namespace中的pid能够相互隔离,但是网络端口还是共享host的端口。网络隔离是通过net namespace实现的, 每个net namespace有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。这样每个container的网络就能隔离开来。docker默认采用veth的方式将container中的虚拟网卡同host上的一个docker bridge: docker0连接在一起。 - -###ipc namespace -container中进程交互还是采用linux常见的进程间交互方法(interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同 VM 不同的是,container 的进程间交互实际上还是host上具有相同pid namespace中的进程间交互,因此需要在IPC资源申请时加入namespace信息 - 每个IPC资源有一个唯一的 32 位 ID。 - -###mnt namespace -类似chroot,将一个进程放到一个特定的目录执行。mnt namespace允许不同namespace的进程看到的文件结构不同,这样每个 namespace 中的进程所看到的文件目录就被隔离开了。同chroot不同,每个namespace中的container在/proc/mounts的信息只包含所在namespace的mount point。 - -###uts namespace -UTS("UNIX Time-sharing System") namespace允许每个container拥有独立的hostname和domain name, 使其在网络上可以被视作一个独立的节点而非Host上的一个进程。 - -###user namespace -每个container可以有不同的 user 和 group id, 也就是说可以在container内部用container内部的用户执行程序而非Host上的用户。 - -Control groups主要用来隔离各个容器和宿主主机的资源利用。 diff --git a/basic_concept/README.md b/basic_concept/README.md new file mode 100644 index 0000000..b5fea06 --- /dev/null +++ b/basic_concept/README.md @@ -0,0 +1,21 @@ +docker有三个基本组件 +* 镜像(Image) +* 容器(Container) +* 仓库(Repository) + + +### 镜像 +docker 镜像就是一个只读的模板。比如:一个镜像可以包含一个完整的ubuntu的操作系统,里面仅安装了apache或者你需要的其它应用程序。 +镜像可以用来创建docker 容器。docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,你甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。 + +###容器 +容器是从image镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个应用程序。 + +*image是只读的,container在启动的时候创建可写的一层作为最上层。 + + +###仓库 +仓库是集中存放镜像文件的场所,可以用来让你上传和下载镜像。分为公有仓库和私有仓库2种形式。公有仓库,目前仅有[Docker Hub](https://hub.docker.com),提供了一个数量庞大的image库供用户下载。当然,用户也可以在本地网络内创建一个私有仓库。 + +*Docker Hub的功能跟GitHub类似。 + diff --git a/arch/container.md b/basic_concept/container.md similarity index 100% rename from arch/container.md rename to basic_concept/container.md diff --git a/basic_concept/image.md b/basic_concept/image.md new file mode 100644 index 0000000..0adf233 --- /dev/null +++ b/basic_concept/image.md @@ -0,0 +1,2 @@ +##镜像 + diff --git a/arch/repo.md b/basic_concept/repository.md similarity index 100% rename from arch/repo.md rename to basic_concept/repository.md diff --git a/image/create.md b/image/create.md index 2ee08a0..7cb502f 100644 --- a/image/create.md +++ b/image/create.md @@ -1,4 +1,4 @@ -##创建我们自己的images +##创建镜像 别人的镜像虽然好,但不一定适合我们。 我们可以对这些镜像做一些修改,有2个方法:利用现成的镜像进行修改或者利用dockerfile创建。 diff --git a/arch/image.md b/image/internal.md similarity index 97% rename from arch/image.md rename to image/internal.md index 227836d..0d323ad 100644 --- a/arch/image.md +++ b/image/internal.md @@ -1,4 +1,4 @@ -##docker image的工作原理 +##工作原理 docker image是怎么实现增量的修改和维护的? 每个docker都有很多层次构成,docker使用 [Union FS](http://en.wikipedia.org/wiki/UnionFS) 将这些不同的层结合到一个image中去。 diff --git a/image/push.md b/image/push.md index df35683..5c7d480 100644 --- a/image/push.md +++ b/image/push.md @@ -1,4 +1,4 @@ -##使用docker push上传images +##上传镜像 用户也可以把自己创建的image上传到docker hub中来共享。 ``` $ sudo docker push ouruser/sinatra diff --git a/image/rmi.md b/image/rmi.md index d89febe..3f28bcc 100644 --- a/image/rmi.md +++ b/image/rmi.md @@ -1,4 +1,4 @@ -##用docker rmi 移除本地images +##移除本地镜像 如果要移除本地的image,可以使用rmi命令。注意rm命令是移除容器。 ``` $ sudo docker rmi training/sinatra diff --git a/install/README.md b/install/README.md index 33a8087..3d389d3 100644 --- a/install/README.md +++ b/install/README.md @@ -1,2 +1,2 @@ #安装 -官方网站上有各个linux发行版的安装指南,这里介绍下centos和ubuntu的安装。 \ No newline at end of file +官方网站上有各个linux发行版的安装指南,这里介绍下centos和ubuntu的安装。 diff --git a/network/linking.md b/network/linking.md index 6a7acd7..c1606f8 100644 --- a/network/linking.md +++ b/network/linking.md @@ -1,14 +1,14 @@ ##docker中的容器互联-linking系统 docker有一个linking 系统可以连接多个容器。它会创建一对父子关系,父容器可以看到所选择的子容器的信息。 ###容器的命名系统 -linking系统依据容器的名称来执行。当我们创建容器的时候,系统会随机分配一个名字。当然我们也可以自己来命名容器,这样做有2个好处: +linking系统依据容器的名称来执行。当我们创建容器的时候,系统会随机分配一个名字。当然用户也可以自己来命名容器,这样做有2个好处: * 当我们自己指定名称的时候,比较好记,比如一个web应用我们可以给它起名叫web * 当我们要连接其他容器时候,可以作为一个有用的参考点,比如连接web容器到db容器 使用--name标记可以为容器命名 ``` $ sudo docker run -d -P --name web training/webapp python app.py ``` -使用docker -ps 来验证我们设定的命名 +使用docker -ps 来验证设定的命名 ``` $ sudo docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES @@ -19,7 +19,7 @@ aed84ee21bde training/webapp:latest python app.py 12 hours ago Up 2 seconds 0 $ sudo docker inspect -f "{{ .Name }}" aed84ee21bde /web ``` -注意:容器的名称是唯一的。如果你命名了一个叫web的容器,当你要再次使用web这个名称的时候,你需要用docker +注意:容器的名称是唯一的。如果你命名了一个叫web的容器,当你要再次使用web这个名称的时候,你需要用docker rm来删除之前创建的容器,也可以再执行docker run的时候 加—rm标记来停止旧的容器,并删除,rm 和-d 参数是不兼容的。 ###容器互联 @@ -75,7 +75,7 @@ PING db (172.17.0.5): 48 data bytes 56 bytes from 172.17.0.5: icmp_seq=0 ttl=64 time=0.267 ms 56 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.250 ms 56 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.256 ms -用ping来ping db容器,它会解析成172.17.0.5 +用ping来ping db容器,它会解析成172.17.0.5 ``` 注意:官方的ubuntu镜像默认没有安装ping -注意:你可以链接多个子容器到父容器,比如我们可以链接多个web到db容器上。 \ No newline at end of file +注意:你可以链接多个子容器到父容器,比如我们可以链接多个web到db容器上。 diff --git a/network/port_mapping.md b/network/port_mapping.md index 07ba92a..7e65034 100644 --- a/network/port_mapping.md +++ b/network/port_mapping.md @@ -1,29 +1,40 @@ ##端口映射 -当我们使用-P 标记时,docker 会随机映射一个49000 到49900的端口到内部容器的端口。 -使用docker ps 可以看到 这次是49155映射到了5000 +当我们使用-P 标记时,docker 会随机映射一个49000 到49900的端口到内部容器开放的端口。 +使用`docker ps`可以看到,本地主机的49155映射到了容器的5000端口。 ``` $ sudo docker run -d -P training/webapp python app.py -$ sudo docker ps nostalgic_morse +$ sudo docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bc533791f3f5 training/webapp:latest python app.py 5 seconds ago Up 2 seconds 0.0.0.0:49155->5000/tcp nostalgic_morse ``` --p(小写的P)可以指定我们要映射的端口,但是,在一个指定端口上只可以绑定一个容器。 +其中,-d是告诉docker在后台启动容器。-P会让docker将容器内必需的网络端口映射到本地主机。 + + +-p(小写的P)则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有`ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort`。 + +###映射所有接口地址 +使用`hostPort:containerPort`格式本地的5000端口映射到容器的5000端口,可以执行 ``` $ sudo docker run -d -p 5000:5000 training/webapp python app.py ``` --p默认会绑定本地所有接口地址,所以我们一般指定一个地址,比如localhost +此时默认会绑定本地所有接口上的所有地址。 + +###映射到指定地址的指定端口 +可以使用`ip:hostPort:containerPort`格式指定映射使用一个特定地址,比如localhost地址127.0.0.1 ``` $ sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py ``` -或者绑定localhost的任意端口到容器的5000端口 +###映射到指定地址的任意端口 +使用`ip::containerPort`绑定localhost的任意端口到容器的5000端口,本地主机会自动分配一个端口。 ``` $ sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py ``` -还可以使用upd标记来指定udp端口 +还可以使用udp标记来指定udp端口 ``` $ sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py ``` -使用dicker port 来查看当前绑定的端口配置,也可以查看到绑定的地址 +###查看映射端口配置 +使用`docker port` 来查看当前映射的端口配置,也可以查看到绑定的地址 ``` $ docker port nostalgic_morse 5000 127.0.0.1:49155.