简述docker容器、docker镜像和网络

一、Docker容器概述

1、docker中的容器技术演进

lxc --> libcontainer --> runC

2、容器的遵循协议规范Open Container Initiative

Linux基金会于2015年6月成立OCI(Open Container Initiative)组织,旨在围绕容器格式和运行时制定一个开放的工业化标准。OCI规范包含两个规格运行规范(runtime-spec)和形象规范(image-spec);

OCI定义了容器运行时标准,runC是Docker按照开放容器格式标准(OCF, Open Container Format)制定的一种具体实现。

runC是从Docker的libcontainer中迁移而来的,实现了容器启停、资源隔离等功能。Docker默认提供了docker-runc实现,事实上,通过containerd的封装,可以在Docker Daemon启动的时候指定runc的实现。

3、 Docker应用

Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。

Docker通常用于如下场景:

web应用的自动化打包和发布;

自动化测试和持续集成、发布;

在服务型环境中部署和调整数据库或其他的后台应用;

从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。

4、docker的核心组件

打开凤凰新闻,查看更多高清图片

image.png

(1)、Docker daemon

Docker 守护进程(dockerd)侦听请求和Docker的API,管理Docker核心对象,如镜像、容器、网络、和卷。

(2)、 Docker client

Docker客户端,命令使用DockerAPI。

(3)、Docker registries

Docker注册镜像库保存了Docker镜像。

Docker公共镜像库和Docker云是公共注册中心,任何人都可以使用,配置后的Docker镜像都可以上传到注册镜像库。

你可以创建和运行自己的私有Docker镜像库。

5、docker的依赖基础环境

依赖的基础环境

处理器要求 64 bits CPU

内核要求 Linux Kernel 3.10+

Linux Kernel cgroups and namespaces

发行版要求 CentOS 7

docker使用的仓库必须有“Extras”仓库

单机上的docker

6、docker的守护进程安装和启动

#查询是否有extras仓库[root@node-65 ~]# yum repolistLoaded plugins: fastestmirrorRepodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fastDetermining fastest mirrors* base: mirrors.aliyun.com* extras: mirrors.tuna.tsinghua.edu.cn* updates: mirrors.tuna.tsinghua.edu.cnrepo id                       repo name                      status!base/7/x86_64                CentOS-7 - Base                10,019!extras/7/x86_64              CentOS-7 - Extras                 314!updates/7/x86_64             CentOS-7 - Updates                598repolist: 10,931#安装docker[root@node-65 ~]# yum install docker -y#配置文件目录[root@node-65 ~]# vim /etc/sysconfig/docker#启动[root@node-65 ~]# systemctl start docker.service#默认docker监听在本机,不能远程[root@node-65 ~]# ls /var/run/docker/libcontainerd/containerd  docker-containerd.pid  docker-containerd.soc

7、docker容器的简单运行

#在公共库查询一个镜像[root@node-65 ~]#  docker search busyboxINDEX       NAME                                  DESCRIPTION                                     STARS     OFFICIAL   AUTOMATEDdocker.io   docker.io/busybox                     Busybox base image.                             1470      [OK]      docker.io   docker.io/progrium/busybox                                                            68                   [OK]docker.io   docker.io/hypriot/rpi-busybox-httpd   Raspberry Pi compatible Docker Image with ...   45                   docker.io   docker.io/radial/busyboxplus          Full-chain, Internet enabled, busybox made...   21          

下载一个镜像

[root@node-65 ~]# docker pull docker.io/busyboxUsing default tag: latestTrying to pull repository docker.io/library/busybox ...latest: Pulling from docker.io/library/busyboxb4a6e23922dd: Pull completeDigest: sha256:8ccbac733d19c0dd4d70b4f0c1e12245b5fa3ad24758a11035ee505c629c0796Status: Downloaded newer image for docker.io/busybox:latest

查询本地镜像

[root@node-65 ~]# docker imagesREPOSITORY          TAG                 IMAGE ID            CREATED             SIZEdocker.io/busybox   latest              758ec7f3a1ee        15 hours ago        1.15 MB

启动容器方法

方法一,docker create方法二,docker run格式: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]--name string 容器名称--rm 容器停止立即删除-i 交互界面--tty 容器启动自动添加一个终端--network string 自动创建网络

docker安装后会自动生成一个网桥,并启动DHCP服务,为生成的容器服务,容器启动后会自动获取ip地址并连接此网桥。

[root@node-65 ~]# ifconfigdocker0: flags=4099 mtu 1500       inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0       ether 02:42:46:9a:3b:6d  txqueuelen 0  (Ethernet)       RX packets 0  bytes 0 (0.0 B)       RX errors 0  dropped 0  overruns 0  frame 0       TX packets 0  bytes 0 (0.0 B)       TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

使用下载镜像启动docker容器

[root@node-65 ~]# docker run --name bbox1 -it docker.io/busybox/ # / # ifconfig     #已经获取到IP地址eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02           inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0............/ # exit    #退出

查询运行的容器

[root@node-65 ~]# docker ps -aCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMESf1984d2b64a2        docker.io/busybox   "sh"                3 minutes ago       Exited (0) 2 minutes ago                       bbox1

容器的删除

[root@node-65 ~]# docker rm bbox1或者ID号

查询docker版本

[root@node-65 ~]# docker versionClient:       #客户端信息Version:         1.13.1API version:     1.26Package version: docker-1.13.1-88.git07f3374.el7.centos.x86_64Go version:      go1.9.4Git commit:      07f3374/1.13.1Built:           Fri Dec  7 16:13:51 2018OS/Arch:         linux/amd64Server:        #服务端信息Version:         1.13.1API version:     1.26 (minimum version 1.12)Package version: docker-1.13.1-88.git07f3374.el7.centos.x86_64Go version:      go1.9.4Git commit:      07f3374/1.13.1Built:           Fri Dec  7 16:13:51 2018OS/Arch:         linux/amd64 Experimental:    false

查询docker信息

[root@node-65 ~]# docker info

二、Docker容器应用

1、Docker组件:

物理组件有:客户端Client <--> 守护进程Daemon <--> 镜像库Registry Server

逻辑组件有:Containers容器,Images镜像、映像,Registry镜像库

2、常用的容器的相关命令

doker官方操作文档:

容器的运行状态

created:创建runing:运行paused:暂停stopped:停止deleted:删除

docker容器命令

docker ps : 查询运行的容器docker run:创建并运行一个容器;docker create:创建一个容器;docker start:启动一个处于停止状态容器;docker kill : 停止容器进程docker stop:停止容器docker restart:重启重启docker pause:暂停容器docker unpause:继续运行容器docker rm :删除容器docker run --rm:运行结束后自动删除容器

查看docker相关的信息命令:

docker version :查看版本

docker info :查看信息

镜像相关命令:

docker images 查询docker rm 删除镜像docker pull 拉取镜像

docker命令流程

3、容器命令应用:

创建容器是基于“镜像文件”,镜像文件中必须有默认要运行的程序,创建方法是联合挂载分层镜像;

注意:

运行的容器内部必须有一个工作前台的运行的进程;

docker的容器的通常也是仅为运行一个程序;

要想在容器内运行多个程序,一般需要提供一个管控程序,例如supervised。

创建容器命令:

docker rundocker create--name CT_NAME--rm:容器运行终止即自行删除--network BRIDGE:让容器加入的网络;默认为docker0;

交互式启动一个容器:

-i:--interactive,交互式;-t:Allocate a pseudo-TTY

从终端拆除容器:

ctrl+p, ctrl+q

附加至某运行状态的容器的终端设备;

docker attach

让运行中的容器运行一个额外的程序;

docker exec

查看容器内部程序运行时输出到终端的信息;

[root@node-65 ~]# docker logs bbox1

查看运行的容器

docker ps -a-a, --all:列出所有容器;--filter, -f:过滤器条件显示name=XXXXXXstatus={stopped|running|paused} #某种状态的容器

动态方式显示容器的资源占用状态:

[root@node-65 ~]# docker stats bbox1CONTAINER           CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDSbbox1               --                  -- / --             --                  --                  --                  --

显示正在运行的流程的一个容器

[root@node-65 ~]# docker top bbox1

三、Docker的镜像

Docker的镜像

1、概述和命令

Docker镜像(Image):可理解为一个面向Docker引擎的只读模板,包含了文件系统。如:一个镜像可以只包含一个完整的操作系统环境,也可以安装了其他的应用程序。通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制来创建和更新现有的镜像。

可见的字段信息:来源于哪一个仓库、镜像的标签信息、镜像的ID(唯一标识了镜像)、创建的时间、镜像的大小。

获取镜像:

docker pull; 命令格式为:docker pull NAME[:TAG], TAG是版本号。默认是latest最新版本。

查看镜像信息:

docker images (查看本地主机上已有的镜像)

为本地镜像添加新的标签:

docker tag(镜像的指向一致,因为不同标签的镜像ID是完全一致的,只是别名不同)

获取镜像的详细信息:

docker inspect, 返回的是JSON格式的消息,可以使用-f参数指定其中的一项内容(docker inspect -f {{“要查看的内容”}}) 镜像ID,可以使用若干个字符组成的可区分字串来代替完整的ID。

搜索镜像:

docker search。可以搜索远端仓库中共享的镜像,默认搜索Docker Hub官方仓库中的镜像。用法为dockersearch TERM,包括的参数有镜像的名字、描述、星级(镜像受欢迎程度)、是否官方支持、是否自动创建。默认的输出结果将按照星级评价进行排序。

删除镜像:

docker rmi IMAGE[IMAGE...], 其中IMAGE可以为标签或ID。当同一个镜像拥有多个标签的时候,docker rmi命令只是删除了该镜像多个标签中的指定标签,并不影响镜像文件。但当镜像只剩下一个标签的时候,再使用docker rmi命令会彻底删除该镜像,会删除这个镜像文件的所有AUFS层。

2、Docker Hub使用:

使用docker最简单的方式莫过于从现有的容器镜像开始。Docker官方网站专门有一个页面来存储所有可用的镜像,网址是:你可以通过浏览这个网页来查找你想要使用的镜像,或者使用命令行的工具来检索。

Docker Hub

首先到Docker Hub官方网站注册用户

docker login登录docker hub

docker logout注销登出docker hub

[root@node-65 ~]# docker login -u 用户名#显示docker hub上的镜像[root@node-65 ~]# docker images

docker push 上传到docker hub

#给指定的镜像添加标签[root@node-65 ~]# docker tag docker.io/busybox;latest docker.io/用户名/bbox:v0.1.0#上传镜像到docker hub[root@node-65 ~]# docker push docker.io/用户名/bbox:v0.1.0#显示docker hub上的镜像[root@node-65 ~]# docker images

docker pull 下载docker hub上的镜像,如果是私有的需要登录才可下载,公共的不需要登录

[root@node-65 ~]# docker docker.io/用户名/bbox:v.0.1.0#显示docker hub上的镜像[root@node-65 ~]# docker images

四、docker的卷

Docker Data Volume

Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层

如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即“写时复制(COW)”机制

可读写层

关闭并重启容器,其数据不受影响;但删除Docker容器,则其更改将会全部丢失

1、 存在的问题

存储于联合文件系统中,不易于宿主机访问;

容器间数据共享不便

删除容器其数据会丢失

2、 解决方案:“卷(volume)”

“卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某目录“绑定(关联)”

容器目录绑定宿主机目录

3、挂载卷分类

(1)docker自行挂载卷

容器启动后,docker会自动在宿主机上生成对应目录,修改容器内部文件,只需修改宿主机上对应文件即可。

有卷管理的docker,容器关闭后,在宿主机自动生成的卷也会自动删除。

#启动一个容器,创建一个可读写目录[root@node-65 ~]# docker run --name h1 --rm -v /data/html -it docker.io/busybox/ # cd /data/html/data/html # vi index.html #编辑

H1 Container#回到宿主机上,docker会自动在宿主机上创建对应的卷#列出当前所有的卷[root@node-65 ]# docker volume listDRIVER              VOLUME NAMElocal               cbb873a851e37cb8afea039a296e296a1f586defa9da#查看对应卷内容[root@node-65 ~]# cat /var/lib/docker/volumes/cbb873a851e37cb8afea039a296e296a1f586defa9da/_data/index.htmlH1 Container  #与容器内部的内容一致  #探测卷的信息[root@node-65 ~]# docker  inspect -f "{{.Mounts}}" h1[{volume cbb873a851e37cb8afea039a296e296a1f586defa9da /var/lib/docker/volumes/cbb873a851e37cb8afea039a296e296a1f586defa9da/_data /data/html local  true }]

(2)用户指定的挂载卷

#在宿主机上创建卷[root@node-65 ~]# mkdir /appdata/html -pvmkdir: created directory ‘/appdata’mkdir: created directory ‘/appdata/html’#编辑内容[root@node-65 ~]# vim /appdata/html/index.html

Test Page~  #指定容器内部目录和宿主机对应的卷,并启动容器[root@node-65 ~]# docker run --name h2 -d -it -v /appdata/html:/data/html docker.io/hehe/bbox:v0.1.1-httpd #测试    [root@node-65 ~]# curl http://172.17.0.2Test Page         

4、删除卷

删除容器之时删除相关的卷为docker rm命令使用-v选项

删除指定的卷docker volume rm

[root@node-65 ~]# docker kill h2h2#删除容器时,-v 同时删除宿主机上的卷[root@node-65 ~]# docker rm -v h2h2

5、多个容器的卷使用同一个主机目录

例如

多个容器的卷使用同一个主机目录

~]# docker run –it --name c1 -v /docker/volumes/v1:/data busybox

~]# docker run –it --name c2 -v /docker/volumes/v1:/data busybox

6、复制使用其它容器的卷

为docker run命令使用--volumes-from选项

卷模板

~]# docker run -it --name bbox1 -v /docker/volumes/v1:/data busybox

~]# docker run -it --name bbox2 --volumes-from bbox1 busybox

五、Docker容器的网络

1、桥接Bridge类型

lsolated:隔离桥接,仅容器间网络通信

Host-only:仅主机桥接,宿主机和各个容器网络通信

NAT:地址转换桥接,容器有内网地址,通过宿主机核心转发,与外网主机网络通信

Phy Bridged:物理桥接,使容器与物理网卡同一网络地址的,与外网网络通信

docker容器网络类型

2、Docker网桥类型

Docker安装完成后,会自动创建三个网络,可使用“dockernetwork ls”命令查看

bridge 桥接式网络host 开放式网络none 封闭式网络

3、Docker网桥创建命令

创建容器时,可为docker run命令使用--net选项指定要加入的网络

(1) none 封闭式网络

~]# docker run --rm --net none busybox:latest ifconfig -a

(2) bridge 桥接式网络

桥接式容器一般拥有两个接口:一个环回接口和一个连接至主机上某桥设备的以太网接口

docker daemon启动时默认会创建一个名为docker0的网络桥,并且创建的容器为桥接式容器,其以太网接口桥接至docker0

--net bridge即为将容器接口添加至docker0桥

docker0桥为NAT桥,因此,桥接式容器可通过此桥接口访问外部网络,但防火墙规则阻止了一切从外部网络访问桥接式容器的请求

~]# docker run --rm --net bridge busybox:latest ifconfig -a

配合docker run命令使用网络选项

“--hostname HOSTNAME”选项为容器指定主机名

“--dns DNS_SERVER_IP”选项能够为容器指定所使用的dns服务器地址

“--add-host HOSTNAME:IP”选项能够为容器指定本地主机名解析项

[root@node-65 ~]# docker run --name bbox1 --rm --net bridge -it --hostname bbox1.hehe.com --dns 192.167.1.1 --add-host www.hehe.com:192.167.0.1 busybox / # cat /etc/hosts     #主机名称127.0.0.1   localhost::1 localhost ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters192.167.0.1 www.hehe.com172.17.0.2  bbox1.hehe.com

/ # cat /etc/resolv.conf    #查询dns解析nameserver 192.167.1.1/ # hostname    #查询主机名bbox1.hehe.com

(3)联盟式桥接

联盟式容器是指使用某个已存在容器的网络接口的容器,接口被联盟内的各容器共享使用;因此,联盟式容器彼此间完全无隔离

例如

# 创建一个监听于2222端口的http服务容器

~]# docker run -d -it --rm -p 2222 busybox:latest /bin/httpd -p 2222 -f# 创建一个联盟式容器,并查看其监听的端口

~]# docker run -it --rm --net container:web --name joined busybox:latestnetstat -tan

联盟式容器彼此间虽然共享同一个网络名称空间,但其它名称空间如User、Mount等还是隔离的

联盟式容器彼此间存在端口冲突的可能性,因此,通常只会在多个容器上的程序需要程序loopback接口互相通信、或对某已存的容器的网络属性进行监控时才使用此种模式的网络模型

(4) host 开放式网络

开放式容器共享主机网络名称空间的容器,它们对主机的网络名称空间拥有全部的访问权限,包括访问那些关键性服务,这对宿主机安全性有很大潜在威胁

为docker run命令使用“--net host”选项即可创建开放式容器,例如:

~]# docker run -it --rm --net host busybox:latest /bin/s

4、容器的端口暴露

将指定的容器端口映射至主机所有地址的一个动态端口-p:

#将容器的80端口映射到宿主机的随机端口[root@node-65 ~]#  docker run --name h1 --rm --net bridge  -d -p 80  docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html#查询映射到那个随机端口[root@node-65 ~]# docker port h180/tcp -> 0.0.0.0:32769#测试访问[root@node-65 ~]# curl 192.168.1.65:32769

BUSY BOX SERVER

将容器端口映射至指定的主机端口-p::

#指明容器的80端口映射到宿主机的90端口[root@node-65 ~]# docker run --name h1 --rm --net bridge  -d -p 90:80  docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html#查询端口映射[root@node-65 ~]# docker port h180/tcp -> 0.0.0.0:90#测试[root@node-65 ~]# curl 192.168.1.65:90

BUSY BOX SERVER

将指定的容器端口映射至主机指定的动态端口-p::

#指定容器80端口映射到宿主机的指定ip的随机端口[root@node-65 ~]# docker run --name h1 --rm --net bridge  -d -p 192.168.1.65::80  docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html#查询端口映射[root@node-65 ~]# docker port h180/tcp -> 192.168.1.65:32768#测试[root@node-65 ~]# curl 192.168.1.65:32768

BUSY BOX SERVER

将指定的容器端口映射至主机指定的端口

#指定容器的80端口映射到宿主机的指定ip的90端口[root@node-65 ~]# docker run --name h1 --rm --net bridge  -d -p 192.168.1.65:90:80  docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html#查询映射端口[root@node-65 ~]# docker port h180/tcp -> 192.168.1.65:90#测试[root@node-65 ~]# curl 192.168.1.65:90

BUSY BOX SERVER

多端口暴露一

[root@node-65 ~]# docker run --name h1 --rm --net bridge  -d -p 192.168.1.65:90:80 -p 8090:8080 -p 10080:10080 docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html#查询映射端口[root@node-65 ~]# docker port h/tcp -> 0.0.0.0:/tcp -> 192.168.1.65:/tcp -> 0.0.0.0:8090

多端口暴露二

使用“-P”选项或“--publish-all”将容器的所有计划要暴露端口全部映射至主机端口

计划要暴露的端口使用使用--expose选项指定

例如:

[root@node-65 ~]# docker run --name h3 --rm --net bridge  -d -P --expose 2222 --expose 3333   docker.io/hehe/bbox:v0.1.1-httpd /bin/httpd -f -h /data/html#查询映射端口[root@node-65 ~]# docker port h32222/tcp -> 0.0.0.0:/tcp -> 0.0.0.0:32771

“动态端口”指随机端口,具体的映射结果可使用docker port命令查看

5、docker默认网络配置

如果不想使用默认的docker0桥接口,或者需要修改此桥接口的网络属性,可通过为docker daemon命令使用-b、--bip、--fixed-cidr、--default-gateway、--dns以及--mtu等选项进行设定

#修改默认启动容器的网络配置[root@node-65 ~]# vim /etc/sysconfig/docker-network # /etc/sysconfig/docker-networkDOCKER_NETWORK_OPTIONS="添加--b、--dns、--bip等选项"

6、自定义网桥

docker创建一个新网桥

[root@node-65 ~]# docker network create -d bridge --subnet=172.16.0.0/16 --ip-range=172.16.0.0/16 --gateway=172.16.0.254 mybr06f3b263dfd24fa7884a44caf151c3ed934eed7200ed0d491ae1c8f214#查询docker网络[root@node-65 ~]# docker network lsNETWORK ID          NAME                DRIVER              SCOPE..........6f3b263dfd24        mybr0               bridge              local...........

--subnet:指明子网--driver:指明设备--ip-range:容器加入时获取的地址范围--gateway:指明网关

创建容器使用mybr0网桥

[root@node-65 ~]# docker run --name h2 --rm -it --net mybr0 -v /appdata/html:/data/html docker.io/hehe/bbox:v0.1.1-httpd / # ifconfigeth0      Link encap:Ethernet  HWaddr 02:42:AC:10:00:01           inet addr:172.16.0.1  Bcast:0.0.0.0  Mask:255.255.0.0  #以获取ip地址

给运行的容器添加网桥

[root@node-65 ~]# docker network connect bridge h2#在容器内部查询网络/ # ifconfigeth0      Link encap:Ethernet  HWaddr 02:42:AC:10:00:01           inet addr:172.16.0.1  Bcast:0.0.0.0  Mask:255.255.0.0  #连接指定的mybr0网桥    .........eth1      Link encap:Ethernet  HWaddr 02:42:AC:11:00:03           inet addr:172.17.0.3  Bcast:0.0.0.0  Mask:255.255.0.0  #多出来一个设备连接默认docker的网桥.............

给运行的容器撤销网桥

[root@node-65 ~]# docker network disconnect bridge h2#在容器内部查询网络/ # ifconfigeth0      Link encap:Ethernet  HWaddr 02:42:AC:10:00:01           inet addr:172.16.0.1  Bcast:0.0.0.0  Mask:255.255.0.0   #只剩下一个网桥了

7、docker的叠加网络

$ docker network create -d overlay \ --subnet=192.168.1.0/25 \ --subnet=192.170.2.0/25 \ --gateway=192.168.1.100 \ --gateway=192.170.2.100 \ --aux-address="my-router=192.168.1.5" --aux-address="my-switch=192.168.1.6" \ --aux-address="my-printer=192.170.1.5" --aux-address="my-nas=192.170.1.6" \ my-multihost-network

--aux-address:辅助网络地址