Docker

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

使用场景

容器与虚拟机

2020822151647

虚拟机最大的缺点就是依赖其专用的操作系统

Docker架构

安装

wget https://get.docker.com

引擎

Docker引擎由如下主要的组件构成:Docker客户端(Docker Client)、Docker守护进程(Docker daemon)、containerd以及runc。它们共同负责容器的创建和运行

2020822154342

LXC提供了对诸如命名空间(Namespace)和控制组(CGroup)等基础工具的操作能力,它们是基于Linux内核的容器虚拟化技术

2020822154039

Docker公司开发了名为Libcontainer的自研工具,用于替代LXC

runc:

containerd:

启动容器的过程:

2020822154716

容器运行时与Docker daemon是解耦的,对Docker daemon的维护和升级工作不会影响到运行中的容器

shim:

镜像

2020823154249

镜像使用

docker search name
docekr pull name<:tag>
docker rmi 镜像ID
docker image rm $(docker image ls -q) -f

标签

在镜像名后面的:xxx 代表标签

没有标签的镜像被称为悬虚镜像

分层

2020823154946

docker 会复用已存在的镜像层

镜像仓库

2020823154458

搭建

docekr pull registry
docker run -di --name=registry 5000:5000 registry   

上传镜像到私服

docker tag nginx 127.0.0.1:5000/nginx 
docker push 127.0.0.1:5000/nginx 

容器

持久化

容器在停止后启动写入的数据仍会存在

但是volume才是持久化的首选

重启策略

在指定事件或者错误后重启来完成自我修复

容器使用

docker ps
docker run -p 8080:80 -d daocloud.io/nginx
docker cp index.html e07dc4e0236a://usr/share/nginx/html
docker cp name:容器文件路径 宿主路径
docker stop name
# 优雅关闭并删除:stop rm
docker start name
docker exec -it <name> bash
docker inspect name
docker logs name

常用软件部署

# 将宿主机33306映射到容器3306,指定root密码为123
docker run -di --name=mysql1 -p 33306:3306 -e MYSQL_ROOT_PASSWORD=123 mysql 
docker run -di --name=mytomcat -p 9000:8080 -v /usr/local/webapps:/usr/local/tomcat/webapps tomcat 
docker run -di --name=mynginx2 -p 8080:80 nginx-update 

迁移与备份

docker commit -m 'update' e07dc4e0236a nginx-update
docker save -o nginx-update.tar nginx-update
docker load -i nginx-update.tar

容器化

202082316156

Dockerfile

批注 2019-07-25 153841

编写Dockerfile文件:

FROM ubuntu
MAINTAINER MY
RUN apt-get update
RUN apt-get install nginx -y
COPY index.html /var/www/html
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]
EXPOSE 80

每一个RUN指令会新增一个镜像层。因此,通过使用&& 连接多个命令以及使用反斜杠(\ )换行的方法,将多个命令包含在一个RUN指令中,通常来说是一种值得提倡的方式

根据文件构建镜像:

docker build -t='name' .

DockerMaven插件

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.4.12</version>
    <configuration>
      <!-- 注意imageName一定要是符合正则[a-z0-9-_.]的,否则构建不会成功 -->
      <!-- 详见:https://github.com/spotify/docker-maven-plugin    Invalid repository name ... only [a-z0-9-_.] are allowed-->
      <imageName>my-pc:5000/${project.artifactId}:${project.version}</imageName>
        <baseImage>java</baseImage>
        <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
          <resources>
              <resource>
                  <targetPath>/</targetPath>
                  <directory>${project.build.directory}</directory>
                  <include>${project.build.finalName}.jar</include>
              </resource>
          </resources>
        <dockerHost>http://my-pc:2375</dockerHost>
     </configuration>
</plugin>
<dependencies>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>activation</artifactId>
        <version>1.1.1</version>
    </dependency>
</dependencies>
mvn clean package docker:build -DpushImage

推送到仓库

docker images push

202082316201

多阶段构建

FROM xxx AS T1

FROM xxx AS T2
COPY --from=T1 ...

最佳实践

利用构建缓存:

合并镜像:

202082316289

no-install-recommends:

不要安装MSI包(Windows)

Compose

编写docker-compose.yml:

version: "3.5"
services:
  redis:
    image: "redis:alpine"
    networks:
      my-net:
  nginx:
    image: "nginx"
    networks:
      my-net:
networks:
  my-net:

volumes:
  my-net:

启动:

docker-compose up

Docker 网络

CNM: 定了Docker网络架构的基础组成要素

2020824154717 2020824154742

Libnetwork是CNM标准的实现

2020824155551

docker network ls # 列出可用网络
docker run -d --network my-net # 指定容器网络

如果在相同网络中继续接入新的容器,那么在新接入容器中是可以通过的容器名称来进行网络通信的

容器网络

Flannel:主要功能是为容器提供跨主机的网络互连,使得不同主机上的容器可以直接通信,无论它们是否在同一物理网络中。它通过创建虚拟网络层来实现这一目标,并使用Overlay网络技术在物理网络之上构建虚拟网络,其有两种实现:

使用 UDP 实现 Overlay 网络的方案

VXLAN 实现方案

sequenceDiagram
    participant Admin as 管理员
    participant FlannelAgent as Flannel代理
    participant Allocator as 分配器
    participant Container as 容器

    Admin->>FlannelAgent: 配置Flannel
    FlannelAgent->>FlannelAgent: 启动
    FlannelAgent->>Allocator: 请求子网分配

    loop 每个主机
        FlannelAgent->>FlannelAgent: 创建虚拟网络接口
        Container->>FlannelAgent: 发送网络流量
        FlannelAgent->>FlannelAgent: 封装数据包到Overlay网络
    end

    FlannelAgent->>FlannelAgent: 路由数据包到目标主机
    FlannelAgent->>Container: 解封装数据包

Calico:

网络类型

2020824155816

docker network create -d bridge localnet
# 将本机8080端口映射到容器80端口
docker run -p 8080:80 <name>

# 将本机端口随机与容器端口映射
docker run -P <name>

持久化

每个Docker容器都有自己的非持久化存储。非持久化存储自动创建,从属于容器,生命周期与容器相同

持久化是将数据存储在卷上。卷与容器是解耦的

2020825152949 2020825153020

卷类型:

卷操作

docker volume create myv
docker volume inspect myv
docker run ... --mount source=bizvol,target=/vol # 指定容器存储卷

安全

202082516037

Docker 平台安全技术:

Namespace

Docker 提供的容器环境是和 Linux 内核隔离的。想要实现这种隔离,就需要用到 Namespace 机制 Namespace的隔离并不够彻底

Capabilities

提供了更细粒度的授权机制,它定义了主体能够进行的某一类操作

CGroups

利用 CGroups 机制来实现对容器中内存、CPU 和 IO 等的限制

守护进程安全性

守护进程,具备操控 Docker 容器的全部权限

如果守护进程提供的API接口没有认证,则很容易被入侵

镜像安全

容器管理

Rancher

可以对容器进行分类、分环境管理,以图形化界面操作docker Rancher是一个开源的企业级全栈化容器部署及管理平台。Rancher为容器提供一揽 子基础架构服务:CNI兼容的网络服务、存储服务、主机管理、负载均衡、防护墙…… Rancher让上述服务跨越公有云、私有云、虚拟机、物理机环境运行,真正实现一键式应 用部署和管理

influxDB

InfluxDB是一个由InfluxData开发的开源时序型数据库。它由Go写成,着力于高性能地查询与存储时序型数据。InfluxDB被广泛应用于存储系统的监控数据,IoT行业的实时数据等场景

cAdvisor

CAdvisor是Google开源的一款用于展示和分析容器运行状态的可视化工具。通过在主机上运行CAdvisor用户可以轻松的获取到当前主机上容器的运行统计信息,并以图表的形式向用户展示

Grafana

grafana 是一款采用 go 语言编写的开源应用,主要用于大规模指标数据的可视化展现,是网络架构和应用分析中最流行的时序数据展示工具,目前已经支持绝大部分常用的时序数据库