首页 > 技术文章 > docker

luckpiky 2019-09-01 12:15 原文

什么是Docker

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

Docker的应用场景

  • Web 应用的自动化打包和发布。
  • 自动化测试和持续集成、发布。
  • 在服务型环境中部署和调整数据库或其他的后台应用。
  • 从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。

Docker的架构

Docker使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
Docker 容器通过 Docker 镜像来创建。
容器与镜像的关系类似于面向对象编程中的对象与类。容器是对象,镜像就是类。

Docker 镜像(Images):Docker 镜像是用于创建 Docker 容器的模板。

Docker 容器(Container):容器是独立运行的一个或一组应用。

Docker 客户端(Client):Docker 客户端通过命令行或者其他工具使用 Docker API 与 Docker 的守护进程通信。

Docker 主机(Host):一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。

Docker 仓库(Registry):Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub 提供了庞大的镜像集合供使用。

Docker Machine:Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。
image

Docker与虚拟机的区别

Docker守护进程可以直接与主操作系统进行通信,为各个Docker容器分配资源;它还可以将容器与主操作系统隔离,并将各个容器互相隔离。虚拟机启动需要数分钟,而Docker容器可以在数毫秒内启动。由于没有臃肿的从操作系统,Docker可以节省大量的磁盘空间以及其他系统资源。
image

容器间如何通信

单主机容器通信

  • bridge:docker默认的网络模式,为容器创建独立的网络命名空间,容器具有独立的网卡等所有单独的网络栈,是最常用的使用方式。
  • host:直接使用容器宿主机的网络命名空间。
  • none:为容器创建独立网络命名空间,但不为它做任何网络配置,容器中只有lo,用户可以在此基础上,对容器网络做任意定制。
  • 用户自定义:docker 1.9版本以后新增的特性,允许容器使用第三方的网络实现或者创建单独的bridge网络,提供网络隔离能力。
  • 其他容器:与host模式类似,只是容器将与指定的容器共享网络命名空间。

跨主机容器通信

  • 容器使用host模式:容器直接使用宿主机的网络,这样天生就可以支持跨主机通信。虽然可以解决跨主机通信问题,但这种方式应用场景很有限,容易出现端口冲突,也无法做到隔离网络环境,一个容器崩溃很可能引起整个宿主机的崩溃。
  • 端口绑定:通过绑定容器端口到宿主机端口,跨主机通信时,使用主机IP+端口的方式访问容器中的服务。显而易见,这种方式仅能支持网络栈的四层及以上的应用,并且容器与宿主机紧耦合,很难灵活的处理,可扩展性不佳。
  • docker外定制容器网络:在容器通过docker创建完成后,然后再通过修改容器的网络命名空间来定义容器网络。典型的就是很久以前的pipework,容器以none模式创建,pipework通过进入容器的网络命名空间为容器重新配置网络,这样容器网络可以是静态IP、vxlan网络等各种方式,非常灵活,容器启动的一段时间内会没有IP,明显无法在大规模场景下使用,只能在实验室中测试使用。
  • 第三方SDN定义容器网络:使用Open vSwitch或Flannel等第三方SDN工具,为容器构建可以跨主机通信的网络环境。这些方案一般要求各个主机上的docker0网桥的cidr不同,以避免出现IP冲突的问题,限制了容器在宿主机上的可获取IP范围。并且在容器需要对集群外提供服务时,需要比较复杂的配置,对部署实施人员的网络技能要求比较高。
  • 基于隧道的overlay网络:按隧道类型来说,不同的公司或者组织有不同的实现方案。docker原生的overlay网络就是基于vxlan隧道实现的。ovn则需要通过geneve或者stt隧道来实现的。flannel最新版本也开始默认基于vxlan实现overlay网络。
  • 基于包封装的overlay网络:基于UDP封装等数据包包装方式,在docker集群上实现跨主机网络。典型实现方案有weave、flannel的早期版本。
  • 基于三层实现SDN网络:基于三层协议和路由,直接在三层上实现跨主机网络,并且通过iptables实现网络的安全隔离。典型的方案为Project Calico。同时对不支持三层路由的环境,Project Calico还提供了基于IPIP封装的跨主机网络实现。

安装docker

mint系统:

$ sudo apt-get install docker-io

测试docker

$ sudo docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
...

更换阿里云的仓库,默认的太慢

curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh -
echo "DOCKER_OPTS=\"--registry-mirror=https://pee6w651.mirror.aliyuncs.com\"" | sudo tee -a /etc/default/docker
sudo service docker restart

使用python镜像

$ sudo docker pull python

#查看本地镜像
$ sudo docker images
python                           latest              336d482502ab        2 weeks ago         692 MB   
692MB有点大

#写一个python脚本:t1.py
print("hello")

#启动docker
$ sudo docker run -v $PWD:/usr/src/myapp -w /usr/src/myapp python python t1.py
hello

看看其他的镜像

image

进入docker的bash

xiaoyi@xiaoyi-Rev-1-0 ~/coding $ sudo docker run -i -t django /bin/bash
root@84447118a8af:/#
root@84447118a8af:/# ls
bin   dev  home  lib64	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 media	opt  root  sbin  sys  usr
root@84447118a8af:/# exit
exit
xiaoyi@xiaoyi-Rev-1-0 ~/coding $ 

创建一个project,并启动django

xiaoyi@xiaoyi-Rev-1-0 ~/coding/fundxray $ sudo docker run -v $PWD:/usr/app -w /usr/app django python manage.py startproject test1
xiaoyi@xiaoyi-Rev-1-0 ~/github_blog/luckpiky.github.io $ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
b1057f58ce57        django              "python manage.py ..."   3 seconds ago       Up 2 seconds                            determined_knuth

xiaoyi@xiaoyi-Rev-1-0 ~/github_blog/luckpiky.github.io $ sudo docker inspect 48cdb5a0cee4

...
"IPAddress": "172.17.0.2",
...
iaoyi@xiaoyi-Rev-1-0 ~/github_blog/luckpiky.github.io $ ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.157 ms


保存容器中修改的内容到新的镜像中

以下是windows上跑的docker:
PS C:\Users\Administrator> docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
centos_dev                 latest              9e74d525d304        11 hours ago        387MB
ubuntu                     latest              c9d990395902        9 days ago          113MB
centos                     latest              e934aafc2206        2 weeks ago         199MB
docker4w/nsenter-dockerd   latest              cae870735e91        5 months ago        187kB
PS C:\Users\Administrator> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
e4c97441ceb1        centos_dev          "/bin/bash"         11 minutes ago      Up 11 minutes                           relaxed_ride
PS C:\Users\Administrator> docker  commit e4c97441ceb1 "dev2"
sha256:50450538bc3948a81f5f947f285ecafd7430de9d3b76e22ae8a43c1eed0ab397
PS C:\Users\Administrator>
PS C:\Users\Administrator> docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
dev2                       latest              50450538bc39        6 seconds ago       387MB
centos_dev                 latest              9e74d525d304        11 hours ago        387MB
ubuntu                     latest              c9d990395902        9 days ago          113MB
centos                     latest              e934aafc2206        2 weeks ago         199MB
docker4w/nsenter-dockerd   latest              cae870735e91        5 months ago        187kB
PS C:\Users\Administrator>

保存后的镜像,使用docker -i -t xxx启动后,原先设置的环境都还存在,比如之前制定的文件夹映射等。

删除镜像

PS C:\Users\Administrator> docker rmi dev2
Untagged: dev2:latest
Deleted: sha256:50450538bc3948a81f5f947f285ecafd7430de9d3b76e22ae8a43c1eed0ab397
PS C:\Users\Administrator>

这里删除时,如果镜像曾经运行过,会删除失败,网上找到的说要用docker rm XXX删除对应的容器id(可以使用docker ps -L来查看之前运行过的容器记录),删除容器引用后,确实能够删除镜像了,但是多删除了一个其他镜像的引用,结果该镜像就无法运行了,不知道什么原因。

进入一个已经启动的容器

PS C:\Users\Administrator\Desktop> docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
afaa331cd991        centos_dev          "/bin/bash"         About an hour ago   Up About an hour                        elegant_noether
PS C:\Users\Administrator\Desktop> docker attach afaa331cd991

采用ps查看运行的docker容器,看到容器id,使用attach 容器id直接进入。

推荐阅读