容器的基本操作

  • 停止容器
  • 进入容器内部
  • 启动一个已经中止的容器
  • 删除容器

镜像的基本操作

  • 定制镜像
  • 保存镜像
  • 加载镜像
  • 导入导出容器(导出包,将包导成新的镜像)
  • 删除镜像

容器的基本操作

  • 停止容器

首先,得明确两个关键的点

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后,变成了退出状态

 

  • 进入容器内部

  1. 使用ssh登陆进容器;
  2. 使用nsenter、nsinit等第三方工具;
  3. 使用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