Docker
什么是容器
- 容器技术是一种虚拟化的方案
- 传统虚拟机是通过中间层,将一台或多台独立的机器虚拟运行在硬件之上
- 而容器时直接运行在系统内核之上的用户空间
- 因此,容器虚拟化也被称为操作系统虚拟化
- 由于运行在操作系统上,所以容器只能运行相同或相似内核的操作系统
容器和传统虚拟化的区别
传统虚拟化:通过虚拟化技术模拟真实的硬件从而创建出来的一台拥有完整功能的逻辑计算机。
Docker容器:Docker容器也是一种虚拟化技术,和传统虚拟化不一样的是Docker只模拟一个程序最核心的运行环境,所以十分小巧,启动更快。
虚拟化分为以下两类:
- 主机级虚拟化
- 全虚拟化
- 半虚拟化
- 容器级虚拟化
容器分离开的资源:
- UTS(主机名与域名)
- Mount(文件系统挂载树)
- IPC
- PID进程树
- User
- Network(tcp/ip协议栈)
Docker虚拟化技术和传统虚拟化技术架构对比:
对比 | 特点 |
---|---|
虚拟机 | 完整的系统功能,隔离性更好,占用空间大(通常以G为单位) 运行占用资源较多,启动慢(分钟级启动) |
容器 | 只有程序运行的核心环境,不需要安装直接运行镜像即可 隔离性一般,十分小巧占用空间极小(一般以M为单位),启动快(秒级启动) |
Linux Namespaces
命名空间(Namespaces)是Linux内核针对实现容器虚拟化而引入的一个强大特性。
每个容器都可以拥有自己独立的命名空间,运行其中的应用都像是在独立的操作系统中运行一样。命名空间保证了容器间彼此互不影响。
namespaces | 系统调用参数 | 隔离内容 | 内核版本 |
---|---|---|---|
UTS | CLONE_NEWUTS | 主机名和域名 | 2.6.19 |
IPC | CLONE_NEWIPC | 信号量、消息队列和共享内存 | 2.6.19 |
PID | CLONE_NEWPID | 进程编号 | 2.6.24 |
Network | CLONE_NEWNET | 网络设备、网络栈、端口等 | 2.6.29 |
Mount | CLONE_NEWNS | 挂载点(文件系统) | 2.4.19 |
User | CLONE_NEWUSER | 用户和用户组 | 3.8 |
CGroups
控制组(CGroups)是Linux内核的一个特性,用来对共享资源进行隔离、限制、审计等。只有能控制分配到容器的资源,Docker才能避免多个容器同时运行时的系统资源竞争。
控制组可以提供对容器的内存、CPU、磁盘IO等资源进行限制。
CGroups能够限制的资源有:
- blkio:块设备IO
- cpu:CPU
- cpuacct:CPU资源使用报告
- cpuset:多处理器平台上的CPU集合
- devices:设备访问
- freezer:挂起或恢复任务
- memory:内存用量及报告
- perf_event:对cgroup中的任务进行统一性能测试
- net_cls:cgroup中的任务创建的数据报文的类别标识符
具体来看,控制组提供如下功能:
- 资源限制(Resource Limitting)组可以设置为不超过设定的内存限制。比如:内存子系统可以为进行组设定一个内存使用上限,一旦进程组使用的内存达到限额再申请内存,就会发出Out of Memory警告
- 优先级(Prioritization)通过优先级让一些组优先得到更多的CPU等资源
- 资源审计(Accounting)用来统计系统实际上把多少资源用到合适的目的上,可以使用cpuacct子系统记录某个进程组使用的CPU时间
- 隔离(Isolation)为组隔离命名空间,这样一个组不会看到另一个组的进程、网络连接和文件系统
- 控制(Control)挂起、恢复和重启等操作
安装Docker后,用户可以在/sys/fs/cgroup/memory/docker/
目录下看到对Docker组应用的各种限制项,包括
[root@localhost ~]# cd /sys/fs/cgroup/memory/
[root@localhost memory]# ls
cgroup.clone_children memory.kmem.slabinfo memory.memsw.limit_in_bytes memory.swappiness
cgroup.event_control memory.kmem.tcp.failcnt memory.memsw.max_usage_in_bytes memory.usage_in_bytes
cgroup.procs memory.kmem.tcp.limit_in_bytes memory.memsw.usage_in_bytes memory.use_hierarchy
cgroup.sane_behavior memory.kmem.tcp.max_usage_in_bytes memory.move_charge_at_immigrate notify_on_release
memory.failcnt memory.kmem.tcp.usage_in_bytes memory.numa_stat release_agent
memory.force_empty memory.kmem.usage_in_bytes memory.oom_control system.slice
memory.kmem.failcnt memory.limit_in_bytes memory.pressure_level tasks
memory.kmem.limit_in_bytes memory.max_usage_in_bytes memory.soft_limit_in_bytes user.slice
memory.kmem.max_usage_in_bytes memory.memsw.failcnt memory.stat
什么是Docker
- Docker是容器技术的一个前端工具,容器是内核的一项技术,Docker只是把这一项技术的使用得以简化,使之普及而已
- Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
- Docker是通过内核虚拟化技术(namespaces(命令空间)及cgroups(控制组)等)来提供容器的资源隔离与安全保障等,由于Docker通过操作系统层的虚拟化实现隔离,所以Docker容器在运行时,不需要虚拟机(VM)额外的操作系统开销,提高资源利用率。
注:此内核是linux内核
Docker官网:https://www.docker.com/
Docker解决什么问题
- 要想使用LXC管理容器,要学习很对LXC工具。LXC命令列表
- 必要时要定制模板
- 每一个名称空间都是安装生成的,在该名称空间中运行的进程会生成一些文件(数据库之类的),当该宿主故障时,如何迁移到其他宿主机上
- 批量创建较困难
总结起来就是通过LXC管理容器比起传统虚拟化的虚拟机的使用复杂度没有多大降低,更何况隔离性也没有虚拟机那么好。当然了好处在于每个容器中的进行都可以直接使用宿主机的性能,中间没有额外开销(节约资源)。LXC在分发和大规模使用上没有很好的方法。于是后来就出现了Docker,早期的Docker可以看作为是LXC的增强版(主要解决分发和大规模使用)。
Docker本身不是容器,Docker只是容器的易用工具。容器是Linux内核的技术,Docker只是简化容器这种技术的使用。
Docker运行架构:
综上所述:LXC面临大规模使用和在其他的主机上复刻容器(分发)很难,于是Docker就在这方面着手解决。所以早期的Docker就是LXC的二次封装。功能上是通过LXC作为容器管理引擎,但是创建容器时,不在是用模板现场安装生成,而是事先通过一种叫做镜像的技术。把一个操作系统的用户空间用到了所有组件编排好,编排好以后整体打包成一个文件。这个文件就叫做镜像文件(Image)。使用Docker创建容器时,Docker不会激活LXC的模板创建安装。而是连接到镜像仓库,下载一个创建容器所需要的镜像。 Docker极大的简化了容器的使用,比如想要运行一个nginx 直接Docker run nginx 就行了。
每个容器本身可以运行一个多一组进程,Docker为了使容器的使用更加易于管理,采用在一个Docker容器中之运行一个进程。这样会带来一下好处和坏处。
好处:
- 每个容器只运行一个进程,多个进程走容器间通信(更加隔离性,更容器分发)
坏处:
- 所需要的存储空间增加了
- 调试容器中的进程比较困难
开发人员开发的好的程序只需要打包到一个Docker镜像中,便可以到处运行在拥有在Docker的机器上。一些特殊进程类似数据库这种,需要采用共享存储才可以更好的解决分发问题。通过将应用打包为镜像这种机制,可以很好的解决分发的问题。 在大规模使用场景上也是很简单的,在每个机器上只需要有一份镜像文件便可以启动N个示例。(具体参考Docker镜像,分层部署-联合挂载这一特性)
有了Docker的镜像机制后就可以很好的解决分发和大规模使用了。 当然想好用好容器还是要有容器编排工具的。
Docker底层技术
- 名称空间:Docker通过名称空间机制为容器提供隔离的工作空间。
- 控制组:Linux可以通过控制组设置进程使用CPU、内存和I/O资源的限额。Docker引擎正是依赖这种底层技术来限制容器使用的资源。
- 联合文件系统:可以将其他文件系统合并到一个联合挂载点。联合文件系统是实现Docker镜像的技术基础。Docker镜像可以通过分层来实现继承。
- 容器格式:Docker引擎将名称空间、控制组和联合文件系统打包到一起所使用的就是容器格式。默认的容器格式是Libcontainer。
Docker优势
- 应用程序快速、一致地交付
- 开发人员在本地编写应用程序代码,通过Docker与同事进行共享。
- 通过Docker将应用程序推送到测试环境中,执行自动测试和手动测试。
- 开发人员发现程序错误时,可以在开发环境中进行修复,然后重新部署到测试环境来进行测试和验证。
- 完成应用程序测试之后,向客户提供补丁程序非常简单,只需将更新后的镜像推送到生产环境中。
- 响应式部署和伸缩应用程序
- 更简单的系统运维
- 更高效的计算资源利用
Docker容器编排
- 能够把这种应用程序之间的依赖关系、从属关系、隶属关系等等反映在启动、关闭时的次序和管理逻辑中,这种功能被称为容器编排。
常见的容器编排工具:
- machine+swarm(把N个Docker主机当一个主机来管理)+compose(单机编排)
- mesos(实现统一资源调度和分配)+marathon
- kubernetes --> k8s
Docker部署
//配置docker源仓库
sudo curl -o /etc/yum.repos.d/docker-ce.repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
sudo sed -i 's@https://download.docker.com@https://mirrors.tuna.tsinghua.edu.cn/docker-ce@g' /etc/yum.repos.d/docker-ce.repo
//安装
sudo yum -y install docker-ce
//启动
sudo systemctl start docker
//docker 加速
sudo tee /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": ["https://j3m2itm3.mirror.aliyuncs.com"]
}
EOF
sudo systemctl restart docker
[root@localhost ~]# docker version
Client: Docker Engine - Community
Version: 20.10.11
API version: 1.41
Go version: go1.16.9
Git commit: dea9396
Built: Thu Nov 18 00:38:53 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.11
API version: 1.41 (minimum version 1.12)
Go version: go1.16.9
Git commit: 847da18
Built: Thu Nov 18 00:37:17 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.12
GitCommit: 7b11cfaabd73bb80907dd23182b9347b4245eb5d
runc:
Version: 1.0.2
GitCommit: v1.0.2-0-g52b36a2
docker-init:
Version: 0.19.0
GitCommit: de40ad0
[root@localhost ~]# docker info
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Build with BuildKit (Docker Inc., v0.6.3-docker)
scan: Docker Scan (Docker Inc., v0.9.0)
Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 20.10.11
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
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: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 7b11cfaabd73bb80907dd23182b9347b4245eb5d
runc version: v1.0.2-0-g52b36a2
init version: de40ad0
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-862.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 3.685GiB
Name: localhost.localdomain
ID: GCC5:3TCX:55W7:XVZK:RXJJ:BI5N:TN63:TUOD:IHYK:RZKV:RM7W:ERPI
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://j3m2itm3.mirror.aliyuncs.com/
Live Restore Enabled: false
Docker常用操作
命令 | 功能 |
---|---|
docker search | 在Docker 中心搜索镜像 |
docker pull | 从注册表中拉取镜像或存储库 |
docker images | 镜像列表 |
docker create | 创建一个新的容器 |
docker start | 启动一个或多个停止的容器 |
docker run | 在新容器中运行命令 |
docker ps | 列表容器 |
docker logs | 获取容器的日志 |
docker restart | 重启一个容器 |
docker stop | 停止一个或多个正在运行的容器 |
docker kill | 杀死一个或多个正在运行的容器 |
docker rm | 移除一个或多个容器 |
docker exec | 在正在运行的容器中运行命令 |
docker info | 显示整个系统的信息 |
docker attach | 连接到正在运行的容器(进入容器;前台运行,退出则容器停止) |
docker inspect | 返回Docker对象的低级信息(进入容器;退出容器不会停止) |
docker search
搜索镜像
[root@localhost ~]# docker search centos
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
centos The official build of CentOS. 6904 [OK]
ansible/centos7-ansible Ansible on Centos7 135 [OK]
consol/centos-xfce-vnc Centos container with "headless" VNC session… 131 [OK]
jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos - … 121 [OK]
centos/systemd systemd enabled base container. 105 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 92
imagine10255/centos6-lnmp-php56 centos6-lnmp-php56 58 [OK]
tutum/centos Simple CentOS docker image with SSH access 48
centos/postgresql-96-centos7 PostgreSQL is an advanced Object-Relational … 45
kinogmt/centos-ssh CentOS with SSH 29 [OK]
guyton/centos6 From official centos6 container with full up… 10 [OK]
centos/tools Docker image that has systems administration… 7 [OK]
drecom/centos-ruby centos ruby 6 [OK]
centos/redis Redis built for CentOS 6 [OK]
stephenlu/centos-ssh-root ssh from centos7 4 [OK]
mamohr/centos-java Oracle Java 8 Docker image based on Centos 7 3 [OK]
darksheer/centos Base Centos Image -- Updated hourly 3 [OK]
amd64/centos The official build of CentOS. 2
miko2u/centos6 CentOS6 日本語環境 2 [OK]
dokken/centos-7 CentOS 7 image for kitchen-dokken 2
blacklabelops/centos CentOS Base Image! Built and Updates Daily! 1 [OK]
mcnaughton/centos-base centos base image 1 [OK]
smartentry/centos centos with smartentry 0 [OK]
jelastic/centosvps An image of the CentOS Elastic VPS maintaine… 0
starlabio/centos-native-build Our CentOS image for native builds 0 [OK]
docker pull
下载镜像
[root@localhost ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
eff15d958d66: Pull complete
1e5351450a59: Pull complete
2df63e6ce2be: Pull complete
9171c7ae368c: Pull complete
020f975acd28: Pull complete
266f639b35ad: Pull complete
Digest: sha256:097c3a0913d7e3a5b01b6c685a60c03632fc7a2b50bc8e35bcaa3691d788226e
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
docker create
创建本地已有镜像的容器
[root@localhost ~]# docker create nginx
fe428c17ff8cb94a6240992d7e1a4f540a806f630d8fef336866573bbef234a7
创建本地没有镜像的容器
[root@localhost ~]# docker create httpd
Unable to find image 'httpd:latest' locally
latest: Pulling from library/httpd
eff15d958d66: Already exists
ba1caf8ba86c: Pull complete
ab86dc02235d: Pull complete
0d58b11d2867: Pull complete
e88da7cb925c: Pull complete
Digest: sha256:1d71eef54c08435c0be99877c408637f03112dc9f929fba3cccdd15896099b02
Status: Downloaded newer image for httpd:latest
aa20e785c44ffb1e1640607a28900c1053561e07da493d2005eed57140c1b22d
docker ps
查看本地容器进程
docker ps #查看容器运行状态
选项:
-a #显示所有的容器,包括未运行的
-q #只显示容器id
-l #显示最近创建的容器。
-f "筛选条件" #根据条件过滤显示的内容
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aa20e785c44f httpd "httpd-foreground" 16 seconds ago Created funny_burnell
fe428c17ff8c nginx "/docker-entrypoint.…" About a minute ago Created heuristic_chaplygin
CONTAINER ID #容器 ID
IMAGE #使用的镜像
COMMAND #启动容器时运行的命令
CREATED #容器的创建时间
STATUS #容器状态
状态有7种:
created(已创建)
restarting(重启中)
running(运行中)
removing(迁移中)
paused(暂停)
exited(停止)
dead(死亡)
PORTS #容器的端口信息和使用的连接类型(tcp\udp)。
NAMES #容器名称
docker images
查看本地镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest ad17c88403e2 12 days ago 143MB
nginx latest ea335eea17ab 2 weeks ago 141MB
docker run
容器启动
docker run 选项 容器 命令
选项:
--name #指定容器的名称,如果不指定随机给容器生成一个名称
-i #启动一个可交互容器,并持续打开标准输出
-t #表示使用终端关联到容器的标准输入输出上
-d #将容器放在后台执行
-rm #删除容器
-p 宿主机端口:容器端口 #将宿主机端口映射给容器端口
-v 宿主机目录:容器目录 #将宿主机目录挂载到容器中
//使用nginx镜像启动一个名为nginx01的容器
[root@loclhost ~]# docker run --name nginx01 nginx
//使用nginx镜像启动一个名为nginx02的容器并分配一个bash shell的终端进入容器
[root@localhost ~]# docker run --name nginx02 -it nginx /bin/bash
root@5915bc21b907:/# exit
exit
注意:
1.指定-it选项为容器分配shell后,启动容器时运行的命令将会被shell替代
2.不加-d选项的容器一旦使用exit退出容器shell,容器就终止运行;ctrl+p+q可以退出shell,容器仍将继续运行
//使用nginx镜像启动一个名为nginx03的容器并在后台运行
[root@localhost ~]# docker run --name nginx03 -d nginx
37a7a1bc3ab44f363f114c313ebabb12e0a55a5b3bad0bb650543de578119f7e
//查看在运行的容器状态
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
37a7a1bc3ab4 nginx "/docker-entrypoint.…" 47 seconds ago Up 47 seconds 80/tcp nginx03
//查看所有容器状态
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
37a7a1bc3ab4 nginx "/docker-entrypoint.…" 50 seconds ago Up 50 seconds 80/tcp nginx03
5915bc21b907 nginx "/docker-entrypoint.…" 2 minutes ago Exited (0) 2 minutes ago nginx02
c46cb5b402e3 nginx "/docker-entrypoint.…" 7 minutes ago Exited (0) 5 minutes ago nginx01
aa20e785c44f httpd "httpd-foreground" 20 minutes ago Created funny_burnell
fe428c17ff8c nginx "/docker-entrypoint.…" 21 minutes ago Created heuristic_chaplygin
//停止容器
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
37a7a1bc3ab4 nginx "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp nginx03
[root@localhost ~]# docker stop nginx03
nginx03
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
//启动容器
[root@localhost ~]# docker start nginx03
nginx03
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
37a7a1bc3ab4 nginx "/docker-entrypoint.…" 4 minutes ago Up 5 seconds 80/tcp nginx03
//删除容器
[root@localhost ~]# docker rm aa69d845c204
删除所有容器
[root@localhost ~]# docker rm $(docker ps -aq)
5915bc21b907
c46cb5b402e3
aa20e785c44f
fe428c17ff8c
docker exec
不进入容器执行容器中的命令
//不进入容器执行容器中的ls命令
[root@localhost ~]# docker exec nginx03 ls
bin
boot
....
//使用docker exec命令打开一个shell进入到容器中,使用exit退出shell,容器也不会终止运行
[root@localhost ~]# docker exec -it nginx03 /bin/bash
root@37a7a1bc3ab4:/# exit
exit
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
37a7a1bc3ab4 nginx "/docker-entrypoint.…" 15 minutes ago Up 10 seconds 80/tcp nginx03
docker inspect
查看容器详细信息
[root@localhost ~]# docker inspect nginx03
[
{
"Id": "37a7a1bc3ab44f363f114c313ebabb12e0a55a5b3bad0bb650543de578119f7e",
"Created": "2021-12-01T18:40:09.04151187Z",
"Path": "/docker-entrypoint.sh",
"Args": [
"nginx",
"-g",
"daemon off;"
],
....