Docker 入门到精通 (图解+秒懂+史上最全)_docker安全沙箱 框架图-程序员宅基地

技术标签: java  容器  docker  

文章很长,建议收藏起来慢慢读!疯狂创客圈总目录 语雀版 | 总目录 码云版| 总目录 博客园版 为您奉上珍贵的学习资源 :


推荐:入大厂 、做架构、大力提升Java 内功 的 精彩博文

入大厂 、做架构、大力提升Java 内功 必备的精彩博文 2021 秋招涨薪1W + 必备的精彩博文
1:Redis 分布式锁 (图解-秒懂-史上最全) 2:Zookeeper 分布式锁 (图解-秒懂-史上最全)
3: Redis与MySQL双写一致性如何保证? (面试必备) 4: 面试必备:秒杀超卖 解决方案 (史上最全)
5:面试必备之:Reactor模式 6: 10分钟看懂, Java NIO 底层原理
7:TCP/IP(图解+秒懂+史上最全) 8:Feign原理 (图解)
9:DNS图解(秒懂 + 史上最全 + 高薪必备) 10:CDN图解(秒懂 + 史上最全 + 高薪必备)
11: 分布式事务( 图解 + 史上最全 + 吐血推荐 ) 12:seata AT模式实战(图解+秒懂+史上最全)
13:seata 源码解读(图解+秒懂+史上最全) 14:seata TCC模式实战(图解+秒懂+史上最全)

Java 面试题 30个专题 , 史上最全 , 面试必刷 阿里、京东、美团… 随意挑、横着走!!!
1: JVM面试题(史上最强、持续更新、吐血推荐) 2:Java基础面试题(史上最全、持续更新、吐血推荐
3:架构设计面试题 (史上最全、持续更新、吐血推荐) 4:设计模式面试题 (史上最全、持续更新、吐血推荐)
17、分布式事务面试题 (史上最全、持续更新、吐血推荐) 一致性协议 (史上最全)
29、多线程面试题(史上最全) 30、HR面经,过五关斩六将后,小心阴沟翻船!
9.网络协议面试题(史上最全、持续更新、吐血推荐) 更多专题, 请参见【 疯狂创客圈 高并发 总目录

SpringCloud 精彩博文
nacos 实战(史上最全) sentinel (史上最全+入门教程)
SpringCloud gateway (史上最全) 更多专题, 请参见【 疯狂创客圈 高并发 总目录

背景:

下一个视频版本,从架构师视角,尼恩为大家打造高可用、高并发中间件的原理与实操。

目标:通过视频和博客的方式,为各位潜力架构师,彻底介绍清楚架构师必须掌握的高可用、高并发环境,包括但不限于:

  • 高可用、高并发nginx架构的原理与实操

  • 高可用、高并发mysql架构的原理与实操

  • 高可用、高并发nacos架构的原理与实操

  • 高可用、高并发rocketmq架构的原理与实操

  • 高可用、高并发es架构的原理与实操

  • 高可用、高并发minio架构的原理与实操

在这里插入图片描述

why 高可用、高并发中间件的原理与实操:

  • 实际的开发过程中,很多小伙伴,常常是埋头苦干,聚焦crud开发,复杂一点的环境出了问题,都不能自己去启动,出了问题,就想热锅上的蚂蚁,无从下手
  • 常常的现象是: 大家 低头看路的时间多,抬头看天的时间少,技术视野比较狭窄。常常是埋头苦干业务开发,很少投入精力进行技术提升。
  • 作为架构师,或者未来想走向高端开发,或者做架构,必须掌握高可用、高并发中间件的原理,掌握其实操。

本系列博客的具体内容,请参见 疯狂创客圈总目录 语雀版 | 总目录 码云版| 总目录 博客园版

Docker 简介

img

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了

Docker的应用场景

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

Docker 架构

Docker 包括三个基本概念:

  • 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
  • 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
  • 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。

Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。

Docker 容器通过 Docker 镜像来创建。

概念 说明
Docker 镜像(Images) Docker 镜像是用于创建 Docker 容器的模板,比如 Ubuntu 系统。
Docker 容器(Container) 容器是独立运行的一个或一组应用,是镜像运行时的实体。
Docker 客户端(Client) Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。
Docker 主机(Host) 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
Docker Registry Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
docker的守护进程查看

systemctl status docker

docker 镜像查看

docker image ls

docker 容器查看

docker ps

Docker Registry配置和查看

cat /etc/docker/daemon.json

配置私有仓库

cat>/etc/docker/daemon.json<<EOF

{

  "registry-mirrors":["http://10.24.2.30:5000","https://tnxkcso1.mirrors.aliyuncs.com"],

  "insecure-registries":["10.24.2.30:5000"]

}

EOF

在线安装docker

离线安装docker

一、基础环境
1、操作系统:CentOS 7.3
2、Docker版本:19.03.9 官方下载地址
3、官方参考文档:https://docs.docker.com/install/linux/docker-ce/binaries/#install-static-binaries

二、Docker安装

1、下载

wget https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz

注意:如果事先下载好了可以忽略这一步

2、解压

把压缩文件存在指定目录下(如root),并进行解压

tar -zxvf docker-19.03.9.tgz

cd root
[root@localhost ~]# tar -zxvf docker-19.03.6.tgz
docker/
docker/containerd
docker/docker
docker/ctr
docker/dockerd
docker/runc
docker/docker-proxy
docker/docker-init
docker/containerd-shim

3、将解压出来的docker文件内容移动到 /usr/bin/ 目录下

cp docker/* /usr/bin/

4、将docker注册为service

cat /etc/systemd/system/docker.service

vi /etc/systemd/system/docker.service

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID

# Having non-zero Limit*s causes performance problems due to accounting overhead

# in the kernel. We recommend using cgroups to do container-local accounting.

LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity

# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0

# set delegate yes so that systemd does not reset the cgroups of docker containers

Delegate=yes

# kill only the docker process, not all processes in the cgroup

KillMode=process

# restart the docker process if it exits prematurely

Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s


[Install]
WantedBy=multi-user.target

5、启动

chmod +x /etc/systemd/system/docker.service #添加文件权限并启动docker

systemctl daemon-reload #重载unit配置文件

systemctl start docker #启动Docker

systemctl enable docker.service #设置开机自启

[root@localhost ~]# vi /etc/systemd/system/docker.service
[root@localhost ~]# chmod +x /etc/systemd/system/docker.service
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl start docker
[root@localhost ~]# systemctl enable docker.service
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /etc/systemd/system/docker.service.

6、验证

systemctl status docker #查看Docker状态

docker -v #查看Docker版本

docker info

[root@localhost ~]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/etc/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2021-10-09 15:25:44 CST; 29s ago
     Docs: https://docs.docker.com
 Main PID: 1916 (dockerd)
   CGroup: /system.slice/docker.service
           ├─1916 /usr/bin/dockerd
           └─1927 containerd --config /var/run/docker/containerd/containerd.toml --log-level info

Oct 09 15:25:43 localhost.localdomain dockerd[1916]: time="2021-10-09T15:25:43.671407996+08:00" level=info msg="scheme \"unix\" not r...e=grpc
Oct 09 15:25:43 localhost.localdomain dockerd[1916]: time="2021-10-09T15:25:43.671440368+08:00" level=info msg="ccResolverWrapper: se...e=grpc
Oct 09 15:25:43 localhost.localdomain dockerd[1916]: time="2021-10-09T15:25:43.671462935+08:00" level=info msg="ClientConn switching ...e=grpc
Oct 09 15:25:43 localhost.localdomain dockerd[1916]: time="2021-10-09T15:25:43.750687781+08:00" level=info msg="Loading containers: start."
Oct 09 15:25:44 localhost.localdomain dockerd[1916]: time="2021-10-09T15:25:44.072960862+08:00" level=info msg="Default bridge (docke...dress"
Oct 09 15:25:44 localhost.localdomain dockerd[1916]: time="2021-10-09T15:25:44.153444071+08:00" level=info msg="Loading containers: done."
Oct 09 15:25:44 localhost.localdomain dockerd[1916]: time="2021-10-09T15:25:44.175249299+08:00" level=info msg="Docker daemon" commit...9.03.6
Oct 09 15:25:44 localhost.localdomain dockerd[1916]: time="2021-10-09T15:25:44.175337834+08:00" level=info msg="Daemon has completed ...ation"
Oct 09 15:25:44 localhost.localdomain systemd[1]: Started Docker Application Container Engine.
Oct 09 15:25:44 localhost.localdomain dockerd[1916]: time="2021-10-09T15:25:44.195084106+08:00" level=info msg="API listen on /var/ru....sock"
Hint: Some lines were ellipsized, use -l to show in full.
[root@localhost ~]# docker -v
Docker version 19.03.6, build 369ce74a3c
[root@localhost ~]# docker info

使用docker

调整镜像仓库

修改docker的registry
修改/etc/docker目录下的daemon.json文件

在文件中加入

{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}
 


保存退出

重新启动docker

chmod +x /etc/systemd/system/docker.service #添加文件权限并启动docker

systemctl daemon-reload #重载unit配置文件

systemctl start docker #启动Docker

systemctl restart docker #重新启动Docker

systemctl enable docker.service #设置开机自启

[root@localhost ~]# vi /etc/systemd/system/docker.service
[root@localhost ~]# chmod +x /etc/systemd/system/docker.service
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl start docker
[root@localhost ~]# systemctl enable docker.service
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /etc/systemd/system/docker.service.

发现内网的环境, 改成了阿里云的,但是没有啥用

[root@localhost ~]# cat /etc/docker/daemon.json
{
  "registry-mirrors": ["https://ku39pxyp.mirror.aliyuncs.com"],
  "insecure-registries": ["hub.company.com"]
}


确保镜像仓库可以ping通

[root@localhost ~]# curl https://ku39pxyp.mirror.aliyuncs.com
curl: (6) Could not resolve host: ku39pxyp.mirror.aliyuncs.com; Unknown error

[root@localhost ~]# ping ku39pxyp.mirror.aliyuncs.com
ping: ku39pxyp.mirror.aliyuncs.com: Name or service not known

开源的镜像仓库Harbor概述

Habor是由VMWare公司开源的容器镜像仓库。事实上,Habor是在Docker Registry上进行了相应的
企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于角色的访
问控制 ,AD/LDAP集成以及审计日志等,足以满足基本企业需求。
官方地址:https://vmware.github.io/harbor/cn/

1、什么是Harbor
• Harbor是VMware公司开源的企业级Docker Registry项目,其目标是帮助用户迅速搭建一个企业级的Docker Registry服务

• Harbor以 Docker 公司开源的Registry 为基础,提供了图形管理UI、基于角色的访问控制(Role Based AccessControl)、AD/LDAP集成、以及审计日志(Auditlogging)等企业用户需求的功能,同时还原生支持中文

• Harbor的每个组件都是以Docker 容器的形式构建的,使用docker-compose 来对它进行部署。用于部署Harbor 的docker- compose模板位于harbor/ docker- compose.yml

2、Harbor的特性
1.基于角色控制: 用户和仓库都是基于项目进行组织的,而用户在项目中可以拥有不同的权限

2.基于镜像的复制策略: 镜像可以在多个Harbor实例之间进行复制(同步)

3.支持LDAP/AD: Harbor 可以集成企业内部有的AD/LDAP (类似数据库的一-张表),用于对已经存在的用户认证和管理

4.镜像删除和垃圾回收: 镜像可以被删除,也可以回收镜像占用的空间

5.图形化用户界面: 用户可以通过浏览器来浏览,搜索镜像仓库以及对项目进行管理

6.审计管理: 所有针对镜像仓库的操作都可以被记录追溯,用于审计管理

7.支持RESTful API: RESTful API提供给管理员对于Harbor 更多的操控,使得与其它管理软件集成变得更容易

8.Harbor 和docker registry的 关系: Harbor实质 上是对docker registry做 了封装,扩展了自己的业务模板

3、Harbor的构成
Harbor在架构上主要有Proxy、 Registry、 Core services、 Database (Harbor-db) 、Log collector ( Harbor-log)、Job services六个组件

● Proxy: Harbor 的Registry、 UI、Token 服务等组件,都处在nginx 反向代理后边。该代理将来自浏览器、docker clients的请求转发到后端不同的服务上

● Registry:负责储存Docker 镜像,并处理Docker push/pull命令。由于要对用户进行访问控制,即不同用户对Docker 镜像有不同的读写权限,Registry 会指向一个Token 服务,强制用户的每次Docker pull/push 请求都要携带一个合法的Token,Registry会通过公钥对Token进行解密验证

● Core services: Harbor的核心功能,主要提供以下3个服务:
1.UI (harbor-ui) :提供图形化界面,帮助用户管理Registry. 上的镜像( image),并对用户进行授权
2.WebHook: 为了及时获取Registry.上image 状态变化的情况,在Registry. 上配置 Webhook,把状态变化传递给UI模块
3.Token 服务:负责根据用户权限给每个Docker push/pull 命令签发Token。 Docker 客户端向Registry服务发起的请求,
如果不包含Token,会被重定向到Token服务,获得Token后再重新向Registry 进行请求

● Database (harbor-db) :为core services提供数据库服务,负责储存用户权限、审计日志、Docker 镜像分组信息等数据

● Job services: 主要用于镜像复制,本地镜像可以被同步到远程Harbor 实例上

● Log collector (harbor-log) :负责收集其他组件的日志到一个地方

• Harbor的每个组件都是以Docker 容器的形式构建的,因此,使用Docker Compose 来对它进行部署。

• 总共分为7个容器运行,通过在docker-compose.yml所在目录中执行docker-compose ps命令来查看,
名称分别为: nginx、 harbor-jobservice、 harbor-ui、 harbor-db、harbor-adminserver、registry、 harbor-log.
其中harbor-adminserver主要是作为一个后端的配置数据管理,并没有太多的其他功能。harbor-ui所要操作的所有数据都通过harbor-adminserver这样一个数据配置管理中心来完成。

docker 镜像仓库Harbor_Harbor

不安全的镜像仓库

[root@localhost ~]# cat  /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

172.11.1.107    hub.company.com


发现内网的环境, 改成了阿里云的,但是没有啥用

[root@localhost ~]# cat /etc/docker/daemon.json
{
  "registry-mirrors": ["http://hub.company.co"],
  "insecure-registries": ["hub.company.com"]
}


查看docker info 的引擎信息

[root@localhost ~]# docker info
Client:
 Debug Mode: false

Server:
 Containers: 14
  Running: 7
  Paused: 0
  Stopped: 7
 Images: 19
 Server Version: 19.03.6
 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 ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: b34a5c8af56e510852c35414db4c1f4fa6172339
 runc version: 3e425f80a8c931f88e6d94a8c831b9d5aa481657
 init version: fec3683
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 3.10.0-1062.el7.x86_64
 Operating System: CentOS Linux 7 (Core)
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 15.49GiB
 Name: localhost.localdomain
 ID: I5KF:Y5JA:VCWG:DJYG:PGZO:PZVA:FYXQ:F624:RWH6:4S6R:BI6Z:L2MT
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  hub.gsafety.com
  127.0.0.0/8
 Registry Mirrors:
  https://ku39pxyp.mirror.aliyuncs.com/
 Live Restore Enabled: false




查看docker相关的进程

[root@localhost ~]# ps -ef | grep docker
root       1460      1  0 Jun23 ?        04:45:43 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root       2249   1460  0 Jun23 ?        00:00:09 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 5433 -container-ip 172.26.0.2 -container-port 5432
root       2280   1460  0 Jun23 ?        00:00:09 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 5432 -container-ip 172.26.0.3 -container-port 5432
root       2310   1455  0 Jun23 ?        00:09:35 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/78dc6aacc7d9490fa7c7252dd6b4df01af3b68c2adb69767fb0d51974ea0728c -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
root       2311   1455  0 Jun23 ?        00:16:19 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/d6ec26035ca0428d5c3bd1cc154a76b356cf3a7d0746b0455d81223c7b9ab7fd -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
root       2483   1460  0 Jun23 ?        00:00:32 /usr/bin/docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 1514 -container-ip 172.21.0.4 -container-port 10514
root       2538   1455  0 Jun23 ?        02:25:41 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/98500167fb283c56fd43f42d3357c52b393481fdcca2bc7a87128ac35e19fa5a -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
root       2571   1455  0 Jun23 ?        02:17:17 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/412652067b159ca617625c315940ce6865534e80fa94b93ef3174f653d21b826 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
root       7077   1460  0 Jun23 ?        00:00:09 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3306 -container-ip 172.19.0.2 -container-port 3306
root       7085   1455  0 Jun23 ?        00:09:39 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/976bb8cd43729535a74d1583a758be937b6cf8f7a3329a1737fcb722576d1fea -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
root       7354   1460  0 Jun23 ?        00:00:09 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3308 -container-ip 172.19.0.3 -container-port 3306
root       7386   1455  0 Jun23 ?        00:09:45 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/14112371b62521a9b52968a6b0d275700343afeceaac478cfb7a90241dfcdf61 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
root       7402   1460  0 Jun23 ?        00:00:09 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3307 -container-ip 172.19.0.4 -container-port 3306
root       7431   1455  0 Jun23 ?        00:10:30 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/a0c6a5d5f891d293ae19e0bc3413729ac41cf38cc7e58d5a547b0f0df87fd6c4 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc
root      28336  21582  0 15:32 pts/0    00:00:00 grep --color=auto docker

Docker本地镜像载入与载出

两种办法

  • 保存镜像(保存镜像载入后获得跟原镜像id相同的镜像)
  • 保存容器(保存容器载入后获得跟原镜像id不同的镜像)

拉取镜像

通过命令可以从镜像仓库中拉取镜像,默认从Docker Hub 获取。

命令格式:

docker image pull :

docker image pull rancher/rke-tools:v0.1.52

[rancher/rke-tools:v0.1.52

保存镜像

  • docker save 镜像id -o /home/mysql.tar
  • docker save 镜像id > /home/mysql.tar

docker save docker.io/rancher/rancher-agent -o /home/rancher-agent .tar

docker save f29ece87a195 -o /home/rancher-agent.tar

docker save docker.io/rancher/rke-tools -o /home/rke-tools-v0.1.52.tar

载入镜像

  • docker load -i mysql.tar

docker load -i /usr/local/rancher-v2.3.5.tar

docker load -i /usr/local/rancher-agent.tar

docker inspect f29ece87a1954772accb8a2332ee8c3fe460697e3f102ffbdc76eb9bc4f4f1d0

docker load -i /usr/local/rke-tools-v0.1.52.tar

docker load -i mysql.tar

[root@localhost ~]# docker load -i /usr/local/rancher-v2.3.5.tar
43c67172d1d1: Loading layer [==================================================>]  65.57MB/65.57MB
21ec61b65b20: Loading layer [==================================================>]  991.2kB/991.2kB
1d0dfb259f6a: Loading layer [==================================================>]  15.87kB/15.87kB
f55aa0bd26b8: Loading layer [==================================================>]  3.072kB/3.072kB
e0af200d6950: Loading layer [==================================================>]  126.1MB/126.1MB
088ed892f9ad: Loading layer [==================================================>]  6.656kB/6.656kB
6aa3142b4130: Loading layer [==================================================>]   34.5MB/34.5MB
f4e84c05ab29: Loading layer [==================================================>]  70.41MB/70.41MB
11a6e4332b53: Loading layer [==================================================>]  224.8MB/224.8MB
46d1ac556da7: Loading layer [==================================================>]  3.072kB/3.072kB
0f8b224a5802: Loading layer [==================================================>]  57.87MB/57.87MB
519eba7d586a: Loading layer [==================================================>]  99.58MB/99.58MB
3f8bb7c0c150: Loading layer [==================================================>]  4.608kB/4.608kB
c22c9a5a8211: Loading layer [==================================================>]  3.072kB/3.072kB
Loaded image: rancher/rancher:v2.3.5

打个tag

docker tag f29ece87a1954772accb8a2332ee8c3fe460697e3f102ffbdc76eb9bc4f4f1d0 rancher/rancher-agent:v2.3.5

docker tag f29ece87a195 172.18.8.104/rancher/rancher-agent:v2.3.5

docker tag 6e421b8753a2 172.18.8.104/rancher/rke-tools:v0.1.52

83fe4871cf67

docker rmi image_name

docker rmi -f 172.18.8.104/rancher/coredns-coredns:1.6.5

docker rmi -f 172.18.8.104/rancher/coredns-coredns:v3.4.3-rancher1

docker rmi hub.doge.net/ubuntu:latest

保存镜像

  • docker export 镜像id -o /home/mysql-export.tar
  • docker save 镜像tag -o /home/mysql-export.tar

载入镜像

  • docker import mysql-export.tar

Docker本地容器相关的操作

创建容器

创建名为"centos6"的容器,并在容器内部和宿主机中查看容器中的进程信息

 docker run -itd -p 6080:80 -p 6022:22 docker.io/lemonbar/centos6-ssh:latest

结果如下

[root@VM-4-17-centos ~]#    docker run -itd -p 80:80 -p 6022:22 docker.io/lemonbar/centos6-ssh:latest
Unable to find image 'lemonbar/centos6-ssh:latest' locally
latest: Pulling from lemonbar/centos6-ssh
a3ed95caeb02: Pull complete
f79eb1f22352: Pull complete
67c1aaa530c8: Pull complete
80447774eee7: Pull complete
6d67b3a80e5a: Pull complete
f1819e4b2f8f: Pull complete
09712b5b9acc: Pull complete
8bc987c5494f: Pull complete
c42b021d0ff2: Pull complete
Digest: sha256:093c2165b3c6fe05d5658343456f9b59bb7ecc690a7d3a112641c86083227dd1
Status: Downloaded newer image for lemonbar/centos6-ssh:latest
a4f1c9b8abcda78c8764cc285183dfa56cd1aa4ce6d111d4d9e77f3a57f3d5fc


查看活跃容器

docker ps

CONTAINER ID        IMAGE                                     COMMAND                  CREATED             STATUS                          PORTS                                              NAMES
a4f1c9b8abcd        lemonbar/centos6-ssh:latest               "/bin/sh -c '/usr/sb…"   32 seconds ago      Up 31 seconds                   0.0.0.0:6022->22/tcp, 0.0.0.0:6080->80/tcp         determined_curie

查看全部容器

docker ps -a

停止容器

docker stop id

删除容器

docker rm id

查看容器的进程信息

**docker top *查看容器中运行的进程信息,支持 ps 命令参数。

语法

docker top [OPTIONS] CONTAINER [ps OPTIONS]

容器运行时不一定有/bin/bash终端来交互执行top命令,而且容器还不一定有top命令,可以使用docker top来实现查看container中正在运行的进程。

Docker 1.11开始,Docker容器运行已经不是简单的通过Docker daemon来启动,而是集成了containerd、runC等多个组件。Docker服务启动之后,我们也可以看见系统上启动了dockerd、docker-containerd等进程,本文主要介绍新版Docker(1.11以后)每个部分的功能和作用。

查找容器名称的命令

[root@localhost ~]# docker ps --format "{
   {.Names}}"

结果如下:

[root@VM-4-17-centos ~]# docker ps --format "{
   {.Names}}"
determined_curie
redis
nginx_slave
nginx_master
nginx_empty
loving_agnesi
pxc_proxy
pxc03
pxc02
pxc01
affectionate_austin
nostalgic_blackwell

在容器内部和宿主机中查看容器中的进程信息

docker exec -it determined_curie  ps -ef

结果如下:

[root@VM-4-17-centos ~]# docker exec -it determined_curie  ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 08:14 pts/0    00:00:00 /usr/sbin/sshd -D
root         5     0  0 08:16 pts/1    00:00:00 ps -ef

我们可以使用docker exec命令进入容器PID名空间,并执行应用。

通过ps -ef命令,可以看到每个determined_curie 容器都包含一个PID为1的进程,"/usr/sbin/sshd",它是容器的启动进程,具有特殊意义。

利用docker top命令,可以让我们从宿主机操作系统中看到容器的进程信息。

[root@VM-4-17-centos ~]# docker top determined_curie
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                27880               27866               0                   16:14               pts/0               00:00:00            /usr/sbin/sshd -D
[root@VM-4-17-centos ~]#

查看其父进程信息
root     17205  1414  0 16:37 pts/0    00:00:00 grep --color=auto 27866
root     27866  5587  0 16:14 ?        00:00:00 docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/a4f1c9b8abcda78c8764cc285183dfa56cd1aa4ce6d111d4d9e77f3a57f3d5fc -address /var/run/docker/containerd/docker-containerd.sock -containerd-binary /usr/bin/docker-containerd -runtime-root /var/run/docker/runtime-runc
root     27880 27866  0 16:14 pts/0    00:00:00 /usr/sbin/sshd -D

查看子进程信息
[root@VM-4-17-centos ~]#  ps aux | grep 27880
root     17777  0.0  0.0 115928  1008 pts/0    S+   16:38   0:00 grep --color=auto 27880
root     27880  0.0  0.0  66664  3072 pts/0    Ss+  16:14   0:00 /usr/sbin/sshd -D

总计三个命令
ps -ef | grep 4948 #查看父进程
ps aux | grep 27880 #查看子进程(容器)
docker ps -a | grep determined_curie   #定位容器id

再启动一个 centos 容器

 docker run -itd  --name centos6-2  -p 6081:80 -p 6021:22 docker.io/lemonbar/centos6-ssh:latest

输出如下:

[root@VM-4-17-centos ~]# docker run -itd  --name centos6-2  -p 6081:80 -p 6021:22 docker.io/lemonbar/centos6-ssh:latest
460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd

查看进程信息

利用docker top命令,可以让我们从宿主机操作系统中看到容器的进程信息。

[root@VM-4-17-centos ~]# docker top centos6-2
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                4962                4948                0                   16:24               pts/0               00:00:00            /usr/sbin/sshd -D


查看其父进程信息
[root@VM-4-17-centos ~]# ps -ef | grep 4948
root      4948  5587  0 16:24 ?        00:00:00 docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd -address /var/run/docker/containerd/docker-containerd.sock -containerd-binary /usr/bin/docker-containerd -runtime-root /var/run/docker/runtime-runc
root      4962  4948  0 16:24 pts/0    00:00:00 /usr/sbin/sshd -D

查看子进程信息
[root@VM-4-17-centos ~]# ps aux | grep 4962
root      4962  0.0  0.0  66664  3068 pts/0    Ss+  16:24   0:00 /usr/sbin/sshd -D
root     15311  0.0  0.0 115932  1008 pts/0    S+   16:35   0:00 grep --color=auto 4962
总计三个命令
ps -ef | grep 4948 #查看父进程
ps aux | grep 4962 #查看子进程(容器)
docker ps -a | grep centos6-2  #定位容器id

进程的对应关系

Linux通过进程ID查看文件路径

子进程的文件路径

[root@VM-4-17-centos ~]#  ls -l /proc/27880
total 0
dr-xr-xr-x 2 root root 0 Nov  3 16:41 attr
-rw-r--r-- 1 root root 0 Nov  3 16:41 autogroup
-r-------- 1 root root 0 Nov  3 16:41 auxv
-r--r--r-- 1 root root 0 Nov  3 16:14 cgroup
--w------- 1 root root 0 Nov  3 16:41 clear_refs
-r--r--r-- 1 root root 0 Nov  3 16:15 cmdline
-rw-r--r-- 1 root root 0 Nov  3 16:41 comm
-rw-r--r-- 1 root root 0 Nov  3 16:41 coredump_filter
-r--r--r-- 1 root root 0 Nov  3 16:41 cpuset
lrwxrwxrwx 1 root root 0 Nov  3 16:41 cwd -> /
-r-------- 1 root root 0 Nov  3 16:41 environ
lrwxrwxrwx 1 root root 0 Nov  3 16:14 exe -> /usr/sbin/sshd
dr-x------ 2 root root 0 Nov  3 16:14 fd
dr-x------ 2 root root 0 Nov  3 16:41 fdinfo
-rw-r--r-- 1 root root 0 Nov  3 16:41 gid_map
-r-------- 1 root root 0 Nov  3 16:41 io
-r--r--r-- 1 root root 0 Nov  3 16:41 limits
-rw-r--r-- 1 root root 0 Nov  3 16:41 loginuid
dr-x------ 2 root root 0 Nov  3 16:41 map_files
-r--r--r-- 1 root root 0 Nov  3 16:41 maps
-rw------- 1 root root 0 Nov  3 16:41 mem
-r--r--r-- 1 root root 0 Nov  3 16:14 mountinfo
-r--r--r-- 1 root root 0 Nov  3 16:41 mounts
-r-------- 1 root root 0 Nov  3 16:41 mountstats
dr-xr-xr-x 5 root root 0 Nov  3 16:41 net
dr-x--x--x 2 root root 0 Nov  3 16:14 ns
-r--r--r-- 1 root root 0 Nov  3 16:41 numa_maps
-rw-r--r-- 1 root root 0 Nov  3 16:41 oom_adj
-r--r--r-- 1 root root 0 Nov  3 16:41 oom_score
-rw-r--r-- 1 root root 0 Nov  3 16:41 oom_score_adj
-r--r--r-- 1 root root 0 Nov  3 16:41 pagemap
-r-------- 1 root root 0 Nov  3 16:41 patch_state
-r--r--r-- 1 root root 0 Nov  3 16:41 personality
-rw-r--r-- 1 root root 0 Nov  3 16:41 projid_map
lrwxrwxrwx 1 root root 0 Nov  3 16:41 root -> /
-rw-r--r-- 1 root root 0 Nov  3 16:41 sched
-r--r--r-- 1 root root 0 Nov  3 16:41 schedstat
-r--r--r-- 1 root root 0 Nov  3 16:41 sessionid
-rw-r--r-- 1 root root 0 Nov  3 16:41 setgroups
-r--r--r-- 1 root root 0 Nov  3 16:41 smaps
-r--r--r-- 1 root root 0 Nov  3 16:41 stack
-r--r--r-- 1 root root 0 Nov  3 16:14 stat
-r--r--r-- 1 root root 0 Nov  3 16:41 statm
-r--r--r-- 1 root root 0 Nov  3 16:14 status
-r--r--r-- 1 root root 0 Nov  3 16:41 syscall
dr-xr-xr-x 3 root root 0 Nov  3 16:41 task
-r--r--r-- 1 root root 0 Nov  3 16:41 timers
-rw-r--r-- 1 root root 0 Nov  3 16:14 uid_map
-r--r--r-- 1 root root 0 Nov  3 16:41 wchan

以下是/proc目录中进程27880的信息说明:

proc/27880 pid为N的进程信息

/proc/27880/cmdline 进程启动命令

/proc/27880/cwd 链接到进程当前工作目录

/proc/27880/environ 进程环境变量列表

/proc/27880/exe 链接到进程的执行命令文件

/proc/27880/fd 包含进程相关的所有的文件描述符

/proc/27880/maps 与进程相关的内存映射信息

/proc/27880/mem 指代进程持有的内存,不可读

/proc/27880/root 链接到进程的根目录

/proc/27880/stat 进程的状态

/proc/27880/statm 进程使用的内存的状态

/proc/27880/status 进程状态信息,比stat/statm更具可读性
容器的PID namespace(命名空间)

在Docker中,进程管理的基础就是Linux内核中的PID名空间技术。

在不同PID名空间中,进程ID是独立的;即在两个不同名空间下的进程可以有相同的PID。

在Docker中,每个Container进程缺省都具有不同的PID名空间。通过名空间技术,Docker实现容器间的进程隔离。

docker中运行的容器进程,本质上还是运行在宿主机上的,所以也会拥有相对应的PID

找出容器ID
# docker ps

输出

[root@VM-4-17-centos ~]# docker ps
CONTAINER ID        IMAGE                                     COMMAND                  CREATED             STATUS                          PORTS                                              NAMES
460d68823930        lemonbar/centos6-ssh:latest               "/bin/sh -c '/usr/sb…"   32 minutes ago      Up 32 minutes                   0.0.0.0:6021->22/tcp, 0.0.0.0:6081->80/tcp         centos6-2

查看容器信息
docker inspect  id

输出

[root@VM-4-17-centos ~]# docker inspect  460d68823930
[root@VM-4-17-centos ~]#  docker inspect  460d68823930
[
    {
        "Id": "460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd",
        "Created": "2021-11-03T08:24:36.934129599Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "/usr/sbin/sshd -D"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 4962,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-11-03T08:24:37.223255812Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:efd998bd6817af509d348b488e3ce4259f9f05632644a7bf574b785bbc8950b8",
        "ResolvConfPath": "/var/lib/docker/containers/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd/hostname",
        "HostsPath": "/var/lib/docker/containers/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd/hosts",
        "LogPath": "/var/lib/docker/containers/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd-json.log",
        "Name": "/centos6-2",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {
                "22/tcp": [
                    {
                        "HostIp": "",
                        "HostPort": "6021"
                    }
                ],
                "80/tcp": [
                    {
                        "HostIp": "",
                        "HostPort": "6081"
                    }
                ]
            },
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "shareable",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DiskQuota": 0,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": 0,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/6835c1b48237aafe27e2efabeda92a3a6623f254f88d54b5e6acce454e560dd6-init/diff:/var/lib/docker/overlay2/7139bf0b716c6e0b6a0c709b7043466f9bbfd7024f8ae584061c00b0bd97348c/diff:/var/lib/docker/overlay2/66a3e278259cdcf50741ce30a115baa3bd6247a60c487e4118e85f2f39328f11/diff:/var/lib/docker/overlay2/20e22c4c28ebadb615eb4c7c290253d3eb91cb49722ee2931b0ee628352a5857/diff:/var/lib/docker/overlay2/a3fa9dbebc83a853083205b8f7921c632cd67f64531f4a25cab419a43172e3ae/diff:/var/lib/docker/overlay2/3af7958c9a4e54d24598058a9fa1e85eb35e3d40f766fa498a674b52724ae73e/diff:/var/lib/docker/overlay2/becb65af4396137ed41fe6d516e834e6e6e9120f4edfac8e2ca8dd67cce23268/diff:/var/lib/docker/overlay2/fef055305158cc96906514c447f0eaea05945138896b0b35ac4146b6a2a3e273/diff:/var/lib/docker/overlay2/79158cdf3ba832493ab0d02d560c784208fe51c74236a5a86f7fb4fb50ab6e44/diff:/var/lib/docker/overlay2/86258a18e1110582b819719593687f11f0404d00a41667b3432c3b974fb1ce42/diff:/var/lib/docker/overlay2/8826b2e0068653fb2c5e8a3dbf839470e2b8eef8cf752b5fe901bea1b210849f/diff:/var/lib/docker/overlay2/145301e2738a8a7581c2bbd5beb9bf7a49b247e46642b8084efbc026a1826116/diff:/var/lib/docker/overlay2/f621f37535e0db1fe44902e22dba7ef0844b9a8b562a9daa39a842a49e9cc9bb/diff:/var/lib/docker/overlay2/7b493e4a97907aaa18b97ad2e9120b5bf87c0e9908ee390a35ea6ff546d8cec6/diff",
                "MergedDir": "/var/lib/docker/overlay2/6835c1b48237aafe27e2efabeda92a3a6623f254f88d54b5e6acce454e560dd6/merged",
                "UpperDir": "/var/lib/docker/overlay2/6835c1b48237aafe27e2efabeda92a3a6623f254f88d54b5e6acce454e560dd6/diff",
                "WorkDir": "/var/lib/docker/overlay2/6835c1b48237aafe27e2efabeda92a3a6623f254f88d54b5e6acce454e560dd6/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "460d68823930",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "22/tcp": {},
                "80/tcp": {}
            },
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": false,
            "Env": [
                "HOME=/",
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "/usr/sbin/sshd -D"
            ],
            "Image": "docker.io/lemonbar/centos6-ssh:latest",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "ea66261fb6d8089d5b2d585a2dc32b2003365df7118f5f5e898a152fb5b35773",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "22/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "6021"
                    }
                ],
                "80/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "6081"
                    }
                ]
            },
            "SandboxKey": "/var/run/docker/netns/ea66261fb6d8",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "09ad719a4e9115ee56c5fb0f5b0d39c50bf5acaf0a1afacedc13969c82a2969f",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.6",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:06",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "2586283d16a08210c955d705f05e0f6999b59523a84b0c163e33f535af809ddd",
                    "EndpointID": "09ad719a4e9115ee56c5fb0f5b0d39c50bf5acaf0a1afacedc13969c82a2969f",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.6",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:06",
                    "DriverOpts": null
                }
            }
        }
    }
]

进入相应目录
# cd /sys/fs/cgroup/memory/docker/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd/

输出

 cd /sys/fs/cgroup/memory/docker/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd/
[root@VM-4-17-centos 460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd]# ll
total 0
-rw-r--r-- 1 root root 0 Nov  3 16:24 cgroup.clone_children
--w--w--w- 1 root root 0 Nov  3 16:24 cgroup.event_control
-rw-r--r-- 1 root root 0 Nov  3 16:24 cgroup.procs
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.failcnt
--w------- 1 root root 0 Nov  3 16:24 memory.force_empty
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.kmem.failcnt
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.kmem.limit_in_bytes
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.kmem.max_usage_in_bytes
-r--r--r-- 1 root root 0 Nov  3 16:24 memory.kmem.slabinfo
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.kmem.tcp.failcnt
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.kmem.tcp.limit_in_bytes
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.kmem.tcp.max_usage_in_bytes
-r--r--r-- 1 root root 0 Nov  3 16:24 memory.kmem.tcp.usage_in_bytes
-r--r--r-- 1 root root 0 Nov  3 16:24 memory.kmem.usage_in_bytes
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.limit_in_bytes
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.max_usage_in_bytes
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.memsw.failcnt
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.memsw.limit_in_bytes
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.memsw.max_usage_in_bytes
-r--r--r-- 1 root root 0 Nov  3 16:24 memory.memsw.usage_in_bytes
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.move_charge_at_immigrate
-r--r--r-- 1 root root 0 Nov  3 16:24 memory.numa_stat
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.oom_control
---------- 1 root root 0 Nov  3 16:24 memory.pressure_level
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.soft_limit_in_bytes
-r--r--r-- 1 root root 0 Nov  3 16:24 memory.stat
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.swappiness
-r--r--r-- 1 root root 0 Nov  3 16:24 memory.usage_in_bytes
-rw-r--r-- 1 root root 0 Nov  3 16:24 memory.use_hierarchy
-rw-r--r-- 1 root root 0 Nov  3 16:24 notify_on_release
-rw-r--r-- 1 root root 0 Nov  3 16:24 tasks

[root@VM-4-17-centos 460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd]# cat cgroup.procs
4962
11539
[root@VM-4-17-centos 460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd]# cat pids.max
max
[root@VM-4-17-centos 460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd]# cat tasks
4962
11539
[root@VM-4-17-centos 460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd]# cat cgroup.clone_children
0
[root@VM-4-17-centos 460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd]# pwd
/sys/fs/cgroup/pids/docker/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd

查看容器目录里的进程号

进程号就存在一个文件里面

[root@VM-4-17-centos 460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd]# 
cat cgroup.procs
4962

与前面利用docker top命令,可以让我们从宿主机操作系统中看到容器的进程信息。

[root@VM-4-17-centos ~]# docker top centos6-2
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                4962                4948                0                   16:24               pts/0               00:00:00            /usr/sbin/sshd -D


启动一个进程

我们下面会在 centos6-2容器中,利用docker exec命令启动一个"sleep"进程

[root@VM-4-17-centos ]# docker exec -d  centos6-2  sleep 2000
[root@VM-4-17-centos ]# docker exec  centos6-2  ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 08:24 pts/0    00:00:00 /usr/sbin/sshd -D
root         6     0  0 09:06 ?        00:00:00 sleep 2000
root        10     0  0 09:06 ?        00:00:00 ps -ef


查看宿主机的进程号

[root@VM-4-17-centos ]#  docker top centos6-2
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                4962                4948                0                   16:24               pts/0               00:00:00            /usr/sbin/sshd -D
root                11539               4948                0                   17:06               ?                   00:00:00            sleep 2000

我们可以清楚的看到exec命令创建的sleep进程属 centos6-2 容器的名空间,但是它的父进程是Docker 容器的启动进程。

查看容器目录里的进程号

进程号就存在一个文件里面

[root@VM-4-17-centos 460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd]# cat cgroup.procs
4962
11539


 docker exec -d  centos6-2 pstree -p
 
 docker exec -d  centos6-2 ps -auxf
 
  docker exec -d  centos6-2 ll /proc

输出

[root@VM-4-17-centos docker]#  docker exec  centos6-2  ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 08:24 pts/0    00:00:00 /usr/sbin/sshd -D
root         6     0  0 09:06 ?        00:00:00 sleep 2000
root        40     0  0 09:26 ?        00:00:00 ps -ef
[root@VM-4-17-centos docker]#  docker exec  centos6-2  ps -auxf
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root        44  0.0  0.0  13360  1012 ?        Rs   09:26   0:00 ps -auxf
root         6  0.0  0.0   4120   316 ?        Ss   09:06   0:00 sleep 2000
root         1  0.0  0.0  66664  3068 pts/0    Ss+  08:24   0:00 /usr/sbin/sshd -D
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
[root@VM-4-17-centos docker]#  docker exec  centos6-2  pstree -p
sshd(1)

Docker文件目录和容器内部操作

Docker默认的文件目录位于Linux server的/var/lib/docker 下面。目录结构如下

img

|-----containers:用于存储容器信息

|-----image:用来存储镜像中间件及本身信息,大小,依赖信息

|-----network

|-----swarm

|-----tmp:docker临时目录

|-----trust:docker信任目录

|-----volumes:docker卷目录

还可以通过docker指令确认文件位置:

docker info

img

查看某个容器的文件目录:

 docker exec 容器name ls

img

 docker exec centos6-2   ls /proc
[root@VM-4-17-centos containers]#  docker exec centos6-2  ls /proc
1
103
acpi
buddyinfo
bus
cgroups
cmdline
consoles
cpuinfo
crypto
devices
diskstats
dma
driver
execdomains
fb
filesystems
fs
interrupts
iomem
ioports
irq
kallsyms
kcore
key-users
keys
kmsg
kpagecount
kpageflags
loadavg
locks
mdstat
meminfo
misc
modules
mounts
mtrr
net
pagetypeinfo
partitions
sched_debug
schedstat
scsi
self
slabinfo
softirqs
stat
swaps
sys
sysrq-trigger
sysvipc
timer_list
timer_stats
tty
uptime
version
vmallocinfo
vmstat
zoneinfo

docker daemon (docker守护进程)

pidof dockerd   #查看docker守护进程pid
lsof -p 3197 | wc -l #docker守护进程打开的文件数

在两个容器中的"centos "是两个独立的进程,但是他们拥有相同的父进程 Docker Daemon。

所以Docker可以父子进程的方式在Docker Daemon和Redis容器之间进行交互。

另一个值得注意的方面是,docker exec命令可以进入指定的容器内部执行命令。由它启动的进程属于容器的namespace和相应的cgroup。

但是这些进程的父进程是Docker Daemon而非容器的PID1进程。

我们下面会在Redis容器中,利用docker exec命令启动一个"sleep"进程

docker@default:~$ docker exec -d redis sleep 2000
docker@default:~$ docker exec redis ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
redis        1     0  0 02:26 ?        00:00:00 redis-server *:6379
root        11     0  0 02:26 ?        00:00:00 sleep 2000
root        21     0  0 02:29 ?        00:00:00 ps -ef
docker@default:~$ docker top redis
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
999                 9955                1264                0                   02:12               ?                   00:00:00            redis-server *:6379
root                9984                1264                0                   02:13               ?                   00:00:00            sleep 2000

我们可以清楚的看到exec命令创建的sleep进程属Redis容器的名空间,但是它的父进程是Docker Daemon。

如果我们在宿主机操作系统中手动杀掉容器的启动进程(在上文示例中是redis-server),容器会自动结束,而容器名空间中所有进程也会退出。

docker@default:~$ PID=$(docker inspect --format="{
   {.State.Pid}}" redis)
docker@default:~$ sudo kill $PID
docker@default:~$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
356eca186321        redis               "/entrypoint.sh redis"   23 minutes ago      Up 4 minutes               6379/tcp            redis2
f6bc57cc1b46        redis               "/entrypoint.sh redis"   23 minutes ago      Exited (0) 4 seconds ago                       redis

通过以上示例:

  • 每个容器有独立的PID名空间,
  • 容器的生命周期和其PID1进程一致
  • 利用docker exec可以进入到容器的名空间中启动进程

Docker Daemon 原理

作为Docker容器管理的守护进程,Docker Daemon从最初集成在docker命令中(1.11版本前),到后来的独立成单独二进制程序(1.11版本开始),其功能正在逐渐拆分细化,被分配到各个单独的模块中去。

演进:Docker守护进程启动

从Docker服务的启动脚本,也能看见守护进程的逐渐剥离:

在Docker 1.8之前,Docker守护进程启动的命令为:

docker -d

这个阶段,守护进程看上去只是Docker client的一个选项。

Docker 1.8开始,启动命令变成了:

docker daemon

这个阶段,守护进程看上去是docker命令的一个模块。

Docker 1.11开始,守护进程启动命令变成了:

dockerd

其服务的配置文件为:


[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID

此时已经和Docker client分离,独立成一个二进制程序了。

当然,守护进程模块不停的在重构,其基本功能和定位没有变化。和一般的CS架构系统一样,守护进程负责和Docker client交互,并管理Docker镜像、容器。

OCI(Open Container Initiative)

Open Container Initiative,也就是常说的OCI,是由多家公司共同成立的项目,并由linux基金会进行管理,致力于container runtime的标准的制定和runc的开发等工作。
官方的介绍是

An open governance structure for the express purpose of creating open industry standards around container formats and runtime. – Open Containers Official Site

所谓container runtime,主要负责的是容器的生命周期的管理。oci的runtime spec标准中对于容器的状态描述,以及对于容器的创建、删除、查看等操作进行了定义。

目前主要有两个标准文档:容器运行时标准 (runtime spec)和 容器镜像标准(image spec)。
这两个协议通过 OCI runtime filesytem bundle 的标准格式连接在一起,OCI 镜像可以通过工具转换成 bundle,然后 OCI 容器引擎能够识别这个 bundle 来运行容器。
在这里插入图片描述

image spec

OCI 容器镜像主要包括几块内容:

文件系统:以 layer 保存的文件系统,每个 layer 保存了和上层之间变化的部分,layer 应该保存哪些文件,怎么表示增加、修改和删除的文件等
config 文件:保存了文件系统的层级信息(每个层级的 hash 值,以及历史信息),以及容器运行时需要的一些信息(比如环境变量、工作目录、命令参数、mount 列表),指定了镜像在某个特定平台和系统的配置。比较接近我们使用 docker inspect <image_id> 看到的内容
manifest 文件:镜像的 config 文件索引,有哪些 layer,额外的 annotation 信息,manifest 文件中保存了很多和当前平台有关的信息
index 文件:可选的文件,指向不同平台的 manifest 文件,这个文件能保证一个镜像可以跨平台使用,每个平台拥有不同的 manifest 文件,使用 index 作为索引

runtime spec

OCI 对容器 runtime 的标准主要是指定容器的运行状态,和 runtime 需要提供的命令。下图可以是容器状态转换图:
在这里插入图片描述

Docker CLI

/usr/bin/docker

Docker 的客户端工具,通过CLI与 dockerd API 交流。 CLI 的例子比如docker build … docker run …

Docker Daemon

/usr/bin/dockerd

当然,守护进程模块不停的在重构,其基本功能和定位没有变化。和一般的CS架构系统一样,守护进程负责和Docker client交互,并管理Docker镜像、容器。

Containerd

/usr/bin/docker-containerd

containerd是容器技术标准化之后的产物,为了能够兼容OCI标准,将容器运行时及其管理功能从Docker Daemon剥离。理论上,即使不运行dockerd,也能够直接通过containerd来管理容器。(当然,containerd本身也只是一个守护进程,容器的实际运行时由后面介绍的runC控制。)
最近,Docker刚刚宣布开源containerd。从其项目介绍页面可以看出,containerd主要职责是镜像管理(镜像、元信息等)、容器执行(调用最终运行时组件执行)。

containerd向上为Docker Daemon提供了gRPC接口,使得Docker Daemon屏蔽下面的结构变化,确保原有接口向下兼容。向下通过containerd-shim结合runC,使得引擎可以独立升级,避免之前Docker Daemon升级会导致所有容器不可用的问题。
在这里插入图片描述
在这里插入图片描述
containerd fully leverages the OCI runtime specification1, image format specifications and OCI reference implementation (runc).
containerd includes a daemon exposing gRPC API over a local UNIX socket. The API is a low-level one designed for higher layers to wrap and extend. Containerd uses RunC to run containers according to the OCI specification.

docker-shim

/usr/bin/docker-containerd-shim

每启动一个容器都会起一个新的docker-shim的一个进程.
他直接通过指定的三个参数来创建一个容器:

  1. 容器id
  2. boundle目录(containerd的对应某个容器生成的目录,一般位于:/var/run/docker/libcontainerd/containerID)
  3. 运行是二进制(默认为runc)来调用runc的api(比如创建容器时,最后拼装的命令如下:runc create 。。。)

他的作用是:

  1. 它允许容器运行时(即 runC)在启动容器之后退出,简单说就是不必为每个容器一直运行一个容器运行时(runC)
  2. 即使在 containerd 和 dockerd 都挂掉的情况下,容器的标准 IO 和其它的文件描述符也都是可用的
  3. 向 containerd 报告容器的退出状态
    前两点尤其重要,有了它们就可以在不中断容器运行的情况下升级或重启 dockerd(这对于生产环境来说意义重大)。

runc (OCI reference implementation)

/usr/bin/docker-runc 

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

runC是从Docker的libcontainer中迁移而来的,实现了容器启停、资源隔离等功能。

Docker默认提供了docker-runc实现,事实上,通过containerd的封装,可以在Docker Daemon启动的时候指定runc的实现。

我们可以通过启动Docker Daemon时增加–add-runtime参数来选择其他的runC现。例如:

docker daemon --add-runtime "custom=/usr/local/bin/my-runc-replacement"

Docker、containerd, containerd-shim和runc之间的关系

在这里插入图片描述
他们之间的关系如下图:

这里写图片描述

我们可以通过启动一个Docker容器,来观察进程之间的关联。

通过docker 而通过runc来启动一个container的过程

查看进程信息

利用docker top命令,可以让我们从宿主机操作系统中看到容器的进程信息。

[root@VM-4-17-centos ~]# docker top centos6-2
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                4962                4948                0                   16:24               pts/0               00:00:00            /usr/sbin/sshd -D


查看子进程信息

[root@VM-4-17-centos containerd]# ps aux | grep 4948
root      4948  0.0  0.0  12212  3696 ?        Sl   16:24   0:00 docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd -address /var/run/docker/containerd/docker-containerd.sock -containerd-binary /usr/bin/docker-containerd -runtime-root /var/run/docker/runtime-runc
root     27040  0.0  0.0 115932  1004 pts/0    S+   18:32   0:00 grep --color=auto 4948

查看进程树
pstree -l -a -A 4948 -p

输出结果如下:

[root@VM-4-17-centos containerd]# pstree -l -a -A 4948 -p
docker-containe,4948 -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd -address /var/run/docker/containerd/docker-containerd.sock -containerd-binary /usr/bin/docker-containerd -runtime-root /var/run/docker/runtime-runc
  |-sshd,4962 -D
  |-{docker-containe},4949
  |-{docker-containe},4950
  |-{docker-containe},4951
  |-{docker-containe},4952
  |-{docker-containe},4953
  |-{docker-containe},4954
  `-{docker-containe},1593


虽然pstree命令截断了命令,但我们还是能够看出,当Docker daemon启动之后,dockerd和docker-containerd进程一直存在。

当启动容器之后,docker-containerd进程(也是这里介绍的containerd组件)会创建docker-containerd-shim进程,其中的参数460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd就是要启动容器的id。

最后docker-containerd-shim子进程,已经是实际在容器中运行的进程(既sleep 1000)。

docker-containerd-shim另一个参数,是一个和容器相关的目录/var/run/docker/containerd/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd,里面的内容有:

[root@VM-4-17-centos containerd]# ll /var/run/docker/containerd/460d688239304172f39bb9586bfc5959e0c3db64e7c3a0937f1003f94408ebbd
total 0
prwx------ 1 root root 0 Nov  3 16:24 init-stdin
prwx------ 1 root root 0 Nov  3 16:24 init-stdout

其中包括了容器配置和标准输入、标准输出、标准错误三个管道文件。

docker-shim

docker-shim是一个真实运行的容器的真实垫片载体,每启动一个容器都会起一个新的docker-shim的一个进程,
他直接通过指定的三个参数:容器id,boundle目录(containerd的对应某个容器生成的目录,一般位于:/var/run/docker/libcontainerd/containerID),
运行是二进制(默认为runc)来调用runc的api创建一个容器(比如创建容器:最后拼装的命令如下:runc create 。。。。。)

RunC

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

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

CRI

kubernetes在初期版本里,就对多个容器引擎做了兼容,因此可以使用docker、rkt对容器进行管理。以docker为例,kubelet中会启动一个docker manager,通过直接调用docker的api进行容器的创建等操作。

在k8s 1.5版本之后,kubernetes推出了自己的运行时接口api–CRI(container runtime interface)。cri接口的推出,隔离了各个容器引擎之间的差异,而通过统一的接口与各个容器引擎之间进行互动。

与oci不同,cri与kubernetes的概念更加贴合,并紧密绑定。cri不仅定义了容器的生命周期的管理,还引入了k8s中pod的概念,并定义了管理pod的生命周期。

在kubernetes中,pod是由一组进行了资源限制的,在隔离环境中的容器组成。而这个隔离环境,称之为PodSandbox。在cri开始之初,主要是支持docker和rkt两种。其中kubelet是通过cri接口,调用docker-shim,并进一步调用docker api实现的。

如上文所述,docker独立出来了containerd。kubernetes也顺应潮流,孵化了cri-containerd项目,用以将containerd接入到cri的标准中。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

为了进一步与oci进行兼容,kubernetes还孵化了cri-o,成为了架设在cri和oci之间的一座桥梁。通过这种方式,可以方便更多符合oci标准的容器运行时,接入kubernetes进行集成使用。可以预见到,通过cri-o,kubernetes在使用的兼容性和广泛性上将会得到进一步加强。
在这里插入图片描述

安装docker-compose

Docker-Compose 项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。

Docker-Compose 项目由 Python 编写,调用 Docker 服务提供的API来对容器进行管理。因此,只要所操作的平台支持 Docker API,就可以在其上利用Compose 来进行编排管理。

首先检查 版本

[root@k8s-master ~]#  /usr/local/bin/docker-compose -version
docker-compose version 1.25.1, build a82fef07

如果安装好了,就ok了,如果没有安装,则安装docker

1.从github上下载docker-compose二进制文件安装

下载最新版的docker-compose文件

# curl -L https://github.com/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

注明:离线安装包已经提供。上传后,复制到/usr/local/bin/即可

cp /root/docker-compose  /usr/local/bin/

添加可执行权限

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

测试安装结果

 

[root@localhost ~]# docker-compose --version 
docker-compose version 1.25.1, build a82fef07


cp /root/docker-compose  /usr/local/bin/
chmod +x /usr/local/bin/docker-compose
 docker-compose --version

参考文献:

https://blog.csdn.net/qq_21222149/article/details/89201744

https://blog.csdn.net/warrior_0319/article/details/80073720
http://www.sel.zju.edu.cn/?p=840
http://alexander.holbreich.org/docker-components-explained/
https://www.cnblogs.com/sparkdev/p/9129334.htmls

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/crazymakercircle/article/details/121134690

智能推荐

Docker 快速上手学习入门教程_docker菜鸟教程-程序员宅基地

文章浏览阅读2.5w次,点赞6次,收藏50次。官方解释是,docker 容器是机器上的沙盒进程,它与主机上的所有其他进程隔离。所以容器只是操作系统中被隔离开来的一个进程,所谓的容器化,其实也只是对操作系统进行欺骗的一种语法糖。_docker菜鸟教程

电脑技巧:Windows系统原版纯净软件必备的两个网站_msdn我告诉你-程序员宅基地

文章浏览阅读5.7k次,点赞3次,收藏14次。该如何避免的,今天小编给大家推荐两个下载Windows系统官方软件的资源网站,可以杜绝软件捆绑等行为。该站提供了丰富的Windows官方技术资源,比较重要的有MSDN技术资源文档库、官方工具和资源、应用程序、开发人员工具(Visual Studio 、SQLServer等等)、系统镜像、设计人员工具等。总的来说,这两个都是非常优秀的Windows系统镜像资源站,提供了丰富的Windows系统镜像资源,并且保证了资源的纯净和安全性,有需要的朋友可以去了解一下。这个非常实用的资源网站的创建者是国内的一个网友。_msdn我告诉你

vue2封装对话框el-dialog组件_<el-dialog 封装成组件 vue2-程序员宅基地

文章浏览阅读1.2k次。vue2封装对话框el-dialog组件_

MFC 文本框换行_c++ mfc同一框内输入二行怎么换行-程序员宅基地

文章浏览阅读4.7k次,点赞5次,收藏6次。MFC 文本框换行 标签: it mfc 文本框1.将Multiline属性设置为True2.换行是使用"\r\n" (宽字符串为L"\r\n")3.如果需要编辑并且按Enter键换行,还要将 Want Return 设置为 True4.如果需要垂直滚动条的话将Vertical Scroll属性设置为True,需要水平滚动条的话将Horizontal Scroll属性设_c++ mfc同一框内输入二行怎么换行

redis-desktop-manager无法连接redis-server的解决方法_redis-server doesn't support auth command or ismis-程序员宅基地

文章浏览阅读832次。检查Linux是否是否开启所需端口,默认为6379,若未打开,将其开启:以root用户执行iptables -I INPUT -p tcp --dport 6379 -j ACCEPT如果还是未能解决,修改redis.conf,修改主机地址:bind 192.168.85.**;然后使用该配置文件,重新启动Redis服务./redis-server redis.conf..._redis-server doesn't support auth command or ismisconfigured. try

实验四 数据选择器及其应用-程序员宅基地

文章浏览阅读4.9k次。济大数电实验报告_数据选择器及其应用

随便推点

灰色预测模型matlab_MATLAB实战|基于灰色预测河南省社会消费品零售总额预测-程序员宅基地

文章浏览阅读236次。1研究内容消费在生产中占据十分重要的地位,是生产的最终目的和动力,是保持省内经济稳定快速发展的核心要素。预测河南省社会消费品零售总额,是进行宏观经济调控和消费体制改变创新的基础,是河南省内人民对美好的全面和谐社会的追求的要求,保持河南省经济稳定和可持续发展具有重要意义。本文建立灰色预测模型,利用MATLAB软件,预测出2019年~2023年河南省社会消费品零售总额预测值分别为21881...._灰色预测模型用什么软件

log4qt-程序员宅基地

文章浏览阅读1.2k次。12.4-在Qt中使用Log4Qt输出Log文件,看这一篇就足够了一、为啥要使用第三方Log库,而不用平台自带的Log库二、Log4j系列库的功能介绍与基本概念三、Log4Qt库的基本介绍四、将Log4qt组装成为一个单独模块五、使用配置文件的方式配置Log4Qt六、使用代码的方式配置Log4Qt七、在Qt工程中引入Log4Qt库模块的方法八、获取示例中的源代码一、为啥要使用第三方Log库,而不用平台自带的Log库首先要说明的是,在平时开发和调试中开发平台自带的“打印输出”已经足够了。但_log4qt

100种思维模型之全局观思维模型-67_计算机中对于全局观的-程序员宅基地

文章浏览阅读786次。全局观思维模型,一个教我们由点到线,由线到面,再由面到体,不断的放大格局去思考问题的思维模型。_计算机中对于全局观的

线程间控制之CountDownLatch和CyclicBarrier使用介绍_countdownluach于cyclicbarrier的用法-程序员宅基地

文章浏览阅读330次。一、CountDownLatch介绍CountDownLatch采用减法计算;是一个同步辅助工具类和CyclicBarrier类功能类似,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。二、CountDownLatch俩种应用场景: 场景一:所有线程在等待开始信号(startSignal.await()),主流程发出开始信号通知,既执行startSignal.countDown()方法后;所有线程才开始执行;每个线程执行完发出做完信号,既执行do..._countdownluach于cyclicbarrier的用法

自动化监控系统Prometheus&Grafana_-自动化监控系统prometheus&grafana实战-程序员宅基地

文章浏览阅读508次。Prometheus 算是一个全能型选手,原生支持容器监控,当然监控传统应用也不是吃干饭的,所以就是容器和非容器他都支持,所有的监控系统都具备这个流程,_-自动化监控系统prometheus&grafana实战

React 组件封装之 Search 搜索_react search-程序员宅基地

文章浏览阅读4.7k次。输入关键字,可以通过键盘的搜索按钮完成搜索功能。_react search