docker简介-学习与参考
docker
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 (SDK | Docker Docs) 与 Docker 的守护进程通信。 |
Docker 主机(Host) | 一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。 |
Docker Registry | Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub(https://hub.docker.com) 提供了庞大的镜像集合供使用。一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。 |
docker的基础命令
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 containersDelegate=yes# kill only the docker process, not all processes in the cgroupKillMode=process# restart the docker process if it exits prematurelyRestart=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 EngineLoaded: loaded (/etc/systemd/system/docker.service; enabled; vendor preset: disabled)Active: active (running) since Sat 2021-10-09 15:25:44 CST; 29s agoDocs: https://docs.docker.comMain PID: 1916 (dockerd)CGroup: /system.slice/docker.service├─1916 /usr/bin/dockerd└─1927 containerd --config /var/run/docker/containerd/containerd.toml --log-level infoOct 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的registry
修改/etc/docker目录下的daemon.json文件
在文件中加入
{"registry-mirrors": ["https://registry.docker-cn.com"]
}
保存退出
重新启动docker
chmod +x /etc/systemd/system/docker.service #添加文件权限并启动dockersystemctl daemon-reload #重载unit配置文件systemctl start docker #启动Dockersystemctl restart docker #重新启动Dockersystemctl 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
查看docker info 的引擎信息
[root@localhost ~]# docker info
Client:Debug Mode: falseServer:Containers: 14Running: 7Paused: 0Stopped: 7Images: 19Server Version: 19.03.6Storage Driver: overlay2Backing Filesystem: xfsSupports d_type: trueNative Overlay Diff: trueLogging Driver: json-fileCgroup Driver: cgroupfsPlugins:Volume: localNetwork: bridge host ipvlan macvlan null overlayLog: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslogSwarm: inactiveRuntimes: runcDefault Runtime: runcInit Binary: docker-initcontainerd version: b34a5c8af56e510852c35414db4c1f4fa6172339runc version: 3e425f80a8c931f88e6d94a8c831b9d5aa481657init version: fec3683Security Options:seccompProfile: defaultKernel Version: 3.10.0-1062.el7.x86_64Operating System: CentOS Linux 7 (Core)OSType: linuxArchitecture: x86_64CPUs: 4Total Memory: 15.49GiBName: localhost.localdomainID: I5KF:Y5JA:VCWG:DJYG:PGZO:PZVA:FYXQ:F624:RWH6:4S6R:BI6Z:L2MTDocker Root Dir: /var/lib/dockerDebug Mode: falseRegistry: https://index.docker.io/v1/Labels:Experimental: falseInsecure Registries:hub.gsafety.com127.0.0.0/8Registry 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
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本地镜像载入与载出
两种办法
- 保存镜像(保存镜像载入后获得跟原镜像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
注:本文以 PDF 持续更新,最新尼恩 架构笔记、面试题 的PDF文件,请从下面的链接获取:码云 或者 语雀
在容器内部和宿主机中查看容器中的进程信息
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@VM-4-17-centos ~]# ps aux | grep 4948
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 -pdocker exec -d centos6-2 ps -auxfdocker 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 下面。目录结构如下
|-----containers:用于存储容器信息
|-----image:用来存储镜像中间件及本身信息,大小,依赖信息
|-----network
|-----swarm
|-----tmp:docker临时目录
|-----trust:docker信任目录
|-----volumes:docker卷目录
还可以通过docker指令确认文件位置:
docker info
查看某个容器的文件目录:
docker exec 容器name ls
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的一个进程.
他直接通过指定的三个参数来创建一个容器:
- 容器id
- boundle目录(containerd的对应某个容器生成的目录,一般位于:/var/run/docker/libcontainerd/containerID)
- 运行是二进制(默认为runc)来调用runc的api(比如创建容器时,最后拼装的命令如下:runc create 。。。)
他的作用是:
- 它允许容器运行时(即 runC)在启动容器之后退出,简单说就是不必为每个容器一直运行一个容器运行时(runC)
- 即使在 containerd 和 dockerd 都挂掉的情况下,容器的标准 IO 和其它的文件描述符也都是可用的
- 向 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在使用的兼容性和广泛性上将会得到进一步加强。
注:本文以 PDF 持续更新,最新尼恩 架构笔记、面试题 的PDF文件,请从下面的链接获取:码云 或者 语雀
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 a82fef07cp /root/docker-compose /usr/local/bin/
chmod +x /usr/local/bin/docker-composedocker-compose --version
总结:docker改变了什么
- 面向产品:产品交付
- 面向开发:简化环境配置
- 面向测试:多版本测试
- 面向运维:环境一致性
- 面向架构:自动化扩容(微服务)
聊聊:docker是怎么工作的?
实际上docker使用了常见的CS架构,也就是client-server模式,docker client负责处理用户输入的各种命令,比如docker build、docker run,真正工作的其实是server,也就是docker demon,值得注意的是,docker client和docker demon可以运行在同一台机器上。
Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。守护进程和客户端可以运行在同一台机器上。
聊聊:docker的工作原理是什么,讲一下
docker是一个Client-Server结构的系统,docker守护进程运行在宿主机上,
守护进程从客户端接受命令并管理运行在主机上的容器,容器是一个运行时环境,这就是我们说的集装箱。
聊聊:docker架构
- distribution 负责与docker registry交互,上传洗澡镜像以及v2 registry 有关的源数据
- registry负责docker registry有关的身份认证、镜像查找、镜像验证以及管理registry mirror等交互操作
- image 负责与镜像源数据有关的存储、查找,镜像层的索引、查找以及镜像tar包有关的导入、导出操作
- reference负责存储本地所有镜像的repository和tag名,并维护与镜像id之间的映射关系
- layer模块负责与镜像层和容器层源数据有关的增删改查,并负责将镜像层的增删改查映射到实际存储镜像层文件的graphdriver模块
- graghdriver是所有与容器镜像相关操作的执行者
聊聊:docker的组成包含哪几大部分
一个完整的docker有以下几个部分组成:
1、docker client,客户端,为用户提供一系列可执行命令,用户用这些命令实现跟 docker daemon 交互;
2、docker daemon,守护进程,一般在宿主主机后台运行,等待接收来自客户端的请求消息;
3、docker image,镜像,镜像run之后就生成为docker容器;
4、docker container,容器,一个系统级别的服务,拥有自己的ip和系统目录结构;运行容器前需要本地存在对应的镜像,如果本地不存在该镜像则就去镜像仓库下载。
docker 使用客户端-服务器 (C/S) 架构模式,使用远程api来管理和创建docker容器。docker 容器通过 docker 镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类。
聊聊:docker技术的三大核心概念是什么?
镜像:
镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。
容器:
容器是基于镜像创建的,是镜像运行起来之后的一个实例,容器才是真正运行业务程序的地方。如果把镜像比作程序里面的类,那么容器就是对象。
镜像仓库:
存放镜像的地方,研发工程师打包好镜像之后需要把镜像上传到镜像仓库中去,然后就可以运行有仓库权限的人拉取镜像来运行容器了。
聊聊:基本的Docker使用流程
- 一切都从Dockerfile开始。Dockerfile是镜像的源代码。
- 创建Dockerfile后,您可以构建它以创建容器的镜像。镜像只是“源代码”的“编译版本”,即Dockerfile。
- 获得容器的镜像后,应使用注册表重新分发容器。注册表就像一个git存储库 - 你可以推送和拉取镜像。
- 接下来,您可以使用该镜像来运行容器。在许多方面,正在运行的容器与虚拟机(但没有管理程序)非常相似。
聊聊:Docker 安全么?
Docker 利用了 Linux 内核中很多安全特性来保证不同容器之间的隔离,并且通
过签名机制来对镜像进行验证。大量生产环境的部署证明,Docker 虽然隔离性无法与
虚拟机相比,但仍然具有极高的安全性。
聊聊:Docker 与 虚拟机 有何不同?
Docker 不是虚拟化方法。它依赖于实际实现基于容器的虚拟化或操作系统级虚拟化的其他工具。为此,Docker 最初使用 LXC 驱动程序,然后移动到libcontainer 现在重命名为 runc。Docker 主要专注于在应用程序容器内自动部署应用程序。应用程序容器旨在打包和运行单个服务,而系统容器则设计为运行多个进程,如虚拟机。因此,Docker 被视为容器化系统上的容器管理或应用程序部署工具。
- 容器不需要引导操作系统内核,因此可以在不到一秒的时间内创建容器。此功能使基于容器的虚拟化比其他虚拟化方法更加独特和可取。
- 由于基于容器的虚拟化为主机增加了很少或没有开销,因此基于容器的虚拟化具有接近本机的性能。
- 对于基于容器的虚拟化,与其他虚拟化不同,不需要其他软件。
- 主机上的所有容器共享主机的调度程序,从而节省了额外资源的需求。
- 与虚拟机映像相比,容器状态(Docker 或 LXC 映像)的大小很小,因此容器映像很容易分发。
- 容器中的资源管理是通过 cgroup 实现的。Cgroups 不允许容器消耗比分配给它们更多的资源。虽然主机的所有资源都在虚拟机中可见,但无法使用。这可以通过在容器和主机上同时运行 top 或 htop 来实现。所有环境的输出看起来都很相似。
特性 | Docker | 虚拟机 |
---|---|---|
启动速度 | 秒级 | 分钟级 |
交付/部署 | 开发、测试、生产环境一致 | 无成熟体系 |
性能 | 近似物理机 | 性能损耗大 |
体量 | 极小(MB) | 较大(GB) |
迁移/扩展 | 跨平台,可复制 | 较为复杂 |
聊聊:docker与传统虚拟机的区别什么?
1、传统虚拟机是需要安装整个操作系统的,然后再在上面安装业务应用,启动应用,通常需要几分钟去启动应用,而docker是直接使用镜像来运行业务容器的,其容器启动属于秒级别;
2、Docker需要的资源更少,Docker在操作系统级别进行虚拟化,Docker容器和内核交互,几乎没有性能损耗,而虚拟机运行着整个操作系统,占用物理机的资源就比较多;
3、Docker更轻量,Docker的架构可以共用一个内核与共享应用程序库,所占内存极小;同样的硬件环境,Docker运行的镜像数远多于虚拟机数量,对系统的利用率非常高;
4、与虚拟机相比,Docker隔离性更弱,Docker属于进程之间的隔离,虚拟机可实现系统级别隔离;
5、Docker的安全性也更弱,Docker的租户root和宿主机root相同,一旦容器内的用户从普通用户权限提升为root权限,它就直接具备了宿主机的root权限,进而可进行无限制的操作。虚拟机租户root权限和宿主机的root虚拟机权限是分离的,并且虚拟机利用如Intel的VT-d和VT-x的ring-1硬件隔离技术,这种技术可以防止虚拟机突破和彼此交互,而容器至今还没有任何形式的硬件隔离;
6、Docker的集中化管理工具还不算成熟,各种虚拟化技术都有成熟的管理工具,比如:VMware vCenter提供完备的虚拟机管理能力;
7、Docker对业务的高可用支持是通过快速重新部署实现的,虚拟化具备负载均衡,高可用、容错、迁移和数据保护等经过生产实践检验的成熟保障机制,Vmware可承诺虚拟机99.999%高可用,保证业务连续性;
8、虚拟化创建是分钟级别的,Docker容器创建是秒级别的,Docker的快速迭代性,决定了无论是开发、测试、部署都可以节省大量时间;
9、虚拟机可以通过镜像实现环境交付的一致性,但镜像分发无法体系化,Docker在Dockerfile中记录了容器构建过程,可在集群中实现快速分发和快速部署。
聊聊:Docker与LXC ( Linux Container)有何不同?
LXC利用Linux上相关技术实现了容器支持; Docker早期版本中使用了LXC技术,后期演化为新的 libcontainer, 在如下的几个方面进行了改进:
- 移植性: 通过抽象容器配置, 容器可以实现从一个平台移植到另一个平台;
- 镜像系统: 基于AUFS的镜像系统为容器的分发带来了很多的便利, 同时共同的镜像层只需要存储一份,实现高效率的存储;
- 版本管理: 类似于Git的版本管理理念, 用户可以更方便地创建、 管理镜像文件;
- 仓库系统: 仓库系统大大降低了镜像的分发和管理的成本;
- 周边工具: 各种现有工具(配置管理、 云平台)对Docker的支持, 以及基于Docker 的PaaS、CI等系统, 让Docker的应用更加方便和多样化。
聊聊:什么是 Docker 镜像?
Docker 镜像是 Docker 容器的源代码,Docker 镜像用于创建容器。使用build 命令创建镜像。
聊聊:什么是 Docker 容器?
Docker 容器包括应用程序及其所有依赖项,作为操作系统的独立进程运行。
聊聊:Docker 容器有几种状态?
四种状态:运行、已暂停、重新启动、已退出。
聊聊:Dockerfile 中最常见的指令是什么?
- FROM:指定基础镜像
- LABEL:功能是为镜像指定标签
- RUN:运行指定的命令
- CMD:容器启动时要运行的命令
聊聊:Dockerfile 中的命令 COPY 和 ADD 命令有什么区别?
COPY 与 ADD 的区别 COPY 的 SRC 只能是本地文件,其他用法一致。 8. 解释一下 Dockerfile 的 ONBUILD 指令? 当镜像用作另一个镜像构建的基础时,ONBUILD 指令向镜像添加将在稍后执行的触发指令。如果要构建将用作构建其他镜像的基础的镜像(例如,可以使用特定于用户的配置自定义的应用程序构建环境或守护程序),这将非常有用。
聊聊:docker常用命令?
- docker pull 拉取或者更新指定镜像
- docker push 将镜像推送至远程仓库
- docker rm 删除容器
- docker rmi 删除镜像
- docker images 列出所有镜像
- docker ps 列出所有容器
1、如何列出可运行的容器?
docker ps
2、启动nginx容器(随机端口映射),并挂载本地文件目录到容器html的命令是?
docker run -d -P --name nginx2 -v /home/nginx:/usr/share/nginx/html nginx
3、进入容器的方法有哪些?
1、使用 docker attach 命令
2、使用 exec 命令,例如docker exec -i -t 784fd3b294d7 /bin/bash
4、容器与主机之间的数据拷贝命令是?
docker cp 命令用于容器与主机之间的数据拷贝
主机到容器:
docker cp /www 96f7f14e99ab:/www/
容器到主机:
docker cp 96f7f14e99ab:/www /tmp/
5、当启动容器的时候提示:exec format error?如何解决问题
检查启动命令是否有可执行权限,进入容器手工运行脚本进行排查。
6、本地的镜像文件都存放在哪里?
与 Docker 相关的本地资源都存放在/var/lib/docker/目录下,其中 container 目录存放容器信息,graph 目录存放镜像信息,aufs 目录下存放具体的内容文件。
7、如何退出一个镜像的 bash,而不终止它?
按 Ctrl-p Ctrl-q。
8、退出容器时候自动删除?
使用 –rm 选项,例如 sudo docker run –rm -it ubuntu
9、如何批量清理临时镜像文件?
可以使用 sudo docker rmi $(sudo docker images -q -f danging=true)命令
10、如何查看镜像支持的环境变量?
使用 sudo docker run IMAGE env
11、本地的镜像文件都存放在哪里
于 Docker 相关的本地资源存放在/var/lib/docker/目录下,其中 container 目录
存放容器信息,graph 目录存放镜像信息,aufs 目录下存放具体的镜像底层文件。
12、容器退出后,通过 docker ps 命令查看不到,数据会丢失么?
容器退出后会处于终止(exited)状态,此时可以通过 docker ps -a 查看,其中数据不会丢失,还可以通过 docker start 来启动,只有删除容器才会清除数据。
13、如何停止所有正在运行的容器?
使用 docker kill $(sudo docker ps -q)
14、如何清理批量后台停止的容器?
答:使用 docker rm $(sudo docker ps -a -q)
15、如何临时退出一个正在交互的容器的终端,而不终止它?
按 Ctrl+p,后按 Ctrl+q,如果按 Ctrl+c 会使容器内的应用进程终止,进而会使容器终止。
说说: Dockerfile的基本指令有哪些?
FROM 指定基础镜像(必须为第一个指令,因为需要指定使用哪个基础镜像来构建镜像);
MAINTAINER 设置镜像作者相关信息,如作者名字,日期,邮件,联系方式等;
COPY 复制文件到镜像;
ADD 复制文件到镜像(ADD与COPY的区别在于,ADD会自动解压tar、zip、tgz、xz等归档文件,而COPY不会,同时ADD指令还可以接一个url下载文件地址,一般建议使用COPY复制文件即可,文件在宿主机上是什么样子复制到镜像里面就是什么样子这样比较好);
ENV 设置环境变量;
EXPOSE 暴露容器进程的端口,仅仅是提示别人容器使用的哪个端口,没有过多作用;
VOLUME 数据卷持久化,挂载一个目录;
WORKDIR 设置工作目录,如果目录不在,则会自动创建目录;
RUN 在容器中运行命令,RUN指令会创建新的镜像层,RUN指令经常被用于安装软件包;
CMD 指定容器启动时默认运行哪些命令,如果有多个CMD,则只有最后一个生效,另外,CMD指令可以被docker run之后的参数替换;
ENTRYOINT 指定容器启动时运行哪些命令,如果有多个ENTRYOINT,则只有最后一个生效,另外,如果Dockerfile中同时存在CMD和ENTRYOINT,那么CMD或docker run之后的参数将被当做参数传递给ENTRYOINT;
说说: 如何进入容器?使用哪个命令
进入容器有两种方法:docker attach、docker exec;
docker attach命令是attach到容器启动命令的终端,docker exec 是另外在容器里面启动一个TTY终端。
docker run -d centos /bin/bash -c "while true;do sleep 2;echo I_am_a_container;done"
3274412d88ca4f1d1292f6d28d46f39c14c733da5a4085c11c6a854d30d1cde0
docker attach 3274412d88ca4f #attach进入容器
Ctrl + c 退出,Ctrl + c会直接关闭容器终端,这样容器没有进程一直在前台运行就会死掉了
Ctrl + pq 退出(不会关闭容器终端停止容器,仅退出)docker exec -it 3274412d88ca /bin/bash #exec进入容器
[root@3274412d88ca /]# ps -ef #进入到容器了开启了一个bash进程
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 05:31 ? 00:00:01 /bin/bash -c while true;do sleep 2;echo I_am_a_container;done
root 306 0 1 05:41 pts/0 00:00:00 /bin/bash
root 322 1 0 05:41 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 2
root 323 306 0 05:41 pts/0 00:00:00 ps -ef
[root@3274412d88ca /]#exit #退出容器,仅退出我们自己的bash窗口
小结:
attach是直接进入容器启动命令的终端,不会启动新的进程;
exec则是在容器里面打开新的终端,会启动新的进程;一般建议已经exec进入容器。
聊聊:什么是 Docker Swarm?
Docker Swarm 是 Docker 的本机群集。它将 Docker 主机池转变为单个虚拟Docker 主机。Docker Swarm 提供标准的 Docker API,任何已经与 Docker守护进程通信的工具都可以使用 Swarm 透明地扩展到多个主机。
聊聊:容器内部机制?
每个容器都在自己的命名空间中运行,但使用与所有其他容器完全相同的内核。发生隔离是因为内核知道分配给进程的命名空间,并且在API调用期间确保进程只能访问其自己的命名空间中的资源。
聊聊:什么是Docker Hub?
Docker hub是一个基于云的注册表服务,允许您链接到代码存储库,构建镜像并测试它们,存储手动推送的镜像以及指向Docker云的链接,以便您可以将镜像部署到主机。它为整个开发流程中的容器镜像发现,分发和变更管理,用户和团队协作以及工作流自动化提供了集中资源。
聊聊:镜像与 UnionFS
Linux 的命名空间和控制组分别解决了不同资源隔离的问题,前者解决了进程、网络以及文件系统的隔离,后者实现了 CPU、内存等资源的隔离,但是在 Docker 中还有另一个非常重要的问题需要解决 - 也就是镜像。
Docker 镜像其实本质就是一个压缩包,我们可以使用命令将一个 Docker 镜像中的文件导出,你可以看到这个镜像中的目录结构与 Linux 操作系统的根目录中的内容并没有太多的区别,可以说 Docker 镜像就是一个文件。
存储驱动
Docker 使用了一系列不同的存储驱动管理镜像内的文件系统并运行容器,这些存储驱动与
Docker 卷(volume)有些不同,存储引擎管理着能够在多个容器之间共享的存储。
聊聊:docker容器之间怎么隔离?
Linux中的PID、IPC、网络等资源是全局的,而NameSpace机制是一种资源隔离方案,在该机制下这些资源就不再是全局的了,而是属于某个特定的NameSpace,各个NameSpace下的资源互不干扰。
虽然有了NameSpace技术可以实现资源隔离,但进程还是可以不受控的访问系统资源,比如CPU、内存、磁盘、网络等,为了控制容器中进程对资源的访问,Docker采用control groups技术(也就是cgroup),有了cgroup就可以控制容器中进程对系统资源的消耗了,比如你可以限制某个容器使用内存的上限、可以在哪些CPU上运行等等。
有了这两项技术,容器看起来就真的像是独立的操作系统了。
聊聊:仓库( Repository)、 注册服务器( Registry)、 注册索引( Index)有何关系?
仓库是存放一组关联镜像的集合,比如同一个应用的不同版本的镜像。注册服务器是存放实际的镜像文件的地方。注册索引则负责维护用户的账号、权限、搜索、标签等的管理。因此,注册服务器利用注册索引来实现认证等管理。
聊聊:如何在生产中监控 Docker?
Docker 提供 docker stats 和 docker 事件等工具来监控生产中的 Docker。
我们可以使用这些命令获取重要统计数据的报告。
Docker 统计数据:当我们使用容器 ID 调用 docker stats 时,我们获得容器的CPU,内存使用情况等。它类似于 Linux 中的 top 命令。
Docker 事件:Docker 事件是一个命令,用于查看 Docker 守护程序中正在进行的活动流。 一些常见的 Docker 事件:attach,commit,die,detach,rename,destroy 等。我们还可以使用各种选项来限制或过滤我们感兴趣的事件。
聊聊:如何在多个环境中使用Docker?
可以进行以下更改:
- 删除应用程序代码的任何卷绑定,以便代码保留在容器内,不能从外部更改
- 绑定到主机上的不同端口
- 以不同方式设置环境变量(例如,减少日志记录的详细程度,或启用电子邮件发送)
- 指定重启策略(例如,重启:始终)以避免停机
- 添加额外服务(例如,日志聚合器)
因此,您可能希望定义一个额外的Compose文件,例如production.yml,它指定适合生产的配置。此配置文件只需要包含您要从原始Compose文件中进行的更改。
聊聊:Docker能在非Linux平台(比如 macOS
或 Windows
)上运行么?
可以。
macOS目前需要使用 docker for mac等软件创建一个轻量级的Linux虚拟机层。 由于成熟度不高,暂时不推荐在Windows环境中使用Docker。
说说: centos镜像几个G,但是docker centos镜像才几百兆,这是为什么?
一个完整的Linux操作系统包含Linux内核和rootfs根文件系统,即我们熟悉的/dev、/proc/、/bin等目录。
我们平时看到的centOS除了rootfs,还会选装很多软件,服务,图形桌面等,所以centOS镜像有好几个G也不足为奇。
而对于容器镜像而言,所有容器都是共享宿主机的Linux 内核的,
而对于docker镜像而言,docker镜像只需要提供一个很小的rootfs根文件系统即可,只需要包含即我们熟悉的/dev、/proc/、/bin等目录,这是最基本的命令,工具,程序库即可,
所以,docker镜像才会这么小。
说说: 镜像的分层结构以及为什么要使用镜像的分层结构?
一个新的镜像其实是从 base 镜像一层一层叠加生成的。
每安装一个软件,dockerfile中使用RUM命令,就会在现有镜像的基础上增加一层,这样一层一层的叠加最后构成整个镜像。
所以我们docker pull拉取一个镜像的时候会看到docker是一层层拉去的。
分层机构最大的一个好处就是 : 共享资源。
比如:有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
说说: 容器的copy-on-write特性,修改容器里面的内容会修改镜像吗?
我们知道,镜像是分层的,镜像的每一层都可以被共享,同时,镜像是只读的。
当一个容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
实际上,docker hub中99%的镜像都是通过在base镜像中安装和配置需要的软件构建出来的
新的镜像是从base镜像一层一层叠加生成的,每安装一个软件,就在现有的基础增加一层
为什么docker镜像要采用这种分层结构呢?
最大的一个好处是:共享资源
比如:有多个镜像都从相同的base镜像构建而来,那么docker host只需在磁盘上保存一份base镜像: 同时内存中也只需加载一份base镜像,就可以为所有容器服务了,而其镜像的每一层都可以被共享
问题是: 如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如/etc下的文件,这时其他容器的/etc是否也会被修改??? 答案是不会
修改会被限制在单个容器内, 这就是 容器copy-on-write特性
所有对容器的改动 - 无论添加、删除、还是修改文件,都只会发生在容器层中,
因为只有容器层是可写的,容器层下面的所有镜像层都是只读的。
镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。
如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。
在容器层中,用户看到的是一个叠加之后的文件系统。
添加文件时:在容器中创建文件时,新文件被添加到容器层中。
读取文件:在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后打开并读入内存。
修改文件:在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
删除文件:在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。
说说: Dockerfile的整个构建镜像过程
1、首先,创建一个目录用于存放应用程序以及构建过程中使用到的各个文件等;
2、然后,在这个目录下创建一个Dockerfile文件,一般建议Dockerfile的文件名就是Dockerfile;
3、编写Dockerfile文件,编写指令,如,使用FORM指令指定基础镜像,COPY指令复制文件,RUN指令指定要运行的命令,ENV设置环境变量,EXPOSE指定容器要暴露的端口,WORKDIR设置当前工作目录,CMD容器启动时运行命令,等等指令构建镜像;
4、Dockerfile编写完成就可以构建镜像了,使用docker build -t 镜像名:tag .
命令来构建镜像,最后一个点是表示当前目录,docker会默认寻找当前目录下的Dockerfile文件来构建镜像,如果不使用默认,可以使用-f参数来指定dockerfile文件,如:docker build -t 镜像名:tag -f /xx/xxx/Dockerfile
;
5、使用docker build命令构建之后,docker就会将当前目录下所有的文件发送给docker daemon,顺序执行Dockerfile文件里的指令,在这过程中会生成临时容器,在临时容器里面安装RUN指定的命令,安装成功后,docker底层会使用类似于docker commit命令来将容器保存为镜像,然后删除临时容器,以此类推,一层层的构建镜像,运行临时容器安装软件,直到最后的镜像构建成功。
说说: Dockerfile构建镜像出现异常,如何排查?
首先,Dockerfile是一层一层的构建镜像,期间会产生一个或多个临时容器,构建过程中其实就是在临时容器里面安装应用,如果因为临时容器安装应用出现异常导致镜像构建失败,这时容器虽然被清理掉了,但是期间构建的中间镜像还在,那么我们可以根据异常时上一层已经构建好的临时镜像,将临时镜像运行为容器,然后在容器里面运行安装命令来定位具体的异常。
相关文章:
docker简介-学习与参考
docker Docker 是一个开源的应用容器引擎,基于 Go 语言并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。 容器是完全使用沙箱…...
3dtiles平移旋转工具制作
3dtiles平移旋转缩放原理及可视化工具实现 背景 平时工作中,通过cesium平台来搭建一个演示场景是很常见的事情。一般来说,演示场景不需要多完善的功能,但是需要一批三维模型搭建,如厂房、电力设备、园区等。在实际搭建过程中&…...
【第十节】C++设计模式(结构型模式)-Flyweight( 享元)模式
目录 一、问题背景 二、模式选择 三、代码实现 四、总结讨论 一、问题背景 享元模式(Flyweight Pattern)在对象存储优化中的应用 在面向对象系统的设计与实现中,创建对象是最常见的操作之一。然而,如果一个应用程序使用了过多…...
VScode在windows10上使用clang-format
用途:自动调整代码格式,如缩进等。 clang-format官方文档:ClangFormat — Clang 21.0.0git documentation 前提:有一个.clang-format文件 下载LLVM:https://github.com/llvm/llvm-project/releases,将可…...
青少年编程与数学 02-010 C++程序设计基础 11课题、程序结构
青少年编程与数学 02-010 C程序设计基础 11课题、程序结构 一、C程序结构二、main函数1. main 函数的基本形式1.1 无参数形式1.2 带参数形式 2. 参数解释3. 示例3.1 无参数形式3.2 带参数形式 4. 编译和运行4.1 编译4.2 运行 5. main 函数的返回值6. 总结 三、预处理指令1. #in…...
Node.js与MySQL的深入探讨
Node.js与MySQL的深入探讨 引言 Node.js,一个基于Chrome V8引擎的JavaScript运行时环境,以其非阻塞、事件驱动的方式在服务器端应用中占据了一席之地。MySQL,作为一款广泛使用的开源关系型数据库管理系统,凭借其稳定性和高效性,成为了许多应用的数据库选择。本文将深入探…...
【洛谷贪心算法题】P2240部分背包问题
【解题思路】 贪心策略选择 对于部分背包问题,关键在于如何选择物品放入背包以达到最大价值。由于物品可以分割,遍历排序后的物品数组,根据物品重量和背包剩余容量的关系,决定是将整个物品放入背包还是分割物品放入背包ÿ…...
ArcGIS Pro技巧实战:高效矢量化天地图地表覆盖图
在地理信息系统(GIS)领域,地表覆盖图的矢量化是一项至关重要的任务。天地图作为中国国家级的地理信息服务平台,提供了丰富且详尽的地表覆盖数据。然而,这些数据通常以栅格格式存在,不利于进行空间分析和数据…...
AF3 pair_sequences函数解读
AlphaFold3 msa_pairing模块的pair_sequences函数的核心目标是基于 MSA(多序列比对)中的物种信息,在多条链之间建立 MSA 配对索引,从而帮助 AlphaFold3 捕捉共进化信息,提升蛋白复合物预测的准确性。函数pair_sequences 通过调用 _make_msa_df、 _create_species_dict 以…...
在VSCode 中使用通义灵码最新版详细教程
在 VSCode 中使用通义灵码:最新版详细教程与使用场景 Visual Studio Code(简称 VSCode)是一款由微软开发的轻量级、功能强大的开源代码编辑器,支持多种编程语言,深受开发者喜爱。而通义灵码(TONGYI Lingma…...
ssh和rdp踩坑
ssh和rdp(远程桌面)踩坑 使用微软账号登录windows的话,ssh的用户名是本地用户名(就是c盘用户文件夹下的用户名),rdp的用户名是微软账号用户名,但是密码都是微软账号的密码,跟登录密…...
Linux驱动学习(四)--字符设备注册
上一节讲到的字符设备注册与销毁是通过cdev_init、cdev_add、cdev_del等函数分步执行的,本小节用一种更简单的方式,来注册字符设备 register_chrdev 如果major为0,该函数将动态的分配一个主设备号并且返回对应的值如果major > 0ÿ…...
vue3 下载文件 responseType-blob 或者 a标签
在 Vue 3 中,你可以使用 axios 或 fetch 来下载文件,并将 responseType 设置为 blob 以处理二进制数据。以下是一个使用 axios 的示例: 使用 axios 下载文件 首先,确保你已经安装了 axios: npm install axios然后在你…...
Meta最新研究:从单张照片到3D数字人的革命性突破
随着人工智能技术的发展,3D建模和虚拟人物生成逐渐变得更加普及和高效。Meta(前身为Facebook)的最新研究成果展示了如何仅通过一张普通手机拍摄的照片就能生成高质量、全方位的3D数字人。这项技术不仅适用于虚拟试衣、游戏角色建模,还能广泛应用于AR/VR内容生成等领域。本文…...
大中型虚拟化园区网络设计
《大中型虚拟化园区网络设计》属于博主的“园区网”专栏,若想成为HCIE,对于园区网相关的知识需要非常了解,更多关于园区网的内容博主会更新在“园区网”专栏里,请持续关注! 一.前言 华为云园区网络解决方案(简称Cloud…...
Vue 项目中配置代理的必要性与实现指南
Vue 项目中配置代理的必要性与实现指南 在 Vue 前端项目的开发过程中,前端与后端地址通常不同,可能引发跨域问题。为了在开发环境下顺畅地请求后端接口,常常会通过配置**代理(proxy)**来解决问题。这篇文章将详细解析…...
chromadb向量数据库使用 (1)
目录 完整代码代码解释 完整代码 import chromadb chroma_client chromadb.Client()collection chroma_client.create_collection(name"my_collection")collection.add(documents["This is a document about pineapple","This is a document about…...
玩机日记 12 fnOS使用lucky反代https转发到外网提供服务
目录 1、安装lucky 2、更新lucky 3、上传ssl证书 4、设置安全入口,替换fnOS的应用url 5、添加https反代 这一篇主要是解决一下飞牛反代https的问题。可以先看玩机日记 12.5 在PVE Windows11上部署本地AI模型,使用群晖反代https转发到外网提供服务&a…...
5分钟学会SpringAI
引言 要开发一个Spring AI的入门案例,我们可以从一个简单的Spring Boot项目开始,然后集成Spring AI的功能来实现基本的生成式AI任务。下面是一个步骤指南,帮助你快速启动并运行一个简单的Spring AI应用。 步骤 1: 准备环境 首先࿰…...
专业的UML开发工具StarUML
专业的UML开发工具StarUML 可靠的软件建模软件StarUML StarUML 是一款支持统一建模语言 (UML)框架的开源建模软件。它提供了几种类型的图表,并允许用户生成多种语言的代码。在它的帮助下,软件开发人员可以创建设计、概念和编码解决方案。但是࿰…...
go语言环境下载与配置(Windows)
下载 Go下载 - Go语言中文网 - Golang中文社区 建议在D盘中创建文件夹安装到 D 盘 ,方便进行管理,然后进行傻瓜式安装。 安装 验证安装 go version 安装成功 配置环境变量 winE --> 右击此电脑 --> 选择属性 --> 高级系统设置 --> 点击…...
矩阵系列 题解
1.洛谷 P1962 斐波那契数列 题意 大家都知道,斐波那契数列是满足如下性质的一个数列: F n { 1 ( n ≤ 2 ) F n − 1 F n − 2 ( n ≥ 3 ) F_n \left\{\begin{aligned} 1 \space (n \le 2) \\ F_{n-1}F_{n-2} \space (n\ge 3) \end{aligned}\right. …...
C++ 正则表达式分组捕获入门指南
在 C 中,正则表达式(regex)是一种用于匹配字符串模式的强大工具。正则表达式不仅能帮助你查找符合特定模式的字符,还能捕获匹配的子字符串(即分组捕获)。这篇文章将介绍 C 正则表达式中的分组捕获机制&…...
动态数据表格:基于 PrimeFaces 的运行时列选择实现
在现代的 Web 应用开发中,动态数据表格是一个非常实用的功能,它允许用户根据自己的需求选择显示哪些列。这种灵活性不仅提升了用户体验,还能适应不同的数据展示需求。今天,我们将通过一个具体的实现案例,展示如何使用 …...
Plugin ‘mysql_native_password‘ is not loaded`
Plugin ‘mysql_native_password’ is not loaded mysql_native_password介绍1. 使用默认的认证插件2. 修改 my.cnf 或 my.ini 配置文件3. 加载插件(如果确实没有加载)4. 重新安装或检查 MySQL 版本 遇到错误 ERROR 1524 (HY000): Plugin mysql_nativ…...
Kotlin 知识点二 延迟初始化和密封类
对变量延迟初始化 Kotlin 语言的许多特性,包括变量不可变,变量不可为空,等等。这些特性 都是为了尽可能地保证程序安全而设计的,但是有些时候这些特性也会在编码时给我们带来不 少的麻烦。 比如,如果你的类中存在很多…...
DeepSeek开源周第二弹:DeepEP如何用RDMA+FP8让MoE模型飞起来?
一、引言:MoE模型的通信瓶颈与DeepEP的诞生 在混合专家(MoE)模型训练中,专家间的全对全(All-to-All)通信成为性能瓶颈。传统方案在跨节点传输时带宽利用率不足50%,延迟高达300μs以上。DeepSee…...
C++ Primer 成员访问运算符
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
无人机遥控器的亮度 和 两个工作频率
工作频率 2.4000-2.4835 GHz , 5.725-5.850 GHz 1.这是一个无人机的遥控器的两个工作频率,为什么会有两个工作频率? 无人机的遥控器采用双频段设计(2.4GHz 和 5.8GHz),主要是为了解决以下问题并优化性…...
ubuntu20.04安装docker
3台主机,2台都能正确安装,第三台怎么都安装不成功; 3台主机都是一样的配置和系统; 后来看来是其外网的ip不一样,导致第三台主机可能被Qiang,不过错误只是提示签名不正确,在设置签名时好像没有…...
【含文档+PPT+源码】基于过滤协同算法的旅游推荐管理系统设计与实现
项目介绍 本课程演示的是一款基于过滤协同算法的旅游推荐管理系统设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系…...
深入解析Crawl4AI:为AI应用量身定制的高效开源爬虫框架
引言 在当今数据驱动的时代,人工智能(AI)和大型语言模型(LLM)的发展对高质量数据的需求日益增长。如何高效地从互联网上获取、处理和提取有价值的数据,成为了研究人员和开发者面临的关键挑战。Crawl4AI作为…...
《Effective Objective-C》阅读笔记(下)
目录 内存管理 理解引用计数 引用计数工作原理 自动释放池 保留环 以ARC简化引用计数 使用ARC时必须遵循的方法命名规则 变量的内存管理语义 ARC如何清理实例变量 在dealloc方法中只释放引用并解除监听 编写“异常安全代码”时留意内存管理问题 以弱引用避免保留环 …...
深度生成模型(二)——基本概念与数学建模
上一篇笔记中提到了端到端模型底层核心采用了深度生成模型,先简单梳理一下 生成式人工智能(Artificial Intelligence Generated Content,AIGC)经历了从早期基于概率模型和规则系统的方法到现代深度生成模型的跨越式发展 深度神经…...
4.WebSocket 配置与Nginx 的完美结合
序言 在现代 web 应用中,WebSocket 作为一种全双工通信协议,为实时数据传输提供了强大的支持。若要确保 WebSocket 在生产环境中的稳定性和性能,使用 Nginx 作为反向代理服务器是一个明智的选择。本篇文章将带你了解如何在 Nginx 中配置 Web…...
【R语言】dplyr包经典函数summarise函数
dplyr包经典函数summarise函数,后面改名乘reframe函数了,但是summarise仍然适用 这个函数的返回结果是一个新的数据框,下面讲一下几种常见用法 示例数据为R自带的数据集mtcars 1.不分组 mtcars %>%summarise(mean mean(disp), n n()…...
Cuppa CMS v1.0 任意文件读取(CVE-2022-25401)
漏洞简介: Cuppa CMS v1.0 administrator/templates/default/html/windows/right.php文件存在任意文件读取漏洞 漏洞环境: 春秋云镜中的漏洞靶标,CVE编号为CVE-2022-25401 漏洞复现 弱口令行不通 直接访问administrator/templates/defau…...
8.Dashboard的导入导出
分享自己的Dashboard 1. 在Dashboard settings中选择 JSON Model 2. 导入 后续请参考第三篇导入光放Dashboard,相近...
RabbitMQ 的介绍与使用
一. 简介 1> 什么是MQ 消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已。 其主要用途:不同进程Process/线程T…...
unity学习58:下拉列表框 dropdown的caption和options
目录 1 下拉列表框 dropdown 1.1 创建dropdown 1.2 dropdown的子物体构成 1.3 drop的子物体构成:默认灰色的模板 template 1.3.1 默认灰色的模板 template 实际是生效的,只是不直接显示 1.3.2 其中 item下面是下拉选项的格式 1.3.3 可以修改和新增 1.4 drop…...
STM32中使用PWM对舵机控制
目录 1、硬件JIE 2、PWM口配置 3、角度转换 4、main函数中应用 5、工程下载连接 1、硬件介绍 单片机:STM32F1 舵机:MG995 2、PWM口配置 20毫秒的PWM脉冲占空比,对舵机控制效果较好 计算的公式: PSC、ARR值的选取…...
如何免费使用稳定的deepseek
0、背景: 在AI辅助工作中,除了使用cursor做编程外,使用deepseek R1进行问题分析、数据分析、代码分析效果非常好。现在我经常会去拿行业信息、遇到的问题等去咨询R1,也给了自己不少启示。但是由于官网稳定性很差,很多…...
STM32内存五区及堆栈空间大小设置(启动文件浅析)
前言 嘿,朋友们!今天咱们来聊聊STM32的内存五区和堆栈空间大小设置。这可是嵌入式开发里的“必修课”,要是没整明白,程序说不定就“翻车”了。别担心,我这就带你一步步搞懂这事儿,让你轻松上手,…...
LVS+Keepalived高可用群集配置案例
以下是一个 LVSKeepalived 高可用群集配置案例: 1、环境准备 LVS 主调度器(lvs1):IP 地址为 192.168.8.101,心跳 IP 为 192.168.4.101LVS 备调度器(lvs2):IP 地址为 192.168.8.102…...
MySQL 中如何解决深度分页的问题? MySQL中 join、inner join、left join、right join区别
MySQL 中如何解决深度分页的问题? 在 MySQL 中解决深度分页问题的核心思路是减少扫描的数据量,尤其是避免通过 LIMIT offset, size 导致的大范围数据扫描。以下是三种优化方法及其原理、适用场景和注意事项: 1. 子查询 覆盖索引(…...
本地部署DeepSeek-R1(Ollama+Docker+OpenWebUI知识库)
安装Ollama 打开 Ollama官网 https://ollama.com/下载安装 Ollama服务默认只允许本机访问,修改允许其它主机访问 OLLAMA_HOST0.0.0.0 ollama serve也可以添加系统环境变量 都知道模型体积很大,顺便也通过环境变量修改模型存放位置,我这…...
ubuntu22.04安装docker engine
在Ubuntu 22.04上安装Docker Engine可以通过以下步骤完成: 更新系统包索引: sudo apt update安装必要的依赖包: 这些包允许apt通过HTTPS使用仓库。 sudo apt install -y apt-transport-https ca-certificates curl software-properties-commo…...
Protobuf原理与序列化
本文目录 1. Protobuf介绍2. Protobuf的优势3. 编写Protobuf头部全局定义消息结构具体定义字段类型定义标签号Base128编码 4. TLVProtobuf的TLV编码如何通过Varint表示300? 5. 编译Protobuf6. 构造消息对象 前言:之前写项目的时候只是简单用了下Protobuf…...
Redis|事务
文章目录 是什么能干嘛Redis 事务 VS 数据库事务怎么玩小总结 是什么 首先回想一下什么是数据库的事务?数据库事务是指作为单个逻辑单元执行的一系列操作,具备以下四个关键特性(ACID): 原子性(Atomicity&am…...
树莓百度百科更新!宜宾园区业务再添新篇
树莓集团宜宾园区业务不断拓展,主要体现在以下几个方面: 产业布局 -聚焦数字经济核心领域:涵盖软件开发、人工智能、大数据等,吸引众多上下游企业入驻,形成从芯片研发、软件开发到系统集成的完整产业链条。 -推进“双…...