传统虚拟机与docker的区别
传统虚拟机:完全型解耦
需要携带操作系统,在系统之上运行应用程序
调用资源繁琐:
例如内存调用:利用hypervisor虚拟化内存,整个过程需要 虚拟内存--虚拟物理内存--真正物理内存三步
docker:半解耦
不携带操作系统,轻巧
docker引擎分配资源 虚拟内存--真正物理内存
对比 传统虚拟机 docker
磁盘 几个或几十G 几十到几百M
CPU内存 虚拟系统占用过多 docker引擎几乎不占资源
启动速度 几分钟 几秒
安装管理 专门的管理运维 安装管理方便
应用部署 每次部署耗时 第二次开始极其方便
耦合性 多个服务互相干扰 一个服务一个容器,隔离
系统依赖 无 相同相似内核,推荐类Unix
Namespace(名称空间):
名字空间是Linux内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。
**IPC:** 共享内存、消息列队
**MNT:** 挂载点、文件系统
**NET:** 网络栈
**PID:** 进程编号
**USER:** 用户、组
**UTS:** 主机名、域名
pid 名字空间
不同用户的进程就是通过 pid 名字空间隔离开的,且不同名字空间中可以有相同 pid。所有的 LXC 进程在 Docker 中的父进程为Docker进程,每个 LXC 进程具有不同的名字空间。同时由于允许嵌套,因此可以很方便的实现嵌套的 Docker 容器。
net 名字空间
有了 pid 名字空间, 每个名字空间中的 pid 能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是通过 net 名字空间实现的, 每个 net 名字空间有独立的 网络设备, IP 地址, 路由表, /proc/net 目录。这样每个容器的网络就能隔离开来。Docker 默认采用 veth 的方式,将容器中的虚拟网卡同 host 上的一 个Docker 网桥 docker0 连接在一起。
ipc 名字空间
容器中进程交互还是采用了 Linux 常见的进程间交互方法(interprocess communication – IPC), 包括信号量、消息队列和共享内存等。然而同 VM 不同的是,容器的进程间交互实际上还是 host 上具有相同 pid 名字空间中的进程间交互,因此需要在 IPC 资源申请时加入名字空间信息,每个 IPC 资源有一个唯一的 32 位 id。
mnt 名字空间
类似 chroot,将一个进程放到一个特定的目录执行。mnt 名字空间允许不同名字空间的进程看到的文件结构不同,这样每个名字空间 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个名字空间中的容器在 /proc/mounts 的信息只包含所在名字空间的 mount point。
uts 名字空间
UTS(“UNIX Time-sharing System”) 名字空间允许每个容器拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 主机上的一个进程。
user 名字空间
每个容器可以有不同的用户和组 id, 也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。
namespace六项隔离,实现了容器与宿主机、容器与容器之间的隔离。
Cgroup(控制组):
控制组(cgroups)是 Linux 内核的一个特性,主要用来对共享资源进行隔离、限制、审计等。只有能控制分配到容器的资源,才能避免当多个容器同时运行时的对系统资源的竞争。
控制组技术最早是由 Google 的程序员 2006 年起提出,Linux 内核自 2.6.24 开始支持。
控制组可以提供对容器的内存、CPU、磁盘 IO 等资源的限制和审计管理。。
mount -t cgroup cd /sys/fs/cgroup
四大功能:
1)资源限制:cgroup可以对进程组使用的资源总额进行限制。
2) 优先级分配:通过分配的cpu时间片数量以及硬盘IO带宽大小,实际上相当于控制了进程运行的优先级别。
3)资源统计:cgroup可以统计系统资源使用量,比如cpu使用时间,内存使用量等,用于按量计费。同时,还支持挂起动能,也就是说通过cgroup把所有资源限制起来,对资源都不能使用,注意着并不是说我们的程序不能使用了,只是不能使用资源,处于等待状态。
4)进程控制:可以对进程组执行挂起、恢复等操作。
内存限额:
容器内存包括两个部分:物理内存和swap
可以通过参数控制容器内存的使用量:
-m 或者--memory: 设置内存的使用限额
--memory-swap: 设置内存+ swap的使用限额
例如:运行一个容器,并且限制该容器最多使用200M内存和100M的swap。
docker run -itd --name container1 -m 200MB --memory-swap 300MB centos:7 cd /sys/fs/cgroup/memory/docker/545dc2376efedb0d48e174fd8a9a614baf64f99fc09 cat memory.limit_in_bytes 209715200 cat memory.memsw.limit_in_bytes 314572800
CPU使用
通过-c或者--cpu-shares设置容器使用cpu的权重。如果不设置默认为1024.
例如:
docker run -itd --name container2 -c 512 centos:7 cd /sys/fs/cgroup/cpu/docker/76178cf366cea1d7a60729f21877d135c25141281ae4b6 cat cpu.shares 512
对比一个没有做CPU权重限制的容器。
docker run -itd --name container3 centos:7 cd /sys/fs/cgroup/cpu/docker/4d0858de8e825d362305c05de2293a619d4329ba82dbf8 cat cpu.shares 1024
容器的Block IO
磁盘的读写。
docker中可以通过设置权重,限制bps和iops的方式控制容器读写磁盘的IO.
bps: 每秒读写的数据量 byte per second
iops: 每秒IO的次数 io per second。
默认情况下,所有容器都能够平等的读写磁盘,也可以通过--blkio-weight参数改变容器的blockIO 的优先级。
--device-read-bps: 显示读取某个设备的bps。
--device-write-bps: 显示写入某个设备的bps。
--device-read-iops: 显示读取某个设备的iops。
--device-write-iops: 显示写入某个设备的iops。
例如:限制testA这个容器,写入/dev/sda这块磁盘的bps为30MB.
docker run -it --name testA --device-write-bps /dev/sda:30MB centos:7
从/dev/zero输入,然后输出到test.out文件中,每次大小为1M,总共800次,oflag=direct 用来指定directIO方式写文件,这样才会使--device-write-bps生效。
time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct 800+0 records in 800+0 records out 838860800 bytes (839 MB) copied, 26.6228 s, 31.5 MB/s real 0m26.629s user 0m0.005s sys 0m1.902s
再运行一个不做限制testB容器,对比一下速率
docker run -itd --name testb centos:7 docker exec -it testb /bin/bash time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct 800+0 records in 800+0 records out 838860800 bytes (839 MB) copied, 2.32559 s, 361 MB/s real 0m2.328s user 0m0.000s sys 0m2.107s
查看镜像
docker images
查看所有容器
docker ps -a
查看运行的容器
docker ps
保存镜像
docker save -o nginx.tar nginx:latest
载入镜像
docker load -i nginx.tar
停止容器
docker stop 容器名或id号
删除容器
docker rm 容器名或id号
删除镜像
docker rmi nginx:latest
进入容器
docker exec -it testA /bin/bash
Docker的常用命令
1、帮助命令
docker version #显示docker的版本信息。
docker info #显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help #帮助命令
帮助文档的地址:https://docs.docker.com/engine/reference/commandline/docker/
2、镜像命令
docker images #查看所有本地主机上的镜像 可以使用docker image ls代替
docker search #搜索镜像
docker pull #下载镜像 docker image pull
docker rmi #删除镜像 docker image rm
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 4 months ago 13.3kB
# 解释
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的ID
CREATED 镜像的创建时间
SIZE 镜像的大小
# 可选项
-a, --all # 列出所有的镜像
-q, --quiet # 只显示镜像的id
docker images -aq #显示所有镜像的id
docker search 搜索镜像
docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11138 [OK]
mariadb MariaDB Server is a high performing open sou… 4221 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 829 [OK]
percona Percona Server is a fork of the MySQL relati… 547 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 274 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 89
mysql/mysql-cluster Experimental MySQL Cluster Docker images. Cr… 88
# 可选项
--filter=STARS=3000 # 搜索出来的镜像就死starts 大于3000的
docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11138 [OK]
mariadb MariaDB Server is a high performing open sou… 4221 [OK]
docker pull 下载镜像
# 下载镜像 docker pull 镜像名[:tag]
docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
b4d181a07f80: Pull complete
a462b60610f5: Pull complete
578fafb77ab8: Pull complete
524046006037: Pull complete
d0cbe54c8855: Pull complete
aa18e05cc46d: Pull complete
32ca814c833f: Pull complete
9ecc8abdb7f5: Pull complete
ad042b682e0f: Pull complete
71d327c6bb78: Pull complete
165d1d10a3fa: Pull complete
2f40c47d0626: Pull complete
Digest: sha256:52b8406e4c32b8cf0557f1b74517e14c5393aff5cf0384eff62d9e81f4985d4b
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
# 等价于
docker pull mysql
docker pull docker.io/library/mysql:latest
# 指定版本下载
docker pull mysql:5.7
5.7: Pulling from library/mysql
b4d181a07f80: Already exists
a462b60610f5: Already exists
578fafb77ab8: Already exists
524046006037: Already exists
d0cbe54c8855: Already exists
aa18e05cc46d: Already exists
32ca814c833f: Already exists
52645b4af634: Pull complete
bca6a5b14385: Pull complete
309f36297c75: Pull complete
7d75cacde0f8: Pull complete
Digest: sha256:1a2f9cd257e75cc80e9118b303d1648366bc2049101449bf2c8d82b022ea86b7
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker rmi 删除镜像
docker rmi -f 镜像id # 删除指定的镜像
docker rmi -f 镜像id 镜像id 镜像id 镜像id # 删除多个镜像
docker rmi -f $(docker images -aq) # 删除全部的镜像
3、容器命令
docker run 镜像id #新建容器并启动
docker ps #列出所有运行的容器 docker container list
docker rm 容器id #删除指定容器
docker start 容器id #启动容器
docker restart容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器
docker pause 容器id #挂起容器
docker unpause 容器id #恢复挂起
docker commit 容器id 镜像名 #把容器制作成镜像
说明:有镜像才可以创建容器,linux,下载一个centos镜像来测试学习
docker pull centos:7
新建容器并启动
docker run [可选参数] image
# 参数说明
--name="Name" 容器名字 tomcat01 tomcat02, 用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口(随机映射到外部端口,一般32000+)
-P 随机映射端口
案例:
docker run -d --name web1 -p 8080:80 nginx #指定端口映射
docker run -d --name web2 -p 8081:80 nginx
docker run -d --name web3 -p 80 nginx #随机映射端口
docker run -d --name web4 -P nginx #随机映射端口
# 测试,启动并进入容器
docker run -it centos:7 /bin/bash
[root@90262d2cbb32 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 从容器中退回主机,容器关闭(想要容器持续运行,添加参数-d)
[root@90262d2cbb32 /]# exit
exit
列出所有的运行的容器
#docker ps命令 #列出当前正在运行的容器
# 列出当前正在运行的容器
-a # 列出当前正在运行的容器+带出历史运行过的容器
-q # 只显示容器的编号
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a199a44bb07c centos "/bin/bash" 23 minutes ago Up 23 minutes compassionate_feynman
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
90262d2cbb32 centos "/bin/bash" 4 minutes ago Exited (0) 3 minutes ago zen_cerf
a199a44bb07c centos "/bin/bash" 23 minutes ago Up 23 minutes compassionate_feynman
2a70eb3c087c d1165f221234 "/hello" 25 hours ago Exited (0) 25 hours ago bold_darwin
退出容器
exit
删除容器
docker rm 容器id # 删除指定容器,不能删除正在运行的容器,如果要强制删除
docker rm -f $(docker ps -aq) # 删除所有的容器
docker ps -a -q | xargs docker rm -f # 删除所有的容器
启动和停止容器的操作
docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器
4、常用其他命令
后台启动容器
# 命令 docker run -d 镜像名!
docker run -d centos:7
# 问题docker ps,发现centos停止了
# 常见的坑,docker 容器使用后台运行,就必须要有一个前台进程, docker 发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
查看日志
docker logs --help
Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
Options:
--details 显示更多的信息
-f, --follow 跟踪日志输出,最后一行为当前时间戳的日志
--since string 显示具体某个时间或时间段的日志
-n, --tail string 从末尾显示多少行,默认all
-t, --timestamps 显示时间戳
#命令测试看日志
docker logs -f -t --details 容器id
# 自己编写一段shell脚本
docker run -d centos:7 /bin/sh -c "while true;do echo 6666;sleep 1;done" #模拟日志
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES596b80f933ac centos "/bin/sh -c 'while t…" 9 seconds ago Up 8 seconds priceless_meninsky
# 显示日志
-tf #显示日志
--tail=number #要显示日志条数
docker logs -tf --tail 10 596b80f933ac
docker logs -tf --tail=10 596b80f933ac
查看容器中进程信息 ps
# 命令 docker top 容器id
docker top 596b80f933ac
UID PID PPID C STIME TTY TIME CMD
root 10528 10491 0 17:17 ? 00:00:00 /bin/sh -c while true;do echo 6666;sleep 1;done
root 11362 10528 0 17:23 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像的元数据
# 命令
docker inspect 容器id
#测试
docker inspect 596b80f933ac
进入当前正在运行的容器 *****
# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
# 命令
docker exec -it 容器id bashShell
# 测试
docker exec -it 596b80f933ac /bin/bash
ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Jul19 ? 00:00:17 /bin/sh -c while true;do echo 6666;sleep 1;done
root 23455 0 0 00:51 pts/0 00:00:00 /bin/bash
root 23704 1 0 00:55 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
root 23705 23455 0 00:55 pts/0 00:00:00 ps -ef
# 方式二
docker attach 容器id
# 测试
docker attach 596b80f933ac
正在执行当前的代码。。。。
# docker exec #进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach #进入容器正在执行的终端,不会启动新的进程!
从容器内拷贝到主机上
docker cp 容器id:容器内路径 目的的主机路径
docker attach 0b308ba7528d
cd /home
ls
# 在容器内新建一个文件
touch test.java
exit
# 将这个文件拷贝出来到主机上
docker cp 0b308ba7528d:/home/test.java /home
# 拷贝是一个手动过程,使用 -v 卷的技术,可以更容易实现
==============================
总结:
attach Attach to a running container #当前shell下attach连接指定运行镜像
build Build an image from a Dockerfile #通过Dockerfile定制镜像
commit Create a new image from a containers changes #提交当前容器为新的镜像
cp Copy files/folders from a container to a HOSTDIR or to STDOUT #从容器中拷贝指定文件或者目录到宿主机中
create Create a new container #创建一个新的容器,同run 但不启动容器
diff Inspect changes on a containers filesystem #查看docker容器变化
events Get real time events from the server #从docker服务获取容器实时事件
exec Run a command in a running container #在已存在的容器上运行命令
export Export a containers filesystem as a tar archive #导出容器的内容流作为一个tar归档文件(对应import)
history Show the history of an image #展示一个镜像形成历史
images List images #列出系统当前镜像
import Import the contents from a tarball to create a filesystem image #从tar包中的内容创建一个新的文件系统映像(对应export)
info Display system-wide information #显示系统相关信息
inspect Return low-level information on a container or image #查看容器详细信息
kill Kill a running container #kill指定docker容器
load Load an image from a tar archive or STDIN #从一个tar包中加载一个镜像(对应save)
login Register or log in to a Docker registry #注册或者登陆一个docker源服务器
logout Log out from a Docker registry #从当前Docker registry退出
logs Fetch the logs of a container #输出当前容器日志信息
pause Pause all processes within a container #暂停容器
port List port mappings or a specific mapping for the CONTAINER #查看映射端口对应的容器内部源端口
ps List containers #列出容器列表
pull Pull an image or a repository from a registry #从docker镜像源服务器拉取指定镜像或者库镜像
push Push an image or a repository to a registry #推送指定镜像或者库镜像至docker源服务器
rename Rename a container #重命名容器
restart Restart a running container #重启运行的容器
rm Remove one or more containers #移除一个或者多个容器
rmi Remove one or more images #移除一个或多个镜像(无容器使用该镜像才可以删除,否则需要删除相关容器才可以继续或者-f强制删除)
run Run a command in a new container #创建一个新的容器并运行一个命令
save Save an image(s) to a tar archive #保存一个镜像为一个tar包(对应load)
search Search the Docker Hub for images #在docker hub中搜索镜像
start Start one or more stopped containers #启动容器
stats Display a live stream of container(s) resource usage statistics #统计容器使用资源
stop Stop a running container #停止容器
tag Tag an image into a repository #给源中镜像打标签
top Display the running processes of a container #查看容器中运行的进程信息
unpause Unpause all processes within a container #取消暂停容器
version Show the Docker version information #查看容器版本号
wait Block until a container stops, then print its exit code #截取容器停止时的退出状态值
===================================================
练习
centos安装nginx
#1. 搜索镜像 search 建议大家去docker hub搜索,可以看到帮助文档
docker search centos
#2. 拉取镜像 pull
docker pull centos
#3. 运行测试
# -d 后台运行
# --name 给容器命名
# -p 宿主机端口:容器内部端口
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 4cdc5dd7eaad 13 days ago 133MB
centos latest 300e315adb2f 7 months ago 209MB
docker run -itd --name nginx01 -p 80:80 centos
8661ad7244a0dc33bed197e3e0147843b4e5e9d9e8646e442ffb102e1d0d4ac3
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8661ad7244a0 centos "/docker-entrypoint.…" 9 seconds ago Up 8 seconds 0.0.0.0:80->80/tcp nginx01
curl localhost
# 进入容器
docker exec -it nginx01 /bin/bash
#安装vim和nginx
yum -y install epel-release
yum -y install vim net-tools nginx
#把容器制作成镜像
docker commit nginx01 mynginx