Docker:相比虚拟机的交付速度更快,资源消耗更低,Docker 采用客户端/服务端架构,使用远程 API 来管理和创建 Docker 容器,其可以轻松的创建一个轻量级的、可移植的、自给自足的容器,docker 的三大理念是 build(构建)、ship(运输)、run(运行),Docker 遵从apache 2.0 协议,并通过(namespace 及cgroup 等)来提供容器的资源隔离与安全保障等,所以 Docker 容器在运行时不需要类似虚拟机(空运行的虚拟机占用物理机 6-8%性能)的额外资源开销,因此可以大幅提高资源利用率,总而言之 Docker 是一种用了新颖方式实现的轻量级虚拟机,类似于 VM 但是在原理和应用上和 VM 的差别还是很大的,并且 docker的专业叫法是应用容器(Application Container)。
docker 的组成:
Docker 客户端(Client):客户端使用 docker 命令或其他工具调用 docker API。
Docker 服务端(Server):Docker 守护进程,运行 docker 容器。
Docker 镜像(Images):镜像可以理解为创建实例使用的模板。
Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务。
Docker 仓库(Registry): 保存镜像的仓库,类似于 git 或 svn 这样的版本控制系统,官方仓库: https://hub.docker.com/
Docker 主机(Host):一个物理机或虚拟机,用于运行 Docker 服务进程和容器。
![](https://s1.51cto.com/images/blog/201904/04/abc94e6408edc838d772408d490d8865.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)![]
Docker 的优势:
快速部署:短时间内可以部署成百上千个应用,更快速交付到线上。
高效虚拟化:不需要额外的 hypervisor 支持,直接基于 linux 实现应用虚拟化,相比虚拟机大幅提高性能和效率。
节省开支:提高服务器利用率,降低 IT 支出。
简化配置:将运行环境打包保存至容器,使用时直接启动即可。
快速迁移和扩展:可跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从 A 宿主机迁移到 B 宿主机,甚至是 A 平台迁移到 B 平台。
Docker的缺点:隔离性:各应用之间的隔离不如虚拟机。
docker(容器)的核心技术:
容器规范:除了 docker 之外的 docker 技术,还有 coreOS 的 rkt,还有阿里的 Pouch,为了保证容器生态的标志性和健康可持续发展包括 Google、Docker 等公司共同成立了一个叫 open container(OCI)的组织,其目的就是制定开放的标准的容器规范,目前OCI 一共发布了两个规范,分别是 runtime spec 和 image format spec,有了这两个规范,不通的容器公司开发的容器只要兼容这两个规范,就可以保证容器的可移植性和相互可操作性。
容器 runtime:runtime 是真正运行容器的地方,因此为了运行不同的容器 runtime 需要和操作系统内核紧密合作相互在支持,以便为容器提供相应的运行环境。
目前主流的三种 runtime:
Lxc:linux 上早期的 runtime,Docker 早期就是采用 lxc 作为 runtime。
runc:目前 Docker 默认的 runtime,runc 遵守 OCI 规范,因此可以兼容 lxc。
rkt:是 CoreOS 开发的容器 runtime,也符合 OCI 规范,所以使用 rktruntime 也可以运行 Docker 容器。
容器管理工具:管理工具连接 runtime 与用户,对用户提供图形或命令方式操作,然后管理工具将用户操作传递给 runtime 执行。
Lxd 是 lxc 的管理工具。Rkt 的管理工具是 rkt cli。
Runc 的管理工具是 docker engine,docker engine 包含后台 deamon 和 cli 两部分,大家经常提到的 Docker 就是指的 docker engine。
容器定义工具:容器定义工具允许用户定义容器的属性和内容,以方便容器能够被保存、共享和重建。
Docker image:是 docker 容器的模板,runtime 依据 docker image 创建容器。
Dockerfile:包含 N 个命令的文本文件,通过 dockerfile 创建出 docker image。
ACI(App container image):与 docker image 类似,是 CoreOS 开发的 rkt 容器的镜像格式。
Registry:统一保存共享镜像的地方,叫做镜像仓库。
Image registry:docker 官方提供的私有仓库部署工具。
Docker hub:docker 官方的公共仓库,已经保存了大量的常用镜像,可以方便大家直接使用。
Harbor:vmware 提供的自带 web 的镜像仓库,目前有很多公司使用。
编排工具:使用k8s,当多个容器在多个主机运行的时候,单独管理每个容器是相当负载而且很容易出错,而且也无法实现某一台主机宕机后容器自动迁移到其他主机从而实现高可用的目的,也无法实现动态伸缩的功能,因此需要有一种工具可以实现统一管理、动态伸缩、故障自愈、批量执行等功能,这就是容器编排引擎。容器编排通常包括容器管理、调度、集群定义和服务发现等功能。
Docker swarm:docker 开发的容器编排引擎。
Kubernetes:google 领导开发的容器编排引擎,内部项目为 Borg,且其同时支持docker 和 CoreOS。
Mesos+Marathon:通用的集群组员调度平台,mesos 与 marathon 一起提供容器编排引擎功能。
docker(容器)的依赖技术:
容器网络:docker 自带的网络 docker network 仅支持管理单机上的容器网络,当多主机运行的时候需要使用第三方开源网络,例如calico、flannel 等。不存放数据。
服务发现:
容器的动态扩容特性决定了容器 IP 也会随之变化,因此需要有一种机制开源自动识别并将用户请求动态转发到新创建的容器上,kubernetes 自带服务发现功能,需要结合 kube-dns 服务解析内部域名。
容器监控:
可以通过原生命令 docker ps/top/stats 查看容器运行状态,另外也可以使heapster/Prometheus等第三方监控工具监控容器的运行状态。
数据管理:
容器的动态迁移会导致其在不通的 Host 之间迁移,因此如何保证与容器相关的数据也能随之迁移或随时访问,可以使用逻辑卷/存储挂载等方式解决。
日志收集:错误日志:(500/403),访问日志:用户是从哪里访问的。
docker 原生的日志查看工具 docker logs,但是容器内部的日志需要通过 ELK 等专门的日志收集分析和展示工具进行处理
DOcker安装及基础命令:官方网址:https://www.docker.com/
阿里云docker镜像站:https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/
自2017 年推出(将 docker 更名为)新的项目Moby,github 地址:https://github.com/moby/moby,Moby 项目属于 Docker 项目的全新上游,Docker 将是一个隶属于的 Moby 的子产品,而且之后的版本之后开始区分为 CE 版本(社区版本)和 EE(企业收费版)。
一、yum安装:[root@host-172-20-102-99 src]#yum install https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/docker-ce-18.06.3.ce-3.el7.x86_64.rpm
[root@99 src]#systemctl start docker
[root@99 src]#ps -ef |grep docker 此时守护进程已开启:
root 12712 1 0 21:25 ? 00:00:00 /usr/bin/dockerd
root 12719 12712 0 21:25 ? 00:00:00 docker-containerd --config /var/run/docker/containerd/containerd.toml
root 12915 3911 0 21:26 pts/0 00:00:00 grep --color=auto docker
[root@99 src]#docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 18.06.3-ce
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
runc version: a592beb5bc4c4092b1b1bac971afed27687340c5
init version: fec3683
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-957.1.3.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 1.795GiB
Name: 99
ID: 76UK:CYYR:3EEB:7IGO:4JAS:ZAQH:FB7N:EHP4:KV2J:V3S3:O5MU:4U32
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
验证网卡:在 docker 安装启动之后,默认会生成一个名称为 docker0 的网卡并且默认 IP 地址为 172.17.0.1 的网卡。
[root@99 ~]#ifconfig
docker0: flags=4099
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:4d:eb:6d:8f 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
二、通过修改 yum 源安装:[root@docker-server1 ~]# rm -rf /etc/yum.repos.d/*
[root@docker-server1 ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo
http://mirrors.aliyun.com/repo/Centos-7.repo
[root@docker-server1 ~]# wget -O /etc/yum.repos.d/epel.repo
http://mirrors.aliyun.com/repo/epel-7.repo
[root@docker-server1 ~]# wget -O /etc/yum.repos.d/docker-ce.repo
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@docker-server1 ~]# yum install docker-ce
[root@106 yum.repos.d]#systemctl start docker
[root@106 yum.repos.d]#systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
这时,我们做镜像的导出和导入:从99主机导出,并导入到106主机:
[root@99 ~]#docker save nginx:1.14.2 > /opt/nginx-docker-images_1.14.12.tar.gz
[root@99 ~]#scp /opt/nginx-docker-images_1.14.12.tar.gz 172.20.102.106:/opt/
[root@106 apps]#docker load < /opt/nginx-docker-images_1.14.12.tar.gz
5dacd731af1b: Loading layer 58.45MB/58.45MB
Loaded image: nginx:1.14.2
镜像仓库官网:https://hub.docker.com
[root@99 src]#docker pull nginx:1.14.2 下载Nginx:centos/php 的下载方式与此一样。
1.14.2: Pulling from library/nginx
27833a3ba0a5: Pull complete
0f23e58bd0b7: Pull complete
8ca774778e85: Pull complete
Digest: sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d
Status: Downloaded newer image for nginx:1.14.2
[root@99 src]#docker pull centos
Using default tag: latest
latest: Pulling from library/centos
8ba884070f61: Pull complete
Digest: sha256:8d487d68857f5bc9595793279b33d082b03713341ddec91054382641d14db861
Status: Downloaded newer image for centos:latest
[root@99 src]#docker pull centos:7.5.1804
7.5.1804: Pulling from library/centos
5ad559c5ae16: Pull complete
Digest: sha256:c777d447a06ac17206510fdbbafe1a9ae49c26684c01c7663a1214a1a476bbdf
Status: Downloaded newer image for centos:7.5.1804
查看下载的镜像:[root@99 src]#docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.14.2 295c7be07902 7 days ago 109MB
centos 7.5.1804 cf49811e3cdb 2 weeks ago 200MB
centos latest 9f38484d220f 2 weeks ago 202MB
docker 镜像加速配置:官网地址:http://cr.console.aliyun.com,
[root@99 ~]#mkdir -p /etc/docker
[root@99 ~]#vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://9916w1ow.mirror.aliyuncs.com"] 把镜像加速器地址指向阿里云。
}
[root@99 ~]#systemctl daemon-reload
[root@99 ~]#systemctl restart docker
[root@99 ~]#docker info
CPUs: 2
Total Memory: 1.795GiB
Name: 99
ID: 76UK:CYYR:3EEB:7IGO:4JAS:ZAQH:FB7N:EHP4:KV2J:V3S3:O5MU:4U32
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/ 默认地址!!
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://9916w1ow.mirror.aliyuncs.com/ 我们给指定的地址!!
Live Restore Enabled: false
这时候我们再去pull下载镜像就会非常快了!
Docker 镜像基础命令:
1、搜索镜像:[root@99 ~]#docker search (images)centos:7.2.1809 #带指定版本号
[root@99 ~]#docker search (images)centos #不带版本号默认为latest
2、下载镜像:从 docker 仓库将镜像下载到本地。
[root@docker-server1 ~]# docker pull (images)nginx
3、查看本地镜像:[root@docker-server1 ~]# docker images
REPOSITORY #镜像所属的仓库名称
TAG #镜像版本号(标识符),默认为 latest
IMAGE ID #镜像唯一 ID 标示
CREATED #镜像创建时间
VIRTUAL SIZE #镜像的大小
镜像导出:可以将镜像从本地导出为一个压缩文件,然后复制到其他服务器进行导入使用。
4、从镜像启动一个容器:会直接进入到容器,并随机生成容器 ID 和名称
[root@99 src]#docker run -it docker.io/nginx bash
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
27833a3ba0a5: Already exists
e83729dd399a: Pull complete
ebc6a67df66d: Pull complete
Digest: sha256:c8a861b8a1eeef6d48955a6c6d5dff8e2580f13ff4d0f549e082e7c82a8617a2
Status: Downloaded newer image for nginx:latest
/>root@e7d1c0d66e05:/#(ctrl+p+q)#退出容器不注销
5、显示所有的容器,包括当前正在运行以及已经关闭的所有容器:[root@99 src]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e7d1c0d66e05 nginx "bash" 28 seconds ago Up 27 seconds 80/tcp compassionate_jang
6、删除运行中的容器:即使容正在运行当中,也会被强制删除掉:
[root@99 src]#docker rm -f e7d1c0d66e05
e7d1c0d66e05
7、删除镜像:[root@99 src]#docker rmi nginx
Untagged: nginx:latest
Untagged: nginx@sha256:c8a861b8a1eeef6d48955a6c6d5dff8e2580f13ff4d0f549e082e7c82a8617a2
Deleted: sha256:2bcb04bdb83f7c5dc30f0edaca1609a716bda1c7d2244d4f5fbbdfef33da366c
Deleted: sha256:dfce9ec5eeabad339cf90fce93b20f179926d5819359141e49e0006a52c066ca
Deleted: sha256:166d13b0f0cb542034a2aef1c034ee2271e1d6aaee4490f749e72d1c04449c5b
8、导出镜像:[root@99 ~]#docker save nginx:1.14.2 > /opt/nginx-docker-images_1.14.12.tar.gz
9、导入镜像:[root@106 apps]#docker load < /opt/nginx-docker-images_1.14.12.tar.gz
5dacd731af1b: Loading layer 58.45MB/58.45MB
Loaded image: nginx:1.14.2
10、随机映射端口:
#前台启动并随机映射本地端口到容器的 80;#前台启动的会话窗口无法进行其他操作,除非退出,但是退出后容器也会退出,如下:
[root@99 ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 :::32768 :::
[root@99 ~]#lsof -i:32768
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 13062 root 4u IPv6 418992 0t0 TCP :filenet-tms (LISTEN)
访问端口:
12、指定端口映射:
方法一、[root@99 src]#docker run -p 172.20.102.99:82:80 --name nginx-test-port2 docker.io/nginx
[root@99 ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 172.20.102.99:82 :::
访问端口:
方式二、本地端口 81 映射到容器 80 端口: # docker run -p 81:80 --name nginx-test-port1 nginx
方式三、本地 IP:本地随机端口:容器端口: # docker run -p 192.168.10.205::80 --name nginx-test-port3 docker.io/nginx
方式四、本机 ip:本地端口:容器端口/协议,默认为 tcp 协议 # docker run -p 192.168.10.205:83:80/udp --name nginx-test-port4 docker.io/nginx
方式五、一次性映射多个端口+协议: # docker run -p 86:80/tcp -p 443:443/tcp -p 53:53/udp --name nginx-test-port5docker.io/nginx
13、查看 Nginx 容器访问日志:[root@99 ~]#docker logs nginx-test-port2
172.20.0.1 - - [04/Apr/2019:00:38:41 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" "-"
2019/04/04 00:38:41 [error] 6#6: 3 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.20.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "172.20.102.99:82"
172.20.0.1 - - [04/Apr/2019:00:38:41 +0000] "GET /favicon.ico HTTP/1.1" 404 154 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" "-"
14、查看容器已经映射的端口:[root@99 ~]#docker port nginx-test-port2
80/tcp -> 172.20.102.99:82
15、自定义容器名称:
[root@99 ~]#docker run -it --name nginx-test nginx
16、后台启动容器:
[root@99 ~]#docker run -d -P --name nginx-test1 docker.io/nginx
7f9ece042db26cf70fbccbfd2576e850af81ac75e251cfc306e188bfc8468236
[root@99 ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f9ece042db2 docker.io/nginx "nginx -g 'daemon of…" About a minute ago Up About a minute 0.0.0.0:32769->80/tcp nginx-test1
17、创建并进入容器:
[root@99 ~]#docker run -t -i --name test-centos2 docker.io/centos
/bin/bash[root@d5e849aaa78b /]# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.2 0.1 11820 1904 pts/0 Ss 00:59 0:00 /bin/bash 第一个进程
root 14 0.0 0.0 51740 1728 pts/0 R+ 01:00 0:00 ps -aux
18、容器退出后自动删除:
[root@99 ~]#docker run -it --rm --name nginx-delete-test docker.io/nginx
端口映射部分的参数:
-d:表示以“守护模式”执行,日志不会出现在输出终端上。
-i:表示以“交互模式”运行容器,-i 则让容器的标准输入保持打开
-t:表示容器启动后会进入其命令行,-t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
-v:表示需要将本地哪个目录挂载到容器中,格式:-v <宿主机目录>:<容器目录>,-v 标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用可以挂载多个数据卷。
-p:表示宿主机与容器的端口映射,此时将容器内部的 22 端口映射为宿主机的 9999 端口,这样就向外界暴露了9999 端口,可通过 Docker 网桥来访问容器内部的 22 端口了。
19、传递运行命令:
[root@99 ~]#docker run -d centos /usr/bin/tail -f '/etc/hosts'
f8e576fcb93b012e5351c6bbbc264ce149cd308669347f75d82890db3e40c355
[root@99 ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f8e576fcb93b centos "/usr/bin/tail -f /e…" 9 seconds ago Up 8 seconds gallant_hawking
20、容器的启动与关闭:
[root@99 ~]#docker stop f8e576fcb93b
f8e576fcb93b
[root@99 ~]#docker start f8e576fcb93b
f8e576fcb93b
21、进入到正在运行的容器:
nsenter 命令需要通过 PID 进入到容器内部,不过可以使用docker inspect 获取到容器的 PID:
[root@99 ~]#docker inspect -f "{{.State.Pid}}" nginx-test1
15159
[root@99 ~]#nsenter -t 15159 -m -u -i -n -p
root@7f9ece042db2:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
22、脚本方式:
将 nsenter 命令写入到脚本进行调用,如下:
[root@99 home]#vim docker-in.sh
#!/bin/bash
docker_in(){
NAME_ID=$1
PID=$(docker inspect -f "{{.State.Pid}}" ${NAME_ID})
nsenter -t ${PID} -m -u -i -n -p
}
docker_in $1
[root@99 home]#chmod a+x docker-in.sh
[root@99 home]#./docker-in.sh nginx-test1
root@7f9ece042db2:/# pwd
/
root@7f9ece042db2:/# exit
logout
23、查看容器内部的 hosts 文件:
[root@99 home]#nsenter -t 15159 -m -u -i -n -p
root@7f9ece042db2:/# 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-allrouters
172.17.0.3 7f9ece042db2 #默认会将实例的 ID 添加到自己的 hosts 文件
24、批量关闭正在运行的容器:
[root@99 ~]# docker stop $(docker ps -a -q)
f8e576fcb93b
c7eb5c22a0d2
3ce69f1ebd4b
d5e849aaa78b
7f9ece042db2
6210779e62d6
57053f0350f0
83d2c5e41730
d1e0d3d093f4
25、批量强制关闭正在运行的容器:[root@99 ~]#docker kill $(docker ps -a -q)
26、批量删除所有容器:[root@99 ~]# docker rm -f $(docker ps -a -q)
27、批量删除已退出容器:[root@99 ~]# docker rm -f docker ps -aq -f status=exited
28、批量强制关闭正在运行的容器:[root@99 ~]# docker kill $(docker ps -a -q)
DNS服务:
默认采用宿主机的dns地址:一是将 dns 地址配置在宿主机二是将参数配置在 docker 启动脚本里面 dns=1.1.1.1
[root@99 ~]# docker run -it --rm --dns 223.6.6.6 nginx bash
root@d7adf3567f69:/# cat /etc/resolv.conf
search openstacklocal
nameserver 223.6.6.6