Docker

2024-06-13

Docker

[TOC]

一、Docker是

1、简介

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux机器或Windows机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

物理机必须要内核3.8以上才能支持docker

2、特点

  • 服务彼此之间相互独立(服务之间的解耦)
  • 服务可以灵活迁移(Docker引擎 docker-ce)

耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。

解耦就是用数学方法将两种运动分离开来处理问题,常用解耦方法就是忽略或简化对所研究问题影响较小的一种运动,只分析主要的运动。(便于管理,防止数据过多的积累在一个文件中)

3、与虚拟机的区别

虚拟机容量占用大,容器不需要装系统,占用容量小

虚拟机安全,容器不安全(共享内核资源),攻击一个内核,其他全部瘫痪,可隔开,做资源控制

特性 虚拟机 容器
隔离级别 操作系统级 进程级
系统策略 Hypervisor CGroups
系统资源 5~15% 0~5%
启动时间 分钟级 秒级
镜像存储 GB-TB KB-MB
群集规模 上百 上万
高可用策略 备份、容灾、迁移 弹性、负载、动态

二、Docker三要素

●镜像:一个面向Docker容器引擎的只读模板

●容器:从镜像创建的运行实例

●仓库:集中保存镜像的地方;分公有和私有仓库

三、Docker基础命令

1、docker容器和本地互传文件:

本地向docker容器传送文件

docker cp 本机保存文件的全路径 container_id:docker容器内的文件全路径

1
docker cp index.jsp 容器id:/usr/local/tomcat/webapps/ROOT

docker容器向本机传送文件

docker cp container_id:docker容器内的文件全路径 本机保存文件的全路径

1
docker cp 4a2f08d2c1f8:/data1/configure.txt E:\PHP\configure.txt

2、镜像操作

●查看docker版本:docker version

●搜索nginx镜像(公有仓库):docker search nginx

●下载nginx镜像:docker pull nginx;下载后存放在/var/lib/docker

●查看镜像列表

docker images #查看下载镜像信息列表

docker inspect nginx:latest #获取镜像详细信息

●为镜像添加新标签

docker tag nginx:latest nginx:web

●两种方式删除镜像

注意:删除某一个镜像时,只要有容器在使用某一个镜像,必须先删除容器,才能删除镜像。

(1)删除镜像+标签名

在这里插入图片描述

(2)删除镜像id

注意:只有当镜像id对应标签仅剩一个时,才能使用镜像id的方式进行删除;否则出现如下报错

或者也可以在最后加上-f选项,一次性删除

在这里插入图片描述

●存出镜像并命名为nginx,存到/opt目录下

1
docker save -o /opt/nginx.tar nginx:latest

●载入镜像

docker load < /opt/nginx

3、容器操作

●创建容器

1
2
3
4
5
docker create -it nginx:latest /bin/bash

-i:让容器的标准输入保持打开

-t:让Docker分配一个伪终端

●查看容器运行状态

1
2
3
docker ps -a          -a:列出所有的容器,包括未运行的容器

Created:已创建; Up:运行中

●启动执行命令查看系统根目录

一般启动容器流程:

1
2
3
4
5
(1)docker pull centos     --下载镜像

(2)docker create -it centos:latest /bin/bash

(3)docker start d4a99affa677

通过run命令启动:(先去查找现有的镜像中有没有,没有先下载,再启动)

1
docker run centos:latest /usr/bin/bash -c ls /

执行完成会关闭,状态是Exited(容器可以做一次性的处理,处理完就释放资源,做到了最小成本控制)

容器持续在后台执行(通过执行死循环)

1
docker run -d centos:latest /bin/bash -c "while true;do echo hello;done"

使用 docker logs 容器id 命令,可以查看容器内的标准输出

●终止容器运行

1
docker stop 0401f589d5ed(CONTAINER ID)

●进入容器(该容器一定要在Up状态)

1
docker exec -it 0f0ba9207b21 /bin/bash

●导出容器

1
docker export cc4a8b1d428c > /opt/nginx_bak

●导入容器(会生成镜像,而不会创建容器)

1
cat /opt/nginx_bak | docker import - nginx:bak

●删除容器(容器必须为停止状态)

1
2
3
docker stop e885c37fb2eb

docker rm e885c37fb2eb

●批量删除容器

1
docker ps -a | awk '{print "docker rm "$1}' | bash

在这里插入图片描述

1
docker ps -a | sed -n '2,$p' | awk '{print "docker rm "$1}' | bash

四、Docker镜像的构建

1、Docker镜像的分层

自下而上制作镜像

1.from 后面跟基础镜像

2.add脚本

3.挂载共享空间 数据卷

4.CMD命令执行脚本

2、基于已有镜像容器创建

1
2
3
4
5
6
7
8
9
10
11
12
13
1、docker create -it 原镜像名 /bin/bash



2、docker commit -m "new" -a "chen" 已有容器id 新镜像名:标签

-m:说明信息

-a:作者信息

-p:生成过程中停止容器的运行

docker images | grep 标签

3、基于本地模板创建

1.导入本地镜像debian-7.0-x86-minimal.tar.gz

2.cat debian-7.0-x86-minimal.tar.gz | docker import - 镜像名:标签

3.docker images | grep 标签

4、基于Dockerfile创建

●Dockerfile是由一组指令组成的文件

●Dockerfile结构四部分

基础镜像信息

维护者信息

镜像操作指令

容器启动时执行指令

●Dockerfile每行支持一条指令,每条指令可携带多个参数,支持使用以“#”号开头的注释

●Dockerfile操作指令

指令 含义
FROM 镜像 指定新镜像所基于的镜像,第一条指令必须为FROM指令,每创建一个镜像就需要一条FROM指令。
MAINTAINER 名字 说明新镜像的维护人信息
RUN命令 在所基于的镜像上执行命令,并提交到新的镜像中
CMD [“要运行的程序”,”参数1”,”参数2”] 指令启动容器时要运行的命令或者脚本,Dockerfile只能有一条CMD命令,如果指定多条则只能最后一条被执行
EXPOSE 端口号 指定新镜像加载到Docker时要开启的端口(EXPOSE暴露的是容器内部端口,需要再映射到一个外部端口上)
ENV 环境变量 变量值 设置一个环境变量的值,会被后面的RUN使用
ADD 源文件/目录 目标文件/目录 将源文件复制到目标文件(与COPY的区别是将本地tar文件解压到镜像中)
COPY 源文件/目录 目标文件/目录 将本地主机上的文件/目录复制到目标地点,源文件/目录要与Dockerfile在相同的目录中
VOLUME [“目录”] 在容器中创建一个挂载点(VOLUME是宿主机中的某一个目录挂载到容器中)
USER 用户名/UID 指定运行容器时的用户
WORKDIR 路径 为后续的RUN、CMD、ENTRYPOINT指定工作目录(WORKDIR类似于cd,但是只切换目录一次,后续的RUN命令就可以写相对路径了)
ONBUILD 命令 指定所生成的镜像作为一个基础镜像时所要运行的命令
HEALTHCHECK 健康检查

CMD指令可以指定容器启动时默认执行的命令,但它可以被docker run命令的参数覆盖掉。

ENTRYPOINT 指令和CMD类似,它也是用户指定容器启动时要执行的命令,但如果dockerfile中也有CMD指令,CMD中的参数会被附加到ENTRYPOINT指令的后面。 如果这时docker run命令带了参数,这个参数会覆盖掉CMD指令的参数,并也会附加到ENTRYPOINT 指令的后面。

这样当容器启动后,会执行ENTRYPOINT 指令的参数部分。

可以看出,相对来说ENTRYPOINT指令优先级更高。

对于目录而言,COPY 和 ADD 命令具有相同的特点:只复制目录中的内容而不包含目录自身

CMD和ENTRYPOINT的区别

CMD指令可以指定容器启动时默认执行的命令,但它可以被docker run命令的参数覆盖掉。

ENTRYPOINT 指令和CMD类似,它也是用户指定容器启动时要执行的命令,但如果dockerfile中也有CMD指令,CMD中的参数会被附加到ENTRYPOINT指令的后面。 如果这时docker run命令带了参数,这个参数会覆盖掉CMD指令的参数,并也会附加到ENTRYPOINT 指令的后面。

这样当容器启动后,会执行ENTRYPOINT 指令的参数部分。

可以看出,相对来说ENTRYPOINT指令优先级更高。

优先级:ENTRYPOINT>CMD>docker run

Dockerfile文件生成apache镜像实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1.vim Dockerfile  (Dockerfile名字不可更改)
#新镜像基于的基础镜像(基础镜像未下载会先下载)
FROM centos:7
#维护镜像的用户信息
MAINTAINER This is chen
#镜像操作指令安装apache软件
RUN yum -y update
RUN yum -y install httpd
#开启80端口
EXPOSE 80
#复制网址首页文件
ADD index.html /var/www/html/index.html
#将执行脚本复制到镜像中
ADD run.sh /run.sh
RUN chmod 755 /run.sh
#启动容器时执行脚本
CMD ["/run.sh"]

此处注意一个细节:每加载一步会生成一个临时的容器,加载完后会删除

在这里插入图片描述

2.vim run.sh #和Dockerfile文件位于相同目录下

1
2
3
4
5
6
7
#!/bin/bash

rm -rf /run/httpd/* #删除进程文件

exec /usr/sbin/apachectl -D FOREGROUND #启动apache


3.vim index.html #编辑首页文件

this is web

4.生成镜像
1
docker build -t httpd:test .  (注意别忘了末尾有".")

5.新镜像运行容器

1
docker run -d -p 1216:80 httpd:test

-p:映射到宿主机指定端口

-P:映射到宿主机随机端口

6.测试容器是否成功运行

http://14.0.0.10:1126/

五、Docker的四种网络模式

https://blog.csdn.net/lilygg/article/details/88616218

1、实现原理

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。

2、网络详解

image-20210128140850997

1
2
3
4
5
6
7
8
9
[root@localhost ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

f9ad4320a5f2 bridge bridge local

894917639bf3 host host local

39da54945dad none null local

#安装docker时,它会自动创建三个网络,bridge(创建容器默认连接到该网络)、none和host

Docker网络模式 配置 说明
host模式 –net=host 容器和宿主机共享Network namespace。
container模式 –net=container:NAME_or_ID 容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。
none模式 –net=none 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。
bridge模式 –net=bridge (默认为该模式)

1)、host模式

容器将不会获得一个独立的Network Namespace(网络命令空间),而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口,(也就是说如果容器是个web,那直接访问宿主机:端口,不需要做NAT转换,跟在宿主机跑web一样。容器中除了网络,其他都还是隔离的。)

使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。

img

2)、Container模式

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信

img

3)、none模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。该模式关闭了容器的网络功能

这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

img

4)、bridge模式

此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及iptables nat表配置与宿主机通信

img

##当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。

bridge模式是docker的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。

3、自定义网络如何配置

#创建容器时默认使用的是桥接模式,但是使用bridge不支持为容器指定IP

1
2
3
4
5
[root@localhost ~]# docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:7 /bin/bash

20dc45293929f81013a60391bef2626f581a8d3d4f29b8a87ac8b1f9b585ab2a

docker: Error response from daemon: user specified IP address is supported on user defined networks only. #提示想要为容器指定IP只能在用户自定义的网络中才行

#配置自定义固定IP

1
2
3
4
5
[root@localhost ~]# docker network create --subnet=172.31.0.0/24 test   

#创建自定义网络test

[root@localhost ~]# docker run -itd --name web1 --net test --ip 172.31.0.10 centos:7 /bin/bash

​ #创建一个容器,指定网络为test,指定IP地址172.31.0.10

img

六、Docker数据管理

1、为什么要进行数据管理操作

●方便查看容器内产生的数据

●多容器间实现数据共享

例如:需要给多个容器中的网站站点上传网页内容时,可以高效的部署网页。

2、两种管理方式

●数据卷

数据卷是容器和宿主之间的数据共享

●数据卷容器

数据卷容器是容器和容器之间的数据共享

img

3、数据卷操作实例

1.将宿主机目录中的/var/www挂载到容器中的/data1中(如果目录不存在都会自动创建)

1
docker run -v /var/www:/data1 --name web1 -it centos:7 /bin/bash

2.在容器中/data1目录下创建文件进行测试

1
2
3
[root@bb58030283e7 /]# cd /data1/

[root@bb58030283e7 data1]# touch 123.txt

3.回到宿主机/var/www查看

1
2
3
4
5
[root@node1 ~]# cd /var/www/

[root@node1 www]# ls

123.txt

4、数据卷容器操作实例

1.创建数据卷容器web10

1
docker run --name web10 -v /data1 -v /data2 -it centos:7 /bin/bash

2.新容器web100挂载数据卷容器web10

1
2
3
docker run -it --volumes-from web10 --name web100 centos:7 /bin/bash

(web100容器会自动关联web10容器中的数据卷)

3.在新容器web100的/data1中创建文件进行测试

1
2
3
4
5
[root@2ad42960c2aa data1]# cd /data1/

[root@2ad42960c2aa data1]# ls

[root@2ad42960c2aa data1]# touch 1.txt

4.回到数据卷容器web10的/data1中查看

1
2
3
4
5
[root@b10f5d5ae9d5 /]# cd data1/

[root@b10f5d5ae9d5 data1]# ls

1.txt

5、私有仓库建立步骤

1、下载registry镜像

2、客户端设置daemon.json文件,指定私有仓库位置;

1
"insecure-registries": ["14.0.0.10:5000"],

3、生成registry容器,开放5000端口

1
docker run -d -p 5000:5000 -v /registry:/data/registry registry

4、给要上传的镜像打上标签

5、上传镜像

6、获取私有仓库列表查看是否上传成功

7、测试私有仓库下载镜像

#–privileged 让容器内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。

1
[root@localhost systemctl]# docker run --privileged -it -v /sys/fs/cgroup:/sys/fs/cgroup:ro 

七、Docker Compose容器编排

1、Docker Compose简介

●一个定义及运行多个Docker容器的工具

●Docker Compose非常适合组合使用多个容器进行开发的场景

3.2Docker Compose文件格式及编写注意事项

●YAML是一种标记语言很直观的数据序列化格式

●文件格式及编写注意事项

不支持制表符tab键缩进,需要使用空格缩进

通常开头缩进2个空格

字符后缩进1个空格,如冒号、逗号、横杆

用#号注释

如果包含特殊字符用单引号引起来

布尔值必须用引号括起来

2、Compose命令说明

●基本的使用格式

1
docker-compose [options] [COMMAND] [ARGS]

●docker-compose选项

1
2
3
4
5
6
7
--verbose 输出更多调试信息

--version 打印版本并退出

-f,--file FILE 使用特定的compose模板文件,默认为docker-compose.yml

-p,--project-name NAME 指定项目名称,默认使用目录名称

3、compose部署

#以docker-ce为基础

上传docker-compose命令包到/usr/local/bin目录下

1
chmod +x /usr/local/bin/docker-compose

#在/root目录下创建compose_tomcat目录

[root@localhost ~]# mkdir compose_tomcat/

目录结构如下:

img

docker-compose.yml配置文件详解:

https://www.jianshu.com/p/2217cfed29d7

一份标准配置文件应该包含 version、services、networks 三大部分,其中最关键的就是 services 和 networks 两个部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
[root@localhost compose_tomcat]# vim docker-compose.yml

version: '3'

services:

tomcat:

​ hostname: tomcat

​ build: #基于一份 Dockerfile创建容器

​ context: ./tomcat

​ dockerfile: Dockerfile

​ ports:

​ - 8080:8080

​ networks:

​ - tomcat

​ volumes:

​ - ./wwwroot:/usr/local/tomcat/webapps/ROOT #注意tomcat站点位置

nginx:

​ hostname: nginx

​ build:

​ context: ./nginx

​ dockerfile: Dockerfile

​ ports:

​ - 1216:80

​ - 1226:443

​ networks:

​ - nginx

​ volumes:

​ - ./nginxroot:/usr/local/nginx/html

networks:

tomcat:

nginx:

[root@localhost compose_tomcat]# docker-compose -f docker-compose.yml up -d

八、Harbor私有仓库

Harbor私有仓库部署与管理

Harbor的每个组件都是以Docker容器的形式构建的,使用docker-compose来对它进行部署

Docker harbor有可视化的web管理界面,可以方便管理Docker镜像,又提供了多个项目的镜像权限管理及控制功能

使用 Docker 命令在本地通过 127.0.0.1 来登录和推送镜像

默认情况下,Register 服务器在端口 80 上侦听。

//登录

1
docker login -u admin -p Harbor12345 http://127.0.0.1

//下载镜像进行测试 下载镜像进行测试

1
docker pull nginx

//镜像打标签 (网页上也会有提示、模板)

1
docker tag nginx 127.0.0.1/myimages/nginx:v1

//上传镜像到 上传镜像到 Harbor

1
docker push 127.0.0.1/myimages/nginx:v1

使用Harbor仓库时遇到的故障:

以上操作都是在 Harbor 服务器本地操作。如果其他客户端上传镜像到 Harbor,就会报

如下错误。

出现这问题的原因 Docker Registry 交互默认使用的是 HTTPS,但是搭建私有镜像默认使用的是 HTTP 服务,所以与私有镜像交互时出现以下错误。

1
2
3
4
5
[root@localhost ~]# docker login -u admin -p Harbor12345 http://14.0.0.20

WARNING! Using --password via the CLI is insecure. Use --password-stdin.

Error response from daemon: Get https://14.0.0.20/v2/: dial tcp 14.0.0.20:443: connect: connection refused

如何解决:

1
2
3
4
5
6
7
[root@client ~]# vim /usr/lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry 14.0.0.20 -- containerd=/run/containerd/containerd.sock

[root@client ~]# systemctl daemon-reload

[root@client ~]# systemctl restart docker

要更改 Harbor 的配置文件时,请先停止现有的 Harbor 实例并更新 Harbor.cfg;然后运行 prepare 脚本来填充配置;最后重新创建并启动 Harbor 的实例。

1.停止现有的 Harbor 实例

1
2
3
4
5
6
7
8
9
10
11
12
13
docker-compose down -v

[root@localhost harbor]# pwd

/usr/local/harbor

[root@localhost harbor]# ls

common docker-compose.yml harbor.v1.2.2.tar.gz NOTICE

docker-compose.clair.yml harbor_1_1_0_template install.sh prepare

docker-compose.notary.yml harbor.cfg LICENSE upgrade

2.更新 Harbor.cfg

1
[root@localhost harbor]# vim Harbor.cfg

3.运行 prepare 脚本来填充配置

1
[root@localhost harbor]# ./prepare

4.重新创建并启动 Harbor 的实例

如果出现如下报错: docker-compose up -d

九、Docker consul容器服务更新与发现

1、consul的介绍

由HashiCorp公司使用go语言开发的一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件(开源)。

主要特点:

服务发现及配置;

支持健康检查,并且运行HTTP、GTPC和DNS协议调用API存储键值对;

采用Raft算法,保证服务的高可用

支持安全服务通信;

支持多数据中心;

2、consul agent

consul通过agent来运行的,agent分为server 和client两种类型,这两种类型基本上没有什么区别,server agent是将服务的消息存储,一般来说为了防止单点故障推荐使用3到5个来构建集群架构。

而client agent主要用于注销服务、健康检查及转发server agent的查询等,相当于一个代理,因此它必须要在集群的每台主机上运行。

一种服务或软件工具的产生必然有其使用场景和其优势,否则哪有其立足之地?

3、consul使用的场景

  • Docker 容器的注册与配置共享
  • Coreos 实例的注册与配置共享
  • SaaS 应用的配置共享、服务发现和健康检查。
  • vitess 集群
  • 与 confd 服务集成,动态生成 nginx 和 haproxy 配置文件

4、Docker Consul容器服务更新与发现原理

基于consul的docker容器服务发现及自动更新(原理+部署)

1
2
3
4
1. Consul Cluster由部署和运行了Consul Agent的节点组成。 在Cluster中有两种角色:Server和 Client。
2. Server和Client的角色和Consul Cluster上运行的应用服务无关, 是基于Consul层面的一种角色划分.
3. Consul Server: 用于维护Consul Cluster的状态信息, 实现数据一致性, 响应RPC请求。官方建议是: 至少要运行3个或者3个以上的Consul Server。 多个server之中需要选举一个leader, 这个选举过程Consul基于Raft协议实现. 多个Server节点上的Consul数据信息保持强一致性。 在局域网内与本地客户端通讯,通过广域网与其他数据中心通讯。Consul Client: 只维护自身的状态, 并将HTTP和DNS接口请求转发给服务端。
4. Consul 支持多数据中心, 多个数据中心要求每个数据中心都要安装一组Consul cluster,多个数据中心间基于gossip protocol协议来通讯, 使用Raft算法实现一致性

5、工作流程:

当后面容器增加时,registrator注册容器中的服务—》通知consul server更新—》consul template模板进行更新,自动修改nginx.conf中的upstream参数

Registrator监控新建的Docker容器,并且检查判定这些容器提供的服务。从我们的目的出发,任何监听在某个端口的程序都是服务。Registrator在容器内发现的任务服务,都将被添加到一个服务注册端,比如Consul或etcd

img

准备template nginx模板文件,参数以变量形式写入

在consul服务器节点上操作

1
2
3
4
5
6
7
8
9
10
11
[root@localhost consul]# vim /root/consul/nginx.ctmpl

upstream http-server {

{{range service "nginx"}}

server {{.Address}}:{{.Port}};

{{end}}

}

consul-template是一个守护进程,用于实时查询consul集群信息,并更新文件系统上任意数量的指定模板,生成配置文件。更新完成后,可以选择运行shell命令执行更新操作,重新加载nginx。这种强大的抽象功能和查询语言模板可以使consul-template特别适合动态的创建配置文件。例如:创建nginx反向代理。

十、资源分配

1、为什么要做资源分配?

容器和虚拟机的区别:

虚拟机不需要做,因为虚拟机在创建的时候已经做了资源分配(配额),(虚拟CPU,虚拟内存,虚拟磁盘等)

而容器共享内核资源,所以需要做Cgroup,可以按照往年监控的数据,查看cpu等资源的耗用情况来进行分配

2、Cgroup资源配置方法

Docker是通过Cgroup来控制容器使用的资源配额,包括CPU、内存、磁盘i/o三大方面,基本覆盖了常见的资源配额和使用量控制。

Cgroup是Control Groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组所使用的物理资源(如CPU、内存、磁盘IO等)的机制,被docker等很多项目用于实现进程资源控制。Cgroup本身是提供将进程进行分组化管理的功能和接口的基础结构,I/O或内存的分配控制等具体的资源管理功能。这些具体的资源管理功能称为Cgroup子系统,有以下几大子系统实现:

blkio:设置限制每个块设备的输入输出控制。例如:磁盘,usb等

CPU:使用调度程序为cgroup任务提供CPU的访问。

cpuacct:产生cgroup任务的CPU资源报告。

cpuset:如果是多核心的cpu,这个子系统会为cgroup任务分配单独的CPU和内存。

devices:允许或拒绝cgroup任务对设备的访问。

freezer:暂停和恢复cgroup任务。

memory:设置每个cgroup的内存限制以及产生内存资源报告。

net_cls:标记每个网络包以供cgroup方便使用。

ns:命名空间子系统。

perf_event:增加了对每个group的监测跟踪的能力,可以监测属于某个特定的group的所有线程以及运行在特定CPU上的线程。

3、使用stress工具测试CPU和内存

#使用Dockerfile来创建一个基于Centos的stress工具镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@localhost ~]# mkdir stress

[root@localhost ~]# vim stress/Dockerfile

[root@localhost ~]# cd stress/

[root@localhost stress]# vim Dockerfile

FROM centos:7

MAINTAINER chen

RUN yum -y install wget

RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

RUN yum -y install stress

[root@localhost stress]# docker build -t centos:stress .

#使用如下命令创建容器,命令中的–cpu-shares参数值不能保证可以获得1个vcpu或者多少GHz的CPU资源,它仅是一个弹性的加权值。

1
[root@localhost ~]# docker run -itd --cpu-shares 100 centos:stress

说明:默认情况下,每个Docker容器的CPU份额都是1024。单独一个容器的份额是没有意义的。只有在同时运行容器时,容器的cpu加权的效果才能显现。

例如:两个容器A、B的cpu份额分别为1000和500,在cpu进行实际片分配的时候,容器A比容器B多一倍的机会获得cpu的时间片。但分配的结果取决于当时主机和其他容器的运行状态,实际上也无法保证容器A一定能获得cpu时间片。比如容器A的进程一直是空闲的,那么容器B是可以获取比容器A更多的cpu时间片的。极端情况下,例如主机上只运行了一个容器,即使它的cpu份额只有50,它也可以独占整个主机的cpu。

例如:cpu时间片:1秒

​ 容器A:50% 0.5秒

​ 容器B:25% 0.25秒

​ 容器C:25% 0.25秒

平均值层面:CPU给A容器充0.5秒,给B容器充0.25秒

#可以通过cpu share可以设置容器使用cpu的优先级,比如启动了两个容器及运行查看cpu使用百分比。

1
[root@localhost stress]# docker run -itd --name cpu1024 --cpu-shares 1024 centos:stress stress -c 10

​ #stress -c 10:容器产生10个子函数进程

1
2
3
[root@localhost stress]# docker exec -it dd0e42e372ff /bin/bash

[root@dd0e42e372ff /]# top

img

1
2
3
4
5
[root@localhost ~]# docker run -itd --name cpu512 --cpu-shares 512 centos:stress stress -c 10

[root@localhost ~]# docker exec -it ddfccf1cac40 /bin/bash

[root@ddfccf1cac40 /]# top

img

#可以发现两个容器cpu使用率是2:1

4、CPU周期限制

Docker提供了–cpu-period、–cpu-quota两个参数控制容器可以分配到的CPU时钟周期。

–cpu-period是用来指定容器对CPU的使用要在多长时间内做一次重新分配。

–cpu-quota是用来指定在这个周期内,最多可以有多少时间来跑这个容器。

与–cpu-shares不同的是,这种配置是指定一个绝对值,容器对CPU资源的使用绝对不会超过配置的值。

cpu-period和cpu-quota的单位为微秒(μs)。cpu-period的最小值为1000微秒,最大值为1秒,默认值为0.1秒(100000μs)

cpu-quota的值默认为-1,表示不做控制。cpu-period和cpu-quota参数一般联合使用。

例如:容器进程需要每1秒使用单个cpu的0.2秒时间,可以将cpu-period设置为1000000即1秒,cpu-quota设置为200000(0.2秒)。

在多核情况下,如果允许容器进程完全占用两个cpu,则可以将cpu-period设置为100000即0.1秒,cpu-quota设置为200000即0.2秒

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[root@localhost ~]# docker run -itd --cpu-period 100000 --cpu-quota 200000 centos:stress

[root@localhost ~]# docker exec -it 16b6689aabc6 /bin/bash

[root@16b6689aabc6 /]# cd /sys/fs/cgroup/

[root@16b6689aabc6 cgroup]# ls

blkio cpuacct freezer net_cls perf_event

cpu cpuset hugetlb net_cls,net_prio pids

cpu,cpuacct devices memory net_prio systemd

[root@16b6689aabc6 cgroup]# cd cpu

[root@16b6689aabc6 cpu]# ls

cgroup.clone_children cpu.rt_period_us cpuacct.usage

cgroup.event_control cpu.rt_runtime_us cpuacct.usage_percpu

cgroup.procs cpu.shares notify_on_release

cpu.cfs_period_us cpu.stat tasks

cpu.cfs_quota_us cpuacct.stat

[root@16b6689aabc6 cpu]# cat cpu.cfs_period_us

100000

[root@16b6689aabc6 cpu]# cat cpu.cfs_quota_us

200000

5、CPU Core控制

对多核CPU的服务器,Docker还可以控制容器运行使用哪些CPU内核,即使用–cpuset-cpus参数。这对具有多CPU的服务器尤其有用,可以对需要高性能计算的容器进行性能最优的配置。

1
[root@localhost ~]# docker run -itd --name cpu1 --cpuset-cpus 1-2 centos:stress

#执行以上命令表示创建的容器只能用1、2两个cpu。最终生成的cgroup的cpu内核配置如下:

1
2
3
4
5
6
7
8
9
10
11
[root@localhost ~]# docker exec -it 75be98d74dcc /bin/bash

top - 07:34:23 up 45 min, 0 users, load average: 0.00, 0.01, 0.04

[root@75be98d74dcc /]# cat /sys/fs/cgroup/cpuset/cpuset.cpus #cpuset:cpu集合

1-2

[root@75be98d74dcc /]# stress -c 5 & #让容器产生5个子函数进程,并在后台运行

[root@75be98d74dcc /]# top #使用top命令查看cpu工作情况(top进去后按1,显示每个cpu的工作情况)

img

#通过下面指令可以看到容器中进程与cpu内核的绑定关系

1
2
3
[root@localhost ~]# docker exec 75be98d74dcc taskset -c -p 1  #-p 1 表示容器中第一个进程pid为1被绑定到cpu1和2上

pid 1's current affinity list: 1,2

6、CPU配额控制参数的混合使用

通过cpuset-cpus参数指定容器A使用cpu内核0,容器B只是用CPU内核1.

在主机上只有这两个容器使用对应cpu内核的情况,它们各自占用全部的内核资源,cpu-shares没有明显效果。

cpuset-cpus、cpuset-mems参数只在多核、多内存节点上的服务器上有效,并且必须与实际的物理配置匹配,否则也无法达到资源控制的目的。

在系统具有多个cpu内核的情况下,需要通过cpuset-cpus参数为容器设置cpu内核才能方便的进行测试。

#创建容器cpu3,仅使用cpu0核心,加权值为512

1
2
3
[root@localhost ~]# docker run -itd --name cpu3 --cpuset-cpus 0 --cpu-shares 512 centos:stress stress -c 1

[root@localhost ~]# docker exec -it 4eb80db7a397 bash

img

#创建容器cpu4,仅使用cpu0核心,加权值为1024

1
2
3
[root@localhost ~]# docker run -itd --name cpu4 --cpuset-cpus 0 --cpu-shares 1024 centos:stress  stress -c 1

[root@localhost ~]# docker exec -it 327038e98aa4 bash

img

7、内存限额

与操作系统类似,容器可使用的内存包括两部分:物理内存和Swap

Docker通过下面两组参数来控制容器内存的使用量。

-m或–memory:设置内存的使用限额,例如100M、1024M

–memory-swap:设置内存+swap的使用限额

执行如下命令允许该容器最多使用200M的内存和300M的swap

[root@localhost ~]# docker run -it -m 200M –memory-swap=300M progrium/stress –vm 1 –vm-bytes 280M

–vm 1:启动1个内存工作线程

–vm-bytes 280M:每个线程分配280M内存

默认情况下,容器可以使用主机上的所有空闲内存。

与cpu的cgroups配置类似,Docker会自动为容器在目录/sys/fs/cgroup/memory/docker/<容器的完整长id>中创建相应cgroup配置文件

注意:如果让工作线程分配的内存超过300M,分配的内存超过限额,stress线程报错,容器退出。

[root@localhost ~]# docker run -it -m 200M –memory-swap=300M progrium/stress –vm 1 –vm-bytes 310M

8、bps和iops的限制

bps是byte per second,每秒读写的数据量。

iops是io per second,每秒io的次数。

可通过以下参数控制容器的bps和iops:

–device-read-bps,限制读某个设备的bps。

–device-write-bps,限制写某个设备的bps。

–device-read-iops,限制读某个设备的iops。

–device-write-iops,限制写某个设备的iops。

示例:限制容器写/dev/sda的速率为5MB/s。

1
2
3
4
5
6
7
8
9
[root@localhost ~]# docker run -it --device-write-bps /dev/sda:5MB centos:stress

[root@7675c030fd53 /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct

^C22+0 records in

22+0 records out

23068672 bytes (23 MB) copied, 4.40131 s, 5.2 MB/s

#通过dd命令测试在容器中写磁盘的速度是否为5MB/s。因为容器的文件系统是在主机/dev/sda上的,在容器中写文件相当于对主机/dev/sda进行写操作。另外,oflag=direct指定用direct IO方式写文件,这样 –device-write-bps才能生效。

结果表明限速5MB/s左右。作为对比测试,如果不限速,结果如下:

1
2
3
4
5
6
7
8
9
[root@server ~]# docker run -it centos:stress

[root@07b87cdda205 /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct

1024+0 records in

1024+0 records out

1073741824 bytes (1.1 GB) copied, 1.01479 s, 1.1 GB/s

十一、Docker-TLS加密通讯

1、使用TLS加密通讯原因

为了防止链路劫持、会话劫持等问题导致Docker通信时被中间人攻击,c/s两端应该通过加密方式通讯。

2、基础知识

1.对称密钥,例如DES、3DES、AES,长度不同,长度越长安全越高,解密速度越慢。

2.非对称密钥,分为公钥和私钥,例如RSA 公钥:所有人可知(锁),私钥(钥匙)个人身份信息,不可抵赖。

3.封装在证书中:个人信息,密钥,有效期

4.ca:证书颁发机构 ca证书

密钥key–》身份签名(csr)–》服务器/客户端(结合)制作证书pem

证书pem发送给客户端,客户端通过证书验证才能访问容器

3、TLS加密通讯部署过程:

1.修改服务器主机名为server,并添加到本地解析文件

1
2
3
4
5
6
7
[root@localhost ~]# hostnamectl set-hostname server

[root@localhost ~]# su

[root@server ~]# vim /etc/hosts

127.0.0.1 server

2.创建ca密钥(ca-key.pem)

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@server ~]# openssl genrsa -aes256 -out ca-key.pem 4096  #256为密钥长度;4096为字节数

Generating RSA private key, 4096 bit long modulus

.......++

...............++

e is 65537 (0x10001)

Enter pass phrase for ca-key.pem: #输入密码123123(自定义)

Verifying - Enter pass phrase for ca-key.pem: #确认密码123123

3.创建ca根证书文件(ca.pem)

1
2
3
[root@server ~]# openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -subj "/CN=*" -out ca.pem    #req:签名;x509:国际标准;sha256:指定哈希256位加密算法;subj:项目名称

Enter pass phrase for ca-key.pem: #输入123123

-——————————————————————————————————————————-

4.创建服务器私钥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@server ~]# openssl genrsa -out server-key.pem 4096   #genrsa:非对称密钥

Generating RSA private key, 4096 bit long modulus

.....................................................................................++

..............................................................++

e is 65537 (0x10001)


[root@server ~]# ls

anaconda-ks.cfg ca.pem server-key.pem 公共 视频 文档 音乐

ca-key.pem initial-setup-ks.cfg stress 模板 图片 下载 桌面

5.签名私钥

1
[root@server ~]# openssl req -subj "/CN=*" -sha256 -new -key server-key.pem -out server.csr

6.使用ca证书与私钥证书签名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@server ~]# openssl x509 -req -days 1000 -sha256 -in server.csr -CA ca.pem  -CAkey ca-key.pem -CAcreateserial -out server-cert.pem

Signature ok

subject=/CN=*

Getting CA Private Key

Enter pass phrase for ca-key.pem: #输入123123

[root@server ~]# ls

anaconda-ks.cfg ca.srl server.csr 公共 图片 音乐

ca-key.pem initial-setup-ks.cfg server-key.pem 模板 文档 桌面

ca.pem server-cert.pem stress 视频 下载

-—————————————————————————————————————————

7.生成客户端密钥

1
2
3
4
5
6
7
8
9
[root@server ~]# openssl genrsa -out key.pem 4096

Generating RSA private key, 4096 bit long modulus

....................................++

.......................................................................++

e is 65537 (0x10001)

8.签名客户端

1
2
3
[root@server ~]# openssl req -subj "/CN=client" -new -key key.pem -out client.csr


9.创建配置文件

1
2
3
[root@server ~]# echo extendedKeyUsage=clientAuth > extfile.cnf


10.签名证书,输入123123,需要(签名客户端,ca证书,ca密钥)

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@server ~]# openssl x509 -req -days 1000 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf

Signature ok

subject=/CN=client

Getting CA Private Key

Enter pass phrase for ca-key.pem:

\---------------------------------------------------------------------------------------------------------------------------------


11.删除多余文件

1
[root@server ~]# rm -rf ca.srl client.csr extfile.cnf server.csr

12.修改docker服务文件文件

1
[root@server ~]# vim /lib/systemd/system/docker.service

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@server ~]# mkdir /tls

[root@server ~]# mv ca.pem /tls

[root@server ~]# mv server-cert.pem /tls

[root@server ~]# mv server-key.pem /tls/

[root@server ~]# mv cert.pem /tls/

[root@server ~]# mv key.pem /tls/

[root@server ~]# ls /tls/

ca.pem cert.pem key.pem server-cert.pem server-key.pem

13.重载进程,重启docker服务

1
2
3
[root@server ~]# systemctl daemon-reload

[root@server ~]# systemctl restart docker

14.将/tls目录下的ca.pem、cert.pem、key.pem三个文件复制给客户端

1
2
3
4
5
[root@server tls]# scp ca.pem root@14.0.0.30:/etc/docker/

[root@server tls]# scp cert.pem root@14.0.0.30:/etc/docker/

[root@server tls]# scp key.pem root@14.0.0.30:/etc/docker/

-———————————————————————————————————————————-

15.到客户端14.0.0.30进行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost docker]# vim /etc/hosts

加入:14.0.0.20 server

[root@localhost ~]# cd /etc/docker/ #注意要切换到服务端传证书文件的目录下

[root@localhost docker]# docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H tcp://server:2376 ps -a #测试成功,成功访问服务端容器

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

327038e98aa4 centos:stress "stress -c 1" About an hour ago Exited (137) About an hour ago cpu4

4eb80db7a397 centos:stress "stress -c 1" About an hour ago Exited (137) About an hour ago cpu3

十二、故障集

1、centos下执行命令service network restart时,抛出主进程被占据的错

原因:从镜像创建容器时,通过以下命令创建

   docker run -itd –name centos-test centos /bin/bash

   这时,进程(PID:1)会被/bin/bash占据。

对策:通过以下命令创建容器

   docker run -itd –name centos-test –privileged=true centos /usr/sbin/init

2、Goland使用Docker插件,连接Docker失败

原因:没有开启Docker的远程访问

对策:如下图,Expose daemon on tcp://localhost:2375 without TLS处打勾

img

3、将要部署的项目创建容器时无法访问数据库

原因:docker是一个虚拟容器,其localhost与主机的localhost是不同的,不能互相访问。

对策:工程总配置文件的数据源要填写真实的IP地址。如果是开发环境的话,推荐使用【host.docker.internal】。这个DNS名称将被解析到主机的IP地址,省去了不断更换IP的麻烦。

十三、面试题

1、什么Docker?

答:Docker是一个容器化平台,它以容器的形式将您的应用程序及其所有依赖项打包在一起,以确保您的应用程序在任何环境中无缝运行。

2、Docker与虚拟机的不同点在哪里?

答:Docker不是虚拟化方法。它依赖于实际实现基于容器的虚拟化或操作系统级虚拟化的其他工具。为此,Docker最初使用LXC驱动程序,然后移动到libcontainer现在重命名为runc。Docker主要专注于在应用程序容器内自动部署应用程序。应用程序容器旨在打包和运行单个服务,而系统容器则设计为运行多个进程,如虚拟机。因此,Docker被视为容器化系统上的容器管理或应用程序部署工具。

3、Docker容器有几种状态?

答:有四种状态:运行、已暂停、重新启动、已退出。

4、Dockerfile中最常见的指令是什么?

答:FROM:指定基础镜像;LABEL:功能是为镜像指定标签;RUN:运行指定的命令;CMD:容器启动时要运行的命令。

5、Dockerfile中的命令COPY和ADD命令有什么区别?

答:一般而言,虽然ADD并且COPY在功能上类似,但是首选COPY。

那是因为它比ADD更易懂。COPY仅支持将本地文件复制到容器中,而ADD具有一些功能(如仅限本地的tar提取和远程URL支持),这些功能并不是很明显。因此,ADD的最佳用途是将本地tar文件自动提取到镜像中,如ADD rootfs.tar.xz /。

6、什么是Docker镜像?

答:Docker镜像是Docker容器的源代码。换句话说,Docker镜像用于创建容器。使用build命令创建镜像,并且在使用run启动时它们将生成容器。镜像存储在Docker注册表中,registry.hub.docker.com因为它们可能变得非常大,镜像被设计为由其他镜像层组成,允许在通过网络传输镜像时发送最少量的数据。

7、解释基本的Docker使用工作流程是怎样的?

答:(1)从Dockerfile开始,Dockerfile是镜像的源代码;(2)创建Dockerfile后,可以构建它以创建容器的镜像。图像只是“源代码”的“编译版本”,即Dockerfile;(3)获得容器的镜像后,应使用注册表重新分发容器。注册表就像一个git存储库,可以推送和拉取镜像;接下来,可以使用该图像来运行容器。在许多方面,正在运行的容器与虚拟机(但没有虚拟机管理程序)非常相似。

8、如何在生产中监控Docker?

答:Docker提供docker stats和docker事件等工具来监控生产中的Docker。我们可以使用这些命令获取重要统计数据的报告。

Docker统计数据:当我们使用容器ID调用docker stats时,我们获得容器的CPU,内存使用情况等。它类似于Linux中的top命令。

Docker事件:Docker事件是一个命令,用于查看Docker守护程序中正在进行的活动流。一些常见的Docker事件是:attach,commit,die,detach,rename,destroy等。

9、Docker如何在非Linux系统中运行容器?

答:通过添加到Linux内核版本2.6.24的名称空间功能,可以实现容器的概念。容器将其ID添加到每个进程,并向每个系统调用添加新的访问控制检查。它由clone()系统调用访问,该调用允许创建先前全局命名空间的单独实例。

10、什么类型的应用程序无状态或有状态更适合Docker容器?

答:最好为Docker Container创建无状态应用程序。我们可以从应用程序中创建一个容器,并从应用程序中取出可配置的状态参数。现在我们可以在生产环境和具有不同参数的QA环境中运行相同的容器。这有助于在不同场景中重用相同的镜像。另外,无状态应用程序比有状态应用程序更容易使用Docker容器进行扩展。

11、你常用的docker命令有哪些?

拉取镜像:docker pull IMAGE(镜像名)

例如:docker pull nginx

部署启动容器:docker run –name NAME(容器名) -p PORTS(要使用的端口) IMAGE(镜像名)

查看容器的运行状态:docker ps -a (该命令可以查看容器是否运行,及已创建的容器名称)

进入运行中的容器: docker exec -it CONTAINER_ID/NAME(容器id或者是容器名) bash

eg:docker exec -it sc_nginx2 /bin/bash

-i :交互式进入容器

-t : 开启一个终端

sc_nginx : 是容器名

/bin/bash : 进入容器的程序

查看docker里有哪些镜像:docker images

删除/启动/停止 容器 :docker rm/start/stop CONTAINER_ID/NAME

启动docker服务:systemctl start docker

设置开机启动:systemctl enable docker

12、Dockerfile是什么?Dockerfile里有哪些内容?

Dockerfile 是用来构建自定义镜像的文本文档

Dockerfile 里包含的信息主要有:

基础镜像

镜像元信息

镜像操作指令

容器启动时执行的命令

-———————————————————-

具体指令:

1 FROM IMAGE(镜像名):version (版本) 基础镜像

eg: FROM mysql:5.6

eg: FORM python (不指定版本,默认最新版本)

2 ENV 用来设置环境变量

eg:ENV NAME World

3 WORKDIR:用来指定工作目录

eg: WORKDIR /app

4 ADD 用于将本地文件添加到镜像中

eg: ADD ./app

5 CMD 构建容器后执行的命令,即在容器启动时执行的命令

eg: CMD [“python”,”app.py”]

6 EXPOSE 指定与外界进行交互的端口

eg: EXPOSE 80

7 VOLUME 定义匿名卷 用于创建挂载点

我们可以利用VOLUME 将源代码、数据或其他内容添加到镜像中,而又不需要提交到镜像中,并且可以使多个容器共享这些内容

eg: VOLUME [“/data_flask”]

8 RUN 构建镜像时执行的命令

eg:RUN pip install -i https://pypi.douban.com/simple/ -r requirements.txt

13、退出容器后,通过docker ps 命令查看不到,数据会丢失吗?

​ 可以用 docker ps -a 来查看

​ 如果仅仅是退出容器的话,数据是不会丢失的,重启容器后,数据依然在

​ 如果删除容器的话,但数据做了持久化存储,也不会丢。

​ 容器删除,那数据也会一起被删除

14、docker 的优点

资源隔离:比如限制应用最大内存使用量,或者资源加载隔离等。

低消耗:虚拟化本身带来的损耗需要尽量的低。

Docker 很好的权衡了两者,即拥有不错的资源隔离能力,又有很低的虚拟化开销。

15、docker的应用场景

1、可以简化配置

不同的软件可能需要不同的运行环境,docker可以将运行环境和配置放在代码中,然后部署,同一个docker可以在不同的环境中使用

2、简化代码流水线(Code Pipeline)

代码从开发者的机器到最终在生产环境上的部署,需要经过很多的中间环境。而每一个中间环境都有自己微小的差别,Docker给应用提供了一个从开发到上线均一致的环境,让代码的流水线变得简单不少。

3、提高开发效率

这就带来了一些额外的好处:Docker能提升开发者的开发效率,不同的开发环境中,我们都想把两件事做好。一是我们想让开发环境尽量贴近生产环境,二是我们想快速搭建开发环境。理想状态中,要达到第一个目标,我们需要将每一个服务都跑在独立的虚拟机中以便监控生产环境中服务的运行状态。然而,我们却不想每次都需要网络连接,每次重新编译的时候远程连接上去特别麻烦。这就是Docker做的特别好的地方,开发环境的机器通常内存比较小,使用虚拟机的时候,我们经常需要为开发环境的机器加内存,而Docker可以轻易的让几十个服务在Docker中跑起来。

4、隔离应用

有很多种原因会让你选择在一个机器上运行不同的应用,比如之前提到的提高开发效率的场景等。

5、整合服务器

正如通过虚拟机来整合多个应用,Docker隔离应用的能力使得Docker可以整合多个服务器以降低成本。由于没有多个操作系统的内存占用,以及能在多个实例之间共享没有使用的内存,Docker可以比虚拟机提供更好的服务器整合解决方案。

6、调试能力

Docker提供了很多的工具,这些工具不一定只是针对容器,但是却适用于容器。它们提供了很多的功能,包括可以为容器设置检查点、设置版本和查看两个容器之间的差别,这些特性可以帮助调试Bug。

7、 快速部署

在虚拟机之前,引入新的硬件资源需要消耗几天的时间。Docker的虚拟化技术将这个时间降到了几分钟,Docker只是创建一个容器进程而无需启动操作系统,这个过程只需要秒级的时间。这正是Google和Facebook都看重的特性。你可以在数据中心创建销毁资源而无需担心重新启动带来的开销。通常数据中心的资源利用率只有30%,通过使用Docker并进行有效的资源分配可以提高资源的利用率。

16、容器的网络类型有哪些?

bridge :默认

host:容器和宿主机共享ip地址,端口号要区别开

none:只有lo接口,没有其他的接口

container:很多容器共享一个ip地址

17、compose 是什么?

容器编排工具

例如:我们现在需要启动10个容器,其中3个nginx,2个redis,3个mysql,1个zabbix,1个ansible,有些容器需求先启动,有容器需要后启动,在启动的时候是有先后顺序的。

这时候需要批量启动容器,而且启动的时候容器之间是有依赖关系,需要考虑启动顺序的

我们可以将编排的内容全部写到一个yaml文件里,docker 的compose根据这个yaml文件里的安排去启动容器。

18、解释基本的Docker使用工作流程

一切都从Dockerfile开始。Dockerfile是镜像的源代码。

创建Dockerfile后,您可以构建它以创建容器的镜像。图像只是“源代码”的“编译版本”,即Dockerfile。

获得容器的镜像后,应使用注册表重新分发容器。注册表就像一个git存储库 - 你可以推送和拉取图像。

接下来,您可以使用该图像来运行容器。在许多方面,正在运行的容器与虚拟机(但没有虚拟机管理程序)非常相似。

19、Docker Image和Layer有什么区别?

Image:Docker镜像是由一系列只读层构建的

Layer:每个层代表Dockerfile中的指令。

下面的Dockerfile包含四个命令,每个命令都创建一个层。

FROM ubuntu:15.04

COPY . /app

RUN make /app

CMD python /app/app.py

每个层只是与之前层的一组差异。

20、您将如何监控生产中的Docker?

Docker提供docker stats和docker events等工具来监控生产中的Docker。我们可以使用这些命令获取重要统计数据的报告。

Docker stats:当我们使用容器ID调用docker stats时,我们获得容器的CPU,内存使用情况等。它类似于Linux中的top命令。

Docker events:Docker events是一个命令,用于查看Docker守护程序中正在进行的任务。

一些常见的Docker事件是:attach,commit,die,detach,rename,destroy等。我们还可以使用各种选项来限制或过滤我们感兴趣的事件。

21、什么是Docker Swarm?

Docker Swarm是Docker的群集管理工具。它将Docker主机池转变为一个虚拟Docker主机。Docker Swarm提供标准的Docker API,任何已经与Docker守护进程通信的工具都可以使用Swarm扩展到多个主机。

22、docker的核心是什么

镜像(Image)

容器(Container)

仓库(Repository)

镜像:类似虚拟机镜像

容器:类似linux系统环境,运行和隔离应用。容器从镜像启动的时候,docker会在镜像的最上一层创建一个可写层,镜像本身是只读的,保持不变。

仓库:每个仓库存放某一类镜像。 |

23、docker的持久化,网络,发布

docker的持久化:在生成容器的同时,加上-v选项,指定把当前服务器的目录映射到容器中

docker的网络:

创建网络:docker network create –subnet=10.10.10.0/24 docker1,其实就是创建一个虚拟交换机、一个虚拟局域网,只有属于同一个虚拟局域网的容器之间才能够相互通讯

发布docker:我们可以使用-p参数把容器端口和宿主机端口绑定

​ -p 宿主机端口:容器端口 #宿主端口可以是任意的端口,只要访问的时候加上端口号,即可访问到相应的容易的端口的服务

24、怎么做一个拥有指定功能的镜像

方法一:生产一个新的容器==>进入模板镜像容器=>操作(制作成自己想要的环境)=>退出容器=>利用容器产生新的镜像

方法二:写Dockerfile文件,把需要对容器的操作写到文件中,通过执行脚本文件来产生新的镜像

25、说下对docker run和docker start的理解?

docker run 只在第一次运行时使用,将镜像放到容器中,以后再次启动这个容器时,只需要使用命令docker start 即可。

docker run相当于执行了两步操作:将镜像放入容器中(docker create),然后将容器启动,使之变成运行时容器(docker start)。

docker start的作用是,重新启动已存在的镜像。也就是说,如果使用这个命令,我们必须事先知道这个容器的ID,或者这个容器的名字,我们可以使用docker ps找到这个容器的信息。

26、docker stop和docker kill的的理解?

kill是不管容器同不同意,我直接执行kill -9,强行终止;stop的话,首先给容器发送一个TERM信号,让容器做一些退出前必须的保护性、安全性操作,然后让容器自动停止运行,如果在一段时间内,容器还是没有停止,再进行kill -9,强行终止。