操作Docker容器
容器是Docker核心概念之一,简单地说,容器是独立运行一个或者一组应用,以及它们的运行环境。对应的虚拟机可以理解为模拟运行的一整套操作系统(提供了运行状态环境和其他系统环境)和跑在上面的应用。
启动容器
启动容器有两种方式,一种是基于镜像新建一个容器并启动,另一个是将已经停止运行容器重新启动。
因为Docker的容器是轻量级的,很多时候用户都是随时删除和新创容器。
新建并启动
docker启动容器的命令是docker run
,在前面我们已经知道了。
例如,下面启动ubuntu,并且输出一个"Hello World"之后容器将终止。
xin@xin:~$ docker run ubuntu:18.04 /bin/echo 'Hello World'
Hello World
这跟直接在本地执行 /bin/echo 'Hello World'
几乎没有任何区别。
我们还可以根据下面的命令启动一个bash终端,运行用户进行交互,并且通过用户所创建的终端来输入命令,例如:
xin@xin:~$ docker run -t -i ubuntu:18.04 bash
root@24d7b3d0f541:/# echo 'Hello World'
Hello World
root@24d7b3d0f541:/# pwd
/
root@24d7b3d0f541:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
其中,-t
选项让docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上,-i
则让容器的标准输入保持打开。
当利用 docker run
来创建容器时,docker在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从共有仓库下载
- 利用镜像创建并启动一个容器
- 从宿主机配置的网桥接口中桥接一个虚拟接口道容器中去
- 从地址池配置一个ip地址给容器
- 执行用户指定的应用程序
- 执行完后容器被停止
后台运行
很多时候,需要让Docker在后台运行不是直接把执行命令的结果输出在当前宿主机下,我们可以通过添加 -d
参数来实现。
不使用 -d
参数来运行容器:
xin@xin:~$ docker run ubuntu:latest /bin/sh -c "while true;do echo hello world; sleep 1; done"
hello world
hello world
hello world
...
可以看到,容器会把输出结果(STDOUT)打印到宿主机上面。
如果我们使用 -d
参数来运行容器:
xin@xin:~$ docker run -d ubuntu:latest /bin/sh -c "while true;do echo hello world; sleep 1; done"
ec9aba576cbcf554e7cbcfd41019cd09177cb33107d6322462085d2fee1f0b68
可以看到,容器并没有输出 Hello World
,返回的是一个完整的容器ID,也可以通过docker container ls
来查看容器信息。
xin@xin:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec9aba576cbc ubuntu:latest "/bin/sh -c 'while t…" 3 minutes ago Up 3 minutes condescending_darwin
想要查看查看输出结果可以使用 docker logs
来查看:
xin@xin:~$ docker logs ec9aba
hello world
hello world
hello world
hello world
hello world
...
终止容器
想要终止容器,我们可以使用 docker container stop
或者 docker stop
来终止一个运行中的容器。除外,当docker容器制定的应用结束时,容器也会自动终止。
终止状态的容器我们可以用 docker container ls -a
命令看到。例如:
xin@xin:~$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec9aba576cbc ubuntu:latest "/bin/sh -c 'while t…" 9 minutes ago Exited (137) 5 minutes ago condescending_darwin
f96e35891f09 ubuntu:latest "/bin/sh -c 'while t…" 11 minutes ago Exited (0) 11 minutes ago optimistic_tesla
10983aeeef8f hello-world "/hello" 22 minutes ago Exited (0) 22 minutes ago condescending_carson
处于终止状态的容器,我们可以通过 docker container start
命令来重新启动。
xin@xin:~$ docker container start ec9aba576cbc
ec9aba576cbc
xin@xin:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec9aba576cbc ubuntu:latest "/bin/sh -c 'while t…" 12 minutes ago Up 33 seconds condescending_darwin
除此之外,我们还可以通过docker container restart
命令将会一个运行状态的容器终止,然后再重启起动它。
xin@xin:~$ docker container restart ec9aba576cbc
ec9aba576cbc
进入容器
在使用 -d
参数时,容器启动后会进如后台。有些时候我们需要进入容器操作,比如查看日志等等。
attach 命令
docker attach
是docker自带的命令,我们看看该如何使用这条命令:
xin@xin:~$ docker run -dit ubuntu
8c222c1b9952b00f73b3d6ba99af4fc1ba347833a051b54f3b19438fe28b367b
xin@xin:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c222c1b9952 ubuntu "/bin/bash" 6 seconds ago Up 5 seconds gracious_northcutt
xin@xin:~$ docker attach 8c222c
root@8c222c1b9952:/#
注意:如果从这个stdin中exit,会导致容器的停止。
exec命令
docker exec
后面可以跟多个参数,这里我们主要了解 -i
-t
参数。
只用 -i
参数时,由于没有分配伪终端,界面没有我们熟悉的linux命令提示符,但是命令执行结果仍然可以返回。
当 -i
-t
参数一起使用时,则可以看到我们熟悉的linux命令提示符。
xin@xin:~$ docker run -dit ubuntu
ef66b628a2ec90987e89866d357d6b0cca2a9609856bde55c3a836adc536f2d0
xin@xin:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef66b628a2ec ubuntu "/bin/bash" 5 seconds ago Up 4 seconds xenodochial_goodall
xin@xin:~$ docker exec -i ef66b628a2ec bash
pwd
/
xin@xin:~$ docker exec -it ef66b628a2ec bash
root@ef66b628a2ec:/# pwd
/
如果从这个stdin中exit,不会导致容器的停止。所以推荐大家使用docker exec
。
关于更多的参数说明,可以用 docker exec --help
查看。
导出和导入容器
导出容器
如果要导出本地摸个容器,可以使用 docker export
命令。
xin@xin:~$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c222c1b9952 ubuntu "/bin/bash" 36 minutes ago Exited (0) 31 minutes ago gracious_northcutt
xin@xin:~$ docker export 8c222c1b9952 > ubuntu.tar
就这样,将容器快照导出到本地。
导入容器快照
我们可以使用 docker import
从容器快照文件中再导入为镜像,例如:
xin@xin:~$ cat ubuntu.tar | docker import - test/ubuntu:v1.0
sha256:1509081e6319b4064a78fa5cbd89b722ed94401feee77df8b1c0ad13077d5b6a
xin@xin:~$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
test/ubuntu v1.0 1509081e6319 7 seconds ago 69.8MB
此外,也可以通过指定URL或某个目录来导入,例如:
xin@xin:~$ docker import http://example.com/exampleimage.tgz example/imagerepo
注:用户即可以使用 docker load
来导入镜像存储文件到本地镜像库,也可以使用docker import
来导入一个容器快照到本地镜像库。这两则区别在于容器快照文件将丢弃所有的历史记录和元数据信息(仅保存容器但是的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入是可以重新指定标签等元数据信息。
删除容器
想要删除一些不必要的容器时,可以使用docker container rm
或者 docker rm
来删除一个处于终止状态的容器。
xin@xin:~$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c222c1b9952 ubuntu "/bin/bash" About an hour ago Exited (0) About an hour ago gracious_northcutt
xin@xin:~$ docker container rm 8c222c1b9952
8c222c1b9952
如果想要删除一个正在运行的容器,可以添加 -f
参数。docker 会发送 SIGKILL 信号给容器。
xin@xin:~$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
788293c052a9 ubuntu "/bin/bash" 30 seconds ago Up 29 seconds gracious_ramanujan
xin@xin:~$ docker container rm -f 788293c052a9
788293c052a9
清理所有终止状态的容器
当终止状态的容器过多时,通过一个个容器id去删除实在麻烦。我们可以用docker container prune
来清理到所有处于终止状态的容器。
xin@xin:~$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
0fc026fc578ab70993cb4fa33767d619937d2e8f1251f8e96635dc3328d69ebb
fe8f24bd976d2b293c9fdc6543c846967c1697e50a67f0ad46399f47b88b313f
Total reclaimed space: 0B
小结
到目前为止,我们学会了操作容器的一些基本命令:
- 通过docker run来启动容器
- 通过-d参数让容器通过后台运行
- 通过docker container stop 来停止正在运行的容器
- 通过attach或者exec进入容器进行操作
- docker export 导出容器快照,docker import 导入容器快照生成镜像
- docker container rm 删除已终止运行的容器,加上 -f 参数可以终止并且删除正在运行的容器
- docker container prune 可以帮助我们清除所有处于终止状态的容器