单机Docker常见知识

单机Docker

最近我在学Docker,这篇文章记录了Docker的基础操作指令。

教程链接:尚硅谷2022版Docker实战教程

Docker镜像为什么这么小?

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是引导文件系统bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

image-20220819153425131

平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M??

对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

Docker run

对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

docker run [options] image [command] [args]

–name=”容器新名字” 为容器指定一个名称;

-d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行);

-i:以交互模式运行容器,通常与 -t 同时使用;

-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;

docker rum -it ubuntu /bin/bash

也即启动交互式容器(前台有伪终端,等待交互);

-P: 随机端口映射,大写P

-p: 指定端口映射,小写p

[pip:hostPort:containerPort | ip::containerPort | hostPort:containerPort]

ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort

映射所有接口地址

使用 hostPort:containerPort 格式本地的 80 端口映射到容器的 80 端口,可以执行

$ docker run -d -p 80:80 nginx:alpine

此时默认会绑定本地所有接口上的所有地址。

映射到指定地址的指定端口

可以使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址,比如 localhost 地址 127.0.0.1

$ docker run -d -p 127.0.0.1:80:80 nginx:alpine

映射到指定地址的任意端口

使用 ip::containerPort 绑定 localhost 的任意端口到容器的 80 端口,本地主机会自动分配一个端口。

$ docker run -d -p 127.0.0.1::80 nginx:alpine

还可以使用 udp 标记来指定 udp 端口

$ docker run -d -p 127.0.0.1:80:80/udp nginx:alpine

指令

指令解释指令解释
docker image查看本机镜像
docker search []查询某个镜像– -limit [num]前num条
docker pull [镜像名字:TAG]下载镜像TAG默认latestTAG可选,表示版本
docker system df查看空间占用
docker rmi删除某个镜像-f强制删除
docker ps查看正在运行的容器
docker rename [原容器名] [新容器名]容器改名
docker start [name]启动容器
docker exec -it [name] /bin/bash进入容器并创建新进程(常用)
docker attach [name]进入容器
docker restart [name]重启容器
docker stop [name]停止容器
docker kill [name]强制停止容器
docker rm [name]删除容器
docker logs [name]查看容器日志
docker top [name]查看容器内部进程
docker instpect [name]查看容器配置
docker cp [name]: 容器内路径 主机路径从容器内拷贝文件到主机
docker tag IMAGE[:TAG] Host:Port[/username/image_name] [:TAG]镜像改名

退出容器

  1. exit:使用exec启动后不停止,使用docker attach 启动后会停止
  2. control+p+q:退出后容器不停止

守护进程Docker

docker容器后台运行,就必须有一个前台进程。

有些程序使用docker run -d 后关闭窗口不会退出(redis),而有些会退出(ubuntu)。

容器与镜像备份

  • docker save images_name:将一个镜像导出为文件,再使用docker load命令将文件导入为一个镜像,会保存该镜像的的所有历史记录。比docker export命令导出的文件大,很好理解,因为会保存镜像的所有历史记录。
  • docker export container_id:将一个容器导出为文件,再使用docker import命令将容器导入成为一个新的镜像,但是相比docker save命令,容器文件会丢失所有元数据和历史记录,仅保存容器当时的状态,相当于虚拟机快照。

两者的区别在于容器快照将会丢弃所有的历史记录和元数据信息,而镜像存储文件将保存完整记录,体积也会更大。此外从容器快照文件导入时,也可以重新指定标签等元数据。

指令解释
docker export [name] > xxx.tar容器备份
cat xxx.tar | docker import – 镜像用户/镜像名:镜像版本号恢复容器备份
docker save [name] >xxx.tar镜像备份
docker load < xxx.tar镜像恢复

提交新镜像

docker commit -m=“提交的描述信息”-a=“作者” 容器ID 目标镜像名:[标签名]

docker commit -m="带vim的ubuntu" -a="Jellow" 9a588b87d1fb8232f6985d23735b73aec5d4bf9c577e7d1add0a3424f5f4acd5 jellow/ubuntu:1.0

本地镜像推送到私有库

<!–以本地搭建私有库为例–>

  1. 首先获取registry镜像,负责管理私有库
docker pull registry
  1. 启动registry
docker run -d -p 127.0.0.1:5000:5000  -v /tmp/myregistry:/tmp/registry --privileged=true registry
  1. 本地镜像改名为符合私服格式的镜像

docker tag IMAGE[:TAG] Host:Port[/username/image_name] [:TAG]

docker tag jellow/ubuntu:1.0 127.0.0.1:5000/jellow/ubuntu:1.1
  1. 旧版本docker默认不允许http方式推送镜像,通过配置选项来取消这个限制

注意:20.10.9版本后默认允许http推送,不用改配置

这里给一下更改示例(更改后重启docker)

image-20220820093922005
"insecure-registries": [
  "127.0.0.1:5000"
]
  1. 推送到私有库
docker push 127.0.0.1:5000/jellow/ubuntu:1.1
  1. 查看目前的镜像
curl -XGET http://127.0.0.1:5000/v2/_catalog

可以看到已经成功添加 {“repositories”:[“jellow/ubuntu”]}

  1. 从私有仓库pull镜像

这个指令其实和docker push就差了push????

docker pull 127.0.0.1:5000/jellow/ubuntu:1.1

容器卷

为什么有数据卷?

docker中的数据在容器删除后就会消失

容器卷的作用是将主机目录和容器目录做映射,容器内的数据备份可以保存在主机目录,完成数据的持久化。

  1. 数据卷可在容器之间共享或重用数据
  2. 卷中的更改可以直接实时生效(不用再手动复制了)
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷的生命周期一直持续到没有容器使用它为止

挂载目录权限设置

Docker挂载主机目录访问如果出现cannot open directory .: Permission denied

解决办法:在挂载目录后多加一个–privileged=true参数即可

如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,

在SELinux里面挂载目录被禁止掉了,如果要开启,我们一般使用–privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。

挂载容器卷

docker run -it --privileged=true -v /宿主机目录:/容器内目录:[权限] [IMAGE]

权限:默认为rw读写,ro为容器只读

继承容器卷

docker run -it --privileged=true --volumes-from [容器名] [IMAGE]

查看容器挂载路径

使用docker inspect ,Mounts记录了挂载路径

Source为主机路径,Destination为容器路径

image-20220820154012667

以后就可以使用Docker安装Redis,MongoDB等数据库软件,需要注意的是这些软件的配置信息和数据最好存储在数据卷中,防止容器删除后消失。

发表评论