单机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等等。
平时我们安装进虚拟机的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默认latest | TAG可选,表示版本 |
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] | 镜像改名 | ||
退出容器
- exit:使用exec启动后不停止,使用docker attach 启动后会停止
- 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
本地镜像推送到私有库
<!–以本地搭建私有库为例–>
- 首先获取registry镜像,负责管理私有库
docker pull registry
- 启动registry
docker run -d -p 127.0.0.1:5000:5000 -v /tmp/myregistry:/tmp/registry --privileged=true registry
- 本地镜像改名为符合私服格式的镜像
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
- 旧版本docker默认不允许http方式推送镜像,通过配置选项来取消这个限制
注意:20.10.9版本后默认允许http推送,不用改配置
这里给一下更改示例(更改后重启docker)
"insecure-registries": [
"127.0.0.1:5000"
]
- 推送到私有库
docker push 127.0.0.1:5000/jellow/ubuntu:1.1
- 查看目前的镜像
curl -XGET http://127.0.0.1:5000/v2/_catalog
可以看到已经成功添加 {“repositories”:[“jellow/ubuntu”]}
- 从私有仓库pull镜像
这个指令其实和docker push就差了push????
docker pull 127.0.0.1:5000/jellow/ubuntu:1.1
容器卷
为什么有数据卷?
docker中的数据在容器删除后就会消失
容器卷的作用是将主机目录和容器目录做映射,容器内的数据备份可以保存在主机目录,完成数据的持久化。
- 数据卷可在容器之间共享或重用数据
- 卷中的更改可以直接实时生效(不用再手动复制了)
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
挂载目录权限设置
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为容器路径
以后就可以使用Docker安装Redis,MongoDB等数据库软件,需要注意的是这些软件的配置信息和数据最好存储在数据卷中,防止容器删除后消失。