LXX的网络日志
人因梦想而伟大
Docker-02-操作Docker容器

操作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 可以帮助我们清除所有处于终止状态的容器