容器的基本操作
- 停止容器
- 进入容器内部
- 启动一个已经中止的容器
- 删除容器
镜像的基本操作
- 定制镜像
- 保存镜像
- 加载镜像
- 导入导出容器(导出包,将包导成新的镜像)
- 删除镜像
容器的基本操作
-
停止容器
首先,得明确两个关键的点
1.在什么情况下容器启动后会立即终止?
实际情况中,除了使用docker stop命令来强制地终止一个容器以外,当容器的启动命令终结时,容器也自动会终止。
原因:
Docker容器是一个进程,实际上它以sh作为主进程。如果主进程停止了,那么容器也就停止了。而如果容器的“启动命令”执行完之后,由于主进程没有命令继续执行,所以主进程会停止,容器也就因此而停止了。
2.如何才能使容器启动后不立即终止?
如果容器的sh主进程不停止,是不是以为这容器就不会停止?答案是肯定的。因此,如果使启动命令不能执行完毕,或者在执行完启动命令后,容器的sh主进程不停止,那么容器在启动后就不会立即终止了!
两种方法:
a.将启动命令设置为死循环
另开一个ssh终端查看docker容器的活跃状态,可见其为活跃状态
这条命令在创建并启动容器之后,会执行/bin/sh -c "while true; do echo hello docker; sleep 1; done",由于该命令永远都不会执行完毕,除非强行终止,所以容器的主进程sh不会停止,因此容器也将不会停止。但是这样的做的话,无法正常的操作容器,而且它会占据资源,所以这种做法在实际的工作中意义并不大。
b.将启动命令设置为“启动一直运行的子进程”
首先需要开启一个容器,并让其保持活跃,不要立即退出
docker run -it --name conta ubuntu /bin/bash
-i选项告诉Docker保持标准输入输出流对容器开放,-t选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
执行完这条命令后,创建并启动容器之后,执行/bin/bash,会启动一个子进程,此时父进程(也就是容器的主进程sh)会进入sleep状态,由于sleep状态不是终止状态,所以容器会继续运行。
为什么在容器中输入exit或者执行ctrl D后,容器将会终止呢?
这是因为exit会退出(结束)当前进程,也就是/bin/bash,由于子进程结束,sh主进程恢复到运行态,然而由于没有命令需要继续执行,所以sh主进程结,因此容器终止。
这时,重新开启一个ssh终端,登录到我的centos虚拟机上,可以看到这个容器时活跃的
明白了以上两点,那么让这个活跃的容器停止一下吧
语法:docker stop [OPTIONS] Container [Container ...]
演示:可见原本活跃的名为container容器在执行stop后,变成了退出状态
-
进入容器内部
- 使用ssh登陆进容器;
- 使用nsenter、nsinit等第三方工具;
- 使用docker本身提供的工具。
- docker attach
a.先创建一个容器 docker run -itd ubuntu /bin/bash
b.进入容器 docker attach 容器的名字/ID
演示:
分别通过容器的ID和名字进入容器内部
- docker exec
a.先创建一个容器 docker run -itd ubuntu /bin/bash
b.可以在宿主机上对容器内部进行创建文件夹 docker exec 容器名字/ID mkdir dir1
c.进入容器 docker exec -it 容器名字/ID /bin/bash
演示:容器名进入与上一个类似,这里不做展示
- 二者区别
a.attach直接进入容器“启动命令”的终端,不会启动新的进程;
b.exec则是在容器中打开新的终端,并且可以启动新的进程;
c.如果想直接在终端中查看容器“启动命令”的输出,用attach;其他情况使用exec。
-
启动一个已经中止的容器
docker start 容器的名字或ID
-
删除容器
三种删除的环境
a.删除一个处于终止状态的容器
语法:docker rm 容器的名字或ID
演示:
b.删除一个正在运行的容器
先使运行中的容器停止,然后再进行删除
c.删除所有处于终止状态的容器
docker ps –a命令可以查看所有容器的信息。而docker ps –a –q只查看所有容器的containerId。在Linux中,将命令放在$()中,会执行命令并返回命令的执行结果。因此$( docker ps -a -q)会返回所有容器的container id,而docker rm只能干掉终止的容器,而如果用docker rm删除正在运行的容器时,将不能删除掉。所以可以使用docker rm $(docker ps -a -q)来删除所有处于终止状态的容器。
演示:
镜像的基本操作
-
定制镜像
commit
语法: docker commit [OPTIONS] CONTAINER [镜像名]
docker commit webserver nginx:v1
思路:
1.安装nginx镜像
2.创建一个webserver容器
3.进入容器,修改一些需要的内容
4.对修改的容器定制成一个镜像nginx:v1
5.执行,用新镜像创建一个容器,然后测试是否定制成功
演示:
1.先安装nginx镜像,Nginx是一款自由的、开源的、高性能的HTTP和反向***服务器
2.这条命令以nginx基础镜像创建了一个名为webserver的容器,-p用于端口映射,以此条命令为例,-p 80:80代表将宿主机的80端口映射到容器的80端口,这意味着可以直接通过访问宿主机ip:80访问到容器的80端口!
3.修改webserver的展示内容,用HTML修改网页的展示内容
测试网页
4.定制镜像
5.以nginx:v1为基础镜像创建启动一个新容器,并将宿主机的50端口映射到容器的80端口,可以在创建的同时,查看容器内的文件(其实是创建完成后,才去进行查看的,这是显而易见的)
换了个浏览器是因为,浏览器的缓存原因
缺点:
1.增加一些不必要的文件进入镜像
2.黑箱操作
3.不利于后期的维护
-
保存镜像
语法 :docker save [OPTIONS] IMAGE [IMAGE...]
思路:将一个镜像保存为tar文件
演示:两种写法
docker save alpine:latest > alpine.tar
docker save -o alpine:lateste alpine.tar "-o指定写到一个文件中,而不是标准输出流中"
也可将多个镜像保存成tar文件
docker save alpine:latest ubuntu:latest > image.tar
-
加载镜像
语法: docker load [OPTIONS]
思路:从tar文件中加载镜像
演示:
两种写法
docker load < alpine.tar
docker load -i alpine.tar "-i指定从一个tar文件中读取,而不是标准输入流中。"
-
导入导出容器
1.将“容器的文件系统”保存到tar包
语法:docker export [OPTIONS] CONTAINER
举例:docker export container1 > container1.tar 或
docker export container1 -o container1.tar -o指定写到一个文件中,而不是标准输出流中
思路: Docker将容器导出到tar包
2.从tar包导成一个镜像
语法:docker import [OPTIONS] 文件|URL|- [镜像名]
思路: Docker将容器导出到tar包,docker import使用docker export导出的tar包加载为一个镜像
举例:docker cat container1.tar | docker import - test:v1.0
详细步骤:
1.以官网存在的镜像创建一个容器
2.在这个容器内可以添加或删除一些文件,将修改后的容器打包
3.将包导入成一个ISO
4.使用新的ISO创建一个容器
5.查看新的容器内部有没有修改的内容
演示:
1.先以官网存在的镜像创建一个容器
docker run -it ubuntu /bin/bash
2.对此容器做出修改,然后打包
mkdir /test/test.zip -p
mkdir /test2/test2.zip -p
docker export f417 > ubuntu-test.tar
3.将tar包导成一个镜像文件
4.用新的镜像创建一个容器,查看其内部内容,可见与预期相符
docker export和docker save的区别
首先,两者的操作对象不同。docker save是将一个镜像保存为一个tar包,而docker export是将一个容器快照保存为一个tar包。然后,docker export导出的容器快照文件将丢弃所有的历史记录和元数据信息,即仅保存容器当时的快照状态;而docker save保存的镜像存储文件将保存完整记录,体积也要大
-
删除镜像
语法:docker rmi [OPTIONS] IMAGE [IMAGE...] i代表image
思路: 删除一个本地的镜像
举例
1.匹配方式
- 镜像短ID docker rmi 1234 镜像id以1234开头的镜像,一般而言,前四位可以唯一标志,如果不可以,docker会提示的
- 镜像长ID docker rmi 123412341234
- 镜像名 docker rmi ubuntu:latest
- 镜像的digest docker rmi ubuntu@sha256:sha256:bec5a2727be7fff3d308193cfde3491f8fba1a2ba392b7546b43a051853a341d
2.删除多个镜像
docker rmi $(docker images –q redis) docker images -q redis会输出所有仓库名为redis的镜像id
3.删除所有镜像
docker rmi $(docker images –qa)
注意:如果想要使用docker rmi删除一个镜像,需要注意需要先将使用该镜像的容器删除掉,否则该镜像不能删除成功。当然也可以使用docker rmi -f强制删除该镜像!
演示:
执行删除所有的镜像后,提示有的镜像不能删除,这是因为有的容器正在使用这个镜像
解决:
用-f来强制删除
如果你想学到更多关于docker的知识,请查阅我的分类专栏之Docker