Docker是一个操作系统级别的虚拟机引擎,它运行在操作系统之上,可以为任何应用创建一个轻量级、可移植的容器,而每个容器的进程是独立的,就像手机上的APP一样。所有的容器都共用一个操作系统内核。
Docker与虚拟机在几个方面有所不同。首先,磁盘空间使用方面,Docker的镜像层一般很小,只有几十M,几百M,而虚拟机则通常以GB为单位。
在性能方面,Docker依附于宿主机,所以性能接近宿主机,而虚拟机相对于原主机来说性能较差。[1]再者,资源利用率方面,Docker的资源利用率较高,而虚拟机对硬件资源消耗大,利用率较低。
隔离性方面,Docker和虚拟机都具有安全隔离的特性。
Docker直接在宿主机内核上运行,而虚拟机运行在隔离层Hypervisor上。
Docker可以同时运行上千个容器,而虚拟机相对较厚重,最多只能启动几十个。
在运行速度方面,Docker优于虚拟机,Docker容器的启动和停止可以在秒级实现,而传统的虚拟机方式要慢得多。
下面是虚拟机和docker的底层原理图:
vmware虚拟机
docker虚拟机:
镜像是一个只读的应用模板,它保存了容器需要的环境和应用的执行程序,可以将镜像看作是容器的代码,当代码执行起来的时候,就成了容器,镜像和容器的关系就类似于程序和进场之间的关系。
我们可以通过dockerfile文件,定义需要安装的程序,然后创建出镜像文件。
容器是一个运行环境,是镜像的一个运行状态,他是镜像执行的动态表现。它里面的内容是可读可写的,容器是完全隔离的,我们不用担心容器之间会相互干扰。
仓库就是用来保存镜像的地方,像docker hub就是全世界最大的镜像库,用户可以将自己做好的镜像发布上去。
docker search [镜像名]
docker search nginx
docker pull [镜像名]
docker pull nginx
如果报如下错误
Error response from daemon: Head "https://registry-1.docker.io/v2/library/nginx/manifests/latest": dial tcp: lookup registry-1.docker.io on 192.168.1.1:53: no such host
修改/etc/resolv.conf,改成如下DNS值
(宿主机是centos7,其他的操作系统可能不一样)
nameserver 114.114.114.114
nameserver 8.8.8.8
docker images
或
docker image ls
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
# 这其实是给nginx镜像重新克隆了一个出来并打上标签
docker tag nginx:latest nginx:v1
docker build [OPTIONS] PATH
OPTIONS表示构建镜像时的参数配置,PATH表示指定的构建上下文路径,Dockerfile入股就在当前项目下,那么就是.
表示
如果不指定Dockerfile,则默认使用当前目录下名为Dockerfile的文件
参数-t
指定要构建的镜像名称和版本,-f
指定要使用的Dockerfile文件
myapp, 表示上下文目录
例子1:app应用路径
myapp/
├── Dockerfile-dev
├── Dockerfile-prod
├── app.py
└── requirements.txt
此场景,就是当前应用下有开发环境,生成环境的不同的dockerfile,那么需要指定具体dockerfile的路径。
docker build -t myapp:dev -f Dockerfile-dev myapp/
如果要使用Dockerfile-prod文件进行构建,则可以使用如下命令:
docker build -t myapp:prod -f Dockerfile-prod myapp/
例子2:自定义的nginx
docker build -t nginx:v1 -f ./Dockerfile-test ../nginx-v1/
docker save -o [导出的文件名] [镜像名]
docker save -o nginx-img.tar.gz nginx:latest
docker load -i [导入的文件名]
docker load -i nginx-img.tar.gz
镜像删除的时候,其关联的容器要先删除干净才行。
docker rmi [镜像名称]:[tag]
docker rmi nginx
若有标签的
docker rmi nginx:1.21
如果想要查看dockerfile构建镜像的过程,通过history
命令来查看
格式 docker image history [镜像名]:[tab]
docker image history nginx:latest
标注:为了更好的区分容器和镜像的命令,我们初学者一开始在docker后面加上
container
来表示容器,这样子比较直观
docker container [arg…]
我们在操作容器时,可以取容器id的前面四位,这个标识这个容器,前四位是唯一的。
# 当前正在运行的
docer ps
# 查看所有的容器
docker ps -a
# 查看最近的容器
docker ps -l
docker run [选项] 镜像名 命令 [参数]
选项说明:
-d: 后台运行容器(守护进程) 并返回容器ID
-i: 以交互模式运行容器,通常与-t同时使用
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用
-p: 指定端口映射,格式:主机(宿主)端口:容器端口
-P: 随机端口映射,容器内部端口随机映射到主机的端口
-v:绑定一个数据卷
-h “mars”: 指定容器的hostname;
-e username=“ritchie”: 设置环境变量;
–rm: 使用场景:默认情况下,如果你想要Docker自动清理容器,就在容器退出(docker stop)时,你可以添加–rm标志。这样子方便来调试用。
–env-file=[]: 从指定文件读入环境变量;
–cpuset=“0-2” or --cpuset=“0,1,2”: 绑定容器到指定CPU运行;
–volume: 和-v一样,绑定一个数据卷
–name=mongo-lb: 为容器指定一个名称
–privileged=true 容器具有root权限,可以读写宿主目录
–restart=always 开机自启动
启动nginx容器为例子:
# 表示以后台启动一个名为nginx容器,并且支持交互模式,并且宿主机和容器端口都是80
docker run -itd --name nginx -p 80:80 nginx:latest
第一次可以通过docker run启动,之后都是通过docker start启动,并且如果镜像不存在会自动去拉取。
docker start [容器id或名称]
# 通过容器id启动
docker start 051c85d85e4a
# 通过容器名启动
docker start nginx
docker restart [容器id或名称]
docker restart nginx
docker stop [容器id或名称]
docker stop 051c85d85e4a
docker pause [容器id或名称]
docker pause 051c85d85e4a
docker unpause [容器id或名称]
docker unpause 051c85d85e4a
- 暂停和停止的差别在于操作系统的处理方式,如果容器进入暂停状态,操作系统会将容器内的进程挂起,容器关联的内存暂存下来。CPU不再执行这个进程。但是如何把它恢复了呢?内存空间恢复,程序接着运行。
- 但是停止不同,停止直接把这个进程杀死,容器所占的内存回收。那保留下来的仅剩容器的文件系统了,也就是一些静态的东西,这就是暂停和停止的差别了,因此一旦停止,暂存在内存的数据没有办法恢复的。
容器删除前,要先停掉容器,如果容器中存在重要数据,需要迁移到数据卷或宿主目录下
docker rm [容器id或容器名称]
docker rm 051c85d85e4a
docker exec -it [容器名或id] -it
# 进入nginx容器内部
docker exec -it nginx /bin/bash
# 退出
exit
容器创建成功后,可以通过docker inspect
命令查看容器的详细信息,这些容器的信息包括容器的名称,id,环境变量,运行命令,主机配置,网络配置,数据卷配置等等,
docker inspect -f{{格式化状态值}} [容器id或容器名]
# 筛选出数据卷信息
docker inspect -f='{{.Mounts}}' nginx
# 查看运行状态
docker inspect -f='{{.State.Running}}' niginx
docker inspect nginx-v1 | grep -i "ip"
docker top [容器id或容器名]
docker top nginx
docker logs [options] 容器id或容器名
-f: 实时看日志
–tail: 表示看默认的几行
-t: 表示显示时间
# 查看容器所有的日志
docker logs nginx
# 实时看日志,并显示最后5行,并显示日期时间
docker logs -f --tail=5 -t nginx
docker export [容器名或容器id] > [目标路径]
本地修改好的index.html文件上传到容器中,然后访问页面
vim ~/index.html
docker cp ~/index.html nginx:/usr/share/nginx/html/
docker export nginx > ~/nginx.tar.gz
可以将前面的nginx容器删除,然后再导入,需要注意的是导入的容器,需要以命令行模式启动
docker run -itd --name=nginx -p 80:80 import-nginx bash
可以更新一个或多个容器的配置,比如容器忘记设置开机重启,没读写权限
docker update [OPTIONS] 容器id1 [容器id2…]
以hyperf容器例子为例子:
docker update --restart=always hyperf
docker logs [-f] 容器名|容器id
-f参数表示动态的去加载日志
比如查看nginx的容器执行日志
先找到所有的容器
docker ps -a
再根据容器id的前四位来查看日志
docker container logs 5237
动态加载日志:
我们在访问web站点时候,日志就会进nginx。这个时候就能实时看到日志了。
docker container logs -f 5237
格式:docker [container] top 容器id|容器名称
容器其实就是一个进程,当进程退出时,容器也就关闭了。
比如查看nginx的容器进程:
docker container top
pstree -halps 2528
格式:docker plugin install [OPTIONS] PLUGIN [KEY=VALUE…]
安装vieux/sshfs
插件并将其DEBUG环境变量设置为1。安装时,需要从Docker Hub中拉出插件,并提示用户接受插件所需的权限列表,设置插件的参数并启用插件。
docker plugin install vieux/sshfs DEBUG=1
插件安装完成后,会出现在插件列表中:
docker plugin ls
ID NAME DESCRIPTION ENABLED
1eba3fdfd738 vieux/sshfs:latest sshFS plugin for Docker true
文章参考:https://www.cjavapy.com/mip/2985/
举例:docker container run -d -P --name=nginx nginx:latest
按以下顺序执行: