jk's notes
  • 第04章 操作 Docker 容器

第04章 操作 Docker 容器

容器是镜像的一个运行实例.

4.1 创建容器

主要介绍 create, start, run, logs 子命令.

1. 新建容器

可以使用 docker [container] create 命令新建一个容器.

jk@jk-System-Product-Name:~$ docker create -it ubuntu:latest
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
7b1a6ab2e44d: Pull complete
Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322
Status: Downloaded newer image for ubuntu:latest
1eddb92809ff2aae01d8e3857db2ea823719a62358de156ea17dce76e57d680e
jk@jk-System-Product-Name:~$ docker ps -a
CONTAINER ID   IMAGE           COMMAND   CREATED          STATUS    PORTS     NAMES
1eddb92809ff   ubuntu:latest   "bash"    14 seconds ago   Created             strange_kapitsa

上述命令在本地未发现 ubuntu:latest, 然后自动下载了镜像, 然后创建容器.

创建的容器为停止状态. 使用命令 docker [container] start 来启动它.

create 命令与 run 命令可用选项非常多. 可以使用 --help 来查看.

书 P40

2. 启动容器

命令 docker [container] start 来启动一个已经创建的容器.

可以在 docker ps 中查看正在运行的容器.

3. 新建并启动容器

可以直接使用 run 子命令. 其背后逻辑为:

  1. 检查本地是否存在镜像, 若不存在从仓库下载
  2. 利用镜像创建一个容器, 并启动该容器
  3. 分配一个文件系统给容器, 并在只读镜像层外面挂载一层可读可写层
  4. 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中
  5. 从网桥地址池配置一个 IP 地址给容器
  6. 执行用户指定的应用程序
  7. 执行完毕后容器被自动终止
$ docker run -it ubuntu:18.04 /bin/bash

其中 -t 是让 Docker 为其分配一个伪终端 (pseudo-tty), 并绑定到容器上.

-i 则是让容器的标准输入保持打开.

在交互模式下, 执行 exit 退出 bash 后, 容器中没有运行程序也会自动退出.

可以使用 docker containert wait 容器 [容器 ...] 子命令来等待容器退出, 并打印返回结果.

执行 docker run 无法正常启动, 可查看退出的错误代码, 可能的代码错误

  • 125: Docker Daemon 执行出错, 例如参数不正确
  • 126: 命令无法执行, 例如无权限
  • 127: 容器内命令无法找到

4. 守护态运行

利用参数 -d 进入守护态.

$ docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done" 

容器会返回一个唯一的 ID, 或使用 docker ps 或 docker container ls 来查看.

5. 查看容器输出

命令 docker logs 容器ID

jk@jk-System-Product-Name:~$ docker logs --help

Usage:  docker logs [OPTIONS] CONTAINER

Fetch the logs of a container

Options:
      --details        Show extra details provided to logs
  -f, --follow         Follow log output
      --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m
                       for 42 minutes)
  -n, --tail string    Number of lines to show from the end of the logs (default "all")
  -t, --timestamps     Show timestamps
      --until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g.
                       42m for 42 minutes)

4.2 停止容器

涉及命令有: pause / unpause, stop 和 prune

1. 暂停容器

可以使用 docker [container] pause 容器 [容器 ...] 来暂停容器.

使用 docker [container] unpause 容器 [容器 ...] 来将暂停的容器恢复到运行状态.

2. 终止容器

使用命令

docker [container] stop [-t|--time[=10]] [容器 ...]

来终一个运行中的容器.

该命令首先向容器发送 SIGTERM 信号, 等一段超时时间后 (默认 10 秒), 在发送 SIGKILL 信号来终止容器.

容器中无程序运行或程序退出后也会处于终止状态.

可以使用 docker ps -qa 查看所有容器 ID. 可以再使用 start 对容器启动.

重启命令 docker [container] restart 容器 可以将容器先停止, 再启动.

4.3 进入容器[重点]

使用参数 -d 进入后台, 需要进入容器, 可以使用 attach 或 exec 命令

1. attach 命令

命令格式为:

docker [container] attach [--detach-keys[=[]]] [--no-stdin] [--sig-proxy[=true]] 容器

其中三个主要选项表示

  • --detach-keys[=[]] 指定退出 attach 模式的快捷键序列. 默认为 CTRL-p CTRL-q.
  • --no-stdin=true|false 是否关闭标准输入. 默认是保持打开.
  • --sig-proxy=true|false 是否代理收到的系统信号给应用程序进程, 默认为 true.

当多个窗口同时 attach 到同一个容器时, 所有窗口会同步显示, 当某个窗口被命令阻塞时, 其他窗口也无法使用.

image-20220704163135250

2. exec 命令 [推荐使用]

从 Docker 1.3.0 开始支持, 其命令格式为

docker [container] exec 
	[-d|--detach] 
	[--detach-keys[=[]]] 
	[-i|--interactive] 
	[--privileged] 
	[-t|--tty] 
	[-u|--user[=USER]] 
	容器 [ARG ...]

比较重要的参数有:

  • -d, --detach: 在容器中后台执行命令
  • --detach-keys: 指定将容器切回后台的按键
  • -e, --env=[]: 指定环境变量列表
  • -i, --interactive=true|false: 打开标准输入接收用户输入命令, 默认为 false
  • --privileged=true|false: 是否给执行命令最高权限, 默认为 false
  • -t, --tty=true|false: 分配伪终端. 默认 false
  • -u, --user=: 执行命令的用户名

例如:

$ docker exec -it 容器ID /bin/bash

这样就会开启一个新的终端, 可在其与容器交互, 并不影响其他连接.

image-20220704164355952

完整语法为:

jk@jk-System-Product-Name:~$ docker exec --help

Usage:  docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

Run a command in a running container

Options:
  -d, --detach               Detached mode: run command in
                             the background
      --detach-keys string   Override the key sequence for
                             detaching a container
  -e, --env list             Set environment variables
      --env-file list        Read in a file of environment
                             variables
  -i, --interactive          Keep STDIN open even if not attached
      --privileged           Give extended privileges to the
                             command
  -t, --tty                  Allocate a pseudo-TTY
  -u, --user string          Username or UID (format:
                             <name|uid>[:<group|gid>])
  -w, --workdir string       Working directory inside the
                             container

4.4 删除容器

使用 docker [container] rm 来删除处于终止或退出状态的容器. 命令格式为:

jk@jk-System-Product-Name:~$ docker rm --help

Usage:  docker rm [OPTIONS] CONTAINER [CONTAINER...]

Remove one or more containers

Options:
  -f, --force     Force the removal of a running container
                  (uses SIGKILL)
  -l, --link      Remove the specified link
  -v, --volumes   Remove anonymous volumes associated with
                  the container

默认无法删除正在运行的, 但是加上参数 -f 则先发送信号 SIGKILL, 待容器终止后删除.

4.5 导入和导出容器

将一个容器从一个系统中迁移到另一个系统中使用 [是不是可以看成备份???]

1. 导出容器

将容器导出到文件中, 无论是否处于运行状态.

jk@jk-System-Product-Name:~$ docker export --help

Usage:  docker export [OPTIONS] CONTAINER

Export a container's filesystem as a tar archive

Options:
  -o, --output string   Write to a file, instead of STDOUT

导出的文件, 可以拷贝到其他机器中再导入运行.

2. 导入容器

使用命令 docker import 来导入容器, 使其称为镜像.

jk@jk-System-Product-Name:~$ docker import --help

Usage:  docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

Import the contents from a tarball to create a filesystem image

Options:
  -c, --change list       Apply Dockerfile instruction to the created image
  -m, --message string    Set commit message for imported image
      --platform string   Set platform if server is multi-platform capable

4.6 查看容器

主要介绍 inspect, top 和 stats 子命令.

1. 查看容器详情

使用 docker inspect 容器 来查看容器内容

jk@jk-System-Product-Name:~$ docker inspect --help

Usage:  docker inspect [OPTIONS] NAME|ID [NAME|ID...]

Return low-level information on Docker objects

Options:
  -f, --format string   Format the output using the given Go template
  -s, --size            Display total file sizes if the type is container
      --type string     Return JSON for specified type

2. 查看容器内进程

使用 docker top 容器 来查看

jk@jk-System-Product-Name:~$ docker top --help

Usage:  docker top CONTAINER [ps OPTIONS]

Display the running processes of a container

3. 查看统计信息

使用命令 docker stats 容器 来显示统计信息.

jk@jk-System-Product-Name:~$ docker stats --help

Usage:  docker stats [OPTIONS] [CONTAINER...]

Display a live stream of container(s) resource usage statistics

Options:
  -a, --all             Show all containers (default shows just running)
      --format string   Pretty-print images using a Go template
      --no-stream       Disable streaming stats and only pull the first result
      --no-trunc        Do not truncate output

4.7 其他容器命令 [暂略]

4.8 本章小结 [略]

第05章 访问 Docker 仓库 [暂略]

第06章 Docker 数据管理

生产环境中会对数据进行持久化. 并且需要在不同容器之间共享数据. 那么就需要在容器外部管理数据.

容器中的数据管理有两种方式:

  1. 数据卷 (Data Volumes): 容器中的数据直接映射到本地主机环境.
  2. 数据卷容器 (Data Volume Containers): 使用特定容器维护数据卷.

本章首先介绍数据卷, 然后介绍数据卷容器, 并在主机, 容器之间共享数据, 并实现数据的备份与恢复.

6.1 数据卷 [重要]

数据卷是供容器使用的特殊目录. 将主机操作系统目录直接映射进容器. 类似于 Linux 中的 mount 行为.

数据卷让数据与容器解耦

1. 创建数据卷

docker 提供了 volume 子命令来管理数据卷.

jk@jk-System-Product-Name:~$ docker volume --help

Usage:  docker volume COMMAND

Manage volumes

Commands:
  create      Create a volume
  inspect     Display detailed information on one or more volumes
  ls          List volumes
  prune       Remove all unused local volumes
  rm          Remove one or more volumes

Run 'docker volume COMMAND --help' for more information on a command.

使用下面命令可以快速的在本地创建一个数据卷:

$ docker volume create -d local test
test

可以在 /var/lib/docker/volumes/ 目录下查看所创建的数据卷.

可以使用 docker volume rm 删除数据卷.

使用 docker volume prune 清除未用的数据卷

使用 docker volume inspect 来查看数据卷信息

使用 docker volume ls 列出所有数据卷

2. 绑定数据卷

除了使用 volume 来管理数据卷外, 还可以在创建容器的时将主机本地的任意路径挂载到容器内作为数据卷. 即为 绑定数据卷.

在使用 docker run 命令时, 可以使用 -mount 选项来使用数据卷. 该选项支持三种数据卷:

  1. volume 普通数据卷. 映射到主机 /var/lib/docker/columes 路径下.
  2. bind 绑定到数据卷. 映射到制定路径下.
  3. tmpfs 临时数据卷. 只存在于内存中.

案例 该案例为作者提供:

使用 training/webapp 镜像创建一个 web 容器, 并创建一个数据卷挂载到容器的 /opt/webapp 目录

$ docker run -d -P --name web --mount type=bind,source=/webapp,destination=/opt/webapp training/webapp python app.py

上述命令等同于早期的 -v 选项, 在容器内创建一个数据卷

$ docker run -d -P --name web -v /webapp:/opt/webapp training/webapp python app.py

这个功能在测试的时候十分方便.

需要注意: 本地目录路径必须使用绝对路径, 容器内可以使用相对路径. 若目录不存在, docker 会创建目录.

Docker 挂载的数据卷默认为读写 (rw), 可以使用 ro 设置为只读.

$ docker run -d -P --name web -v /webapp:/opt/webapp:ro training/webapp python app.py

如此, 容器内对所挂数据卷内的数据就无法修改了.

推荐挂载目录, 而不是文件.

在 docker 中运行一个 ubuntu:latest, 然后将 /home/webapp 目录与本地 /webapp 绑定在一起.

$ docker run -dit --name ubuntu-web-server --mount type=bind,source=/webapp,destination=/home/webapp ubuntu:latest /bin/bash

image-20220705151805364

进入 docker 中 /home 目录下可以看到 webapp 已被创建. 现在, 在该目录下做的所有操作, 都会映射到主机的 /webapp 目录中.

image-20220705152018712

image-20220705152131719

6.2 数据卷容器

一般用在多个容器间数据共享. 数据卷也是一个容器, 其作用是专门提供数据卷给其他容器挂载.

例子, 创建一个数据卷容器 dbdata, 并在其中创建一个数据卷挂载到 /dbdata:

jk@jk-System-Product-Name:~$ docker run -it -v /dbdata --name dbdata ubuntu
root@2454ba698668:/# ls
bin   dbdata  etc   lib    lib64   media  opt   root  sbin  sys  usr
boot  dev     home  lib32  libx32  mnt    proc  run   srv   tmp  var
root@2454ba698668:/#

进入容器后, 可以查看本地目录.

疑惑

  1. -v 带有形如 path1:path2 的参数, path1 为本地目录, path2 为容器中的目录[正解]
  2. -v 仅带有形如 path 的参数, 表示容器中的目录???

在其他容器中要使用数据卷容器 dbdata, 则使用 --volumes-from 来引用数据卷容器.

下面创建 db1 和 db2 两个容器, 并从 dbdata 容器挂载数据卷

$ docker run -it --volumes-from dbdata --name db1 ubuntu
$ docker run -it --volumes-from dbdata --name db2 ubuntu

此时有三个容器在运行: dbdata, db1, db2. 并且任何一个容器在 /dbdata 中写下数据, 其他两个容器都可以看到变化.

可以多次使用 --volumes-from 从多个容器挂载数据卷. 还可以从其他已经挂载了数据卷的容器来挂载数据卷.

注意:

  1. 提供数据卷的容器不必保持运行状态.
  2. 删除挂载容器, 数据卷容器不会自动删除. 若要关联删除, 需要在删除最后一个容器时, 使用 -v 参数. [怎么用?]

6.3 利用数据卷来迁移数据

可以利用数据卷容器对其中的数据卷进行备份, 恢复, 来实现数据的迁移.

数据卷是存数据的地方.

数据卷容器, 为数据卷提供了一个容器空间. 可以将其想象成一个文件服务器.

1. 备份

使用下面的命令来备份 dbdata 数据卷容器内的数据卷:

$ docker run --volumns-from dbdata -v $(pwd):/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata

解释

  • 首先利用 ubuntu 镜像创建了一个 docker 容器 worker
  • 使用 --volumes-from dbdata 表示挂载容器卷
  • -v $(pwd):/backup 表示将本地的当前目录与容器的 /backup 目录绑定
  • 启动容器后, 执行 tar cvf /backup/backup.tar /dbdata 将 /dbdata 目录打包到 /backup/back.tar 中

备份实际上就是利用数据卷共享这一特征, 将数据卷容器中的数据卷打包成一个压缩文件.

不过直接将本地目录作为共享目录, 压缩本地目录似乎一样.

或许在大面积集群等特殊逻辑中有用吧.

2. 恢复

恢复数据到换一个容器, 可以按照下面步骤.

  • 首先创建一个带有数据卷的容器 dbdata2.
  • 然后创建一个新容器挂载这个带有数据卷的容器.
  • 同时在这个新容器中使用 untar 解压备份文件到所挂载容器卷中
$ docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
$ docker run --volumns-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar

创建数据卷容器, 并用本地 /dbdata 目录作为数据卷

然后运行一个新容器, 挂载该数据卷容器, 即可在本地操作 /dbdata

然后解压文件, 使得数据卷容器可用

6.4 本章小结 [略]

Last Updated:
Contributors: jk