Docker Containers
Container 表示容器,他们彼此是隔离的。Docker 整个使用过程的核心就是对 Container 的生命周期管理。
docker container
通过 docker container
命令来管理容器,它可以包含的子命令包括:
子命令 | 说明 |
---|---|
docker container create | 创建一个新容器 |
docker container run | 创建并运行一个容器 |
docker container start | 运行容器 |
docker container restart | 重新运行容器 |
docker container stop | 停止一个容器 |
docker container stats | 显示容器资源使用情况 |
docker container port | 列出所有发布的端口 |
docker container ls | 列出所有容器 |
docker container rm | 删除容器 |
docker container prune | 删除所有未启动的容器 |
创建并运行容器: container run | container create/start/stop
最常见的创建容器命令就是docker run命令,它是 docker container run
的简写形式,它创建并运行一个容器(相当于 create -> start
,如果映像不存在还会执行 pull):
该命令使用指定的images创建一个容器(container)。
Notes
默认情况下必须 sudo 执行,可以通过配置来实现非 root 用户创建容器
与容器进行交互: -a stdout/stdin/stderr | -it
在终端下交互我们通过 STDIN 来输入、STDOUT 来输出以及 STDERR 来显示错误信息。如果我们想要与容器进行交互就需要将容器内的 stdin/stdout/stderr 附加到当前终端下,而则就可以通过 -a/--attach
来实现:
# echo 输出内容到 stdin,
# 而 -a stdin 将容器的 stdin 附加到终端的 stdin
# 因此实现了 terminal -> docker 的数据传输
echo "test" | docker run -i -a stdin ubuntu cat -
# 下面的示例没有任何输出,除非出现了错误
# 想要看到输出必须附加到 stdout
docker run -a stderr ubuntu echo test
有时候我们希望保持 stdin 一直打开,此时可以通过 -i/--interactive
选项来实现,它能够实现 input 的管道传递:
docker run --rm -i busybox echo "foo bar baz" \
| docker run --rm -i busybox awk '{ print $2 }' \
| docker run --rm -i busybox rev
rab
-i
通常还会与 -t/--tty
一起使用来将容器的伪终端和当前控制台 I/O 绑定,实现真正的容器环境的交互式会话:
Note
单独使用 -t
,这样容器仍然会被分配一个伪 TTY 但是无法写入 stdin,表现就是执行命令没有输出。唯一可能有用的情况就是哈容器的输出需要 tty 环境
后台运行: -d/--detach
启动容器时,默认在前台运行(此时要想交互需要 -it
),如果想要更改容器为后台运行需要使用 -d/--detach
命令:
$ docker run -d nginx
0246aa4d1448a401cabd2ce8f242192b6e7af721527e48a810463366c7ff54f1
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0246aa4d1448 nginx "/docker-entrypoint.â¦" 2 seconds ago Up 1 second 80/tcp pedantic_liskov
$ docker logs -n 5 0246aa4d1448
2023/11/06 15:58:23 [notice] 1#1: start worker process 33
2023/11/06 15:58:23 [notice] 1#1: start worker process 34
2023/11/06 15:58:23 [notice] 1#1: start worker process 35
2023/11/06 15:58:23 [notice] 1#1: start worker process 36
2023/11/06 15:58:23 [notice] 1#1: start worker process 37
$ docker attach 0246aa4d1448
^C
2023/11/06 15:58:40 [notice] 1#1: signal 2 (SIGINT) received, exiting
...
Note
docker container attach CONTAINER
用于将后台运行的容器连接到 stdin stdout 和 stderr
不阻塞命令的后台运行
有时候我们启动容器即使指定了 -d
但是 docker ps
后依然没有看到正在运行的容器,这是因为运行的命令是非阻塞的。例如 ping bash
等都属于这种情况。容器在命令执行完毕后一定是会推出的,即使位于后台:
# bash 是非阻塞命令他运行后自动推出
docker run -d debian bash
# sleep 阻塞 9999 秒,在 sleep 完成前不会退出
docker run -d debian sleep 9999
而对于 bash 还比较特殊,如果它连接到虚拟终端就不会自动退出,因此如果执行:
Tips
还有就是如果我们 docker run -it debian bash
即在前台运行了一个命令,如果想要让他切换到后台可以执行 chtl + p + q
命令执行: COMMAND/--entrypoint
运行容器核心是为了运行某个命令,它可以直接在后面通过 [COMMAND]
来指定。
Tips
默认情况下会执行 Dockerfile 文件中的 CMD 指令,[COMMAND]
实际上覆盖这个 CMD 指令
还有一个称为入口点的概念,可以通过 --entrypoint
选项来指定,该参数必须包含一个字符串值,他就是我们要在容器中运行的命令,并且 CMD/[COMMAND]
将作为参数附加到 ENTYPOINT 上。
Tips
实际上就是 Dockerfile 中的 ENTRYPOINT 指令,类似于 CMD 指令
工作目录: -w/--workdir
容器中运行命令默认的工作目录是根目录(/
),可以通过-w/--workdir
来设置其他目录作为工作目录:
Tips
在 Dockerfile 中使用 WORKDIR 指令设置工作目录
设置环境变量: -e
Docker 在创建 Linux 容器时会自动设置一些环境变量:
HOME
: 根据 USER 设置HOSTNAME
: 与容器关联的主机名PATH
: 包括常用的运行目录(/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
)TERM
: 如果为容器分配了伪 tty 该环境变量是xterm
此外还可以使用一个或多个 -e
来在容器中设置任何环境变量,甚至能够覆盖上述变量:
export today=Wednesday
docker run -e "deep=purple" -e today --rm alpine env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=d2219b854598
deep=purple
today=Wednesday
HOME=/root
Tips
在 Dockerfile 中使用 ENV 指令设置环境变量
自动启动容器: --restart
可以使用 --restart
来定义如何自动重启容器:
no
: 不自动重启,这也是默认行为on-failure[:max-retries]
: 如果容器因为错误而退出,请自动重启容器。其中可选的max-retries
来限制重启的次数always
: 如果容器停止,请始终重启容器。有个特殊情况就是如果手动停止了容器,这仅当 Docker 守护进程重新启动或手动启动容器本身才会重新启动unless-stopped
: 如果容器停止,请始终重启容器,这与 always 是一样的。区别在于如果手动停止了容器,即使 Docker 守护进程重新启动也不会重新启动。也就是说手动停止也必须手动启动
手动启动容器: container start
手动启动停止的容器最核心的就是需要知道停止的容器,这可以使用 docker ps --all
来实现。
Tips
容器启动本质上就是重新运行了 docker run [cmd]
命令。
其他
还有一些容器的其他设置参数:
显示容器资源使用: container stats
docker container stats
命令返回正在运行的容器的实时资源数据流:
$ docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
b95a83497c91 awesome_brattain 0.28% 5.629MiB / 1.952GiB 0.28% 916B / 0B 147kB / 0B 9
67b2525d8ad1 foobar 0.00% 1.727MiB / 1.952GiB 0.09% 2.48kB / 0B 4.11MB / 0B 2
e5c383697914 test-1951.1.kay7x1lh1twk9c0oig50sd5tr 0.00% 196KiB / 1.952GiB 0.01% 71.2kB / 0B 770kB / 0B 1
4bda148efbc0 random.1.vnc8on831idyr42slu578u3cr 0.00% 1.672MiB / 1.952GiB 0.08% 110kB / 0B 578kB / 0B 2
删除容器: --rm | container rm | container prune
在 container run --rm
能够在运行完容器后删除与容器关联的匿名卷。类似的标准操作就是 docker container rm -v my-container
。
Tips
这个通常是用来调试使用的,注意它只能删除匿名卷,对于命名卷来说必须手动删除
而 docker container prune
能够删除所有已停止的容器。
在运行的容器中执行命令: container exec
如果想要在正在运行的容器中运行新命令:
docker exec -d mycontainer touch /tmp/execWorks
# 甚至可以直接执行交互式 shell
docker exec -it mycontainer sh
需要注意的是命令必须是可执行文件,而不能是 chained 命令:
# 不起作用
docker exec -it my_container "echo a && echo b"
# 正在应该
docker exec -it my_container sh -c "echo a && echo b"
该命令默认会在容器的默认工作目录上执行,并且使用默认环境变量,此时可以通过一些参数来修改:
-e/--env
: 设置环境变量-w/--workdir
: 设置工作目录
列出所有容器: container ls
docker container ls用于列出所用容器,他有一个非常常见的别名就是 docker ps
:
(own) yangguodong@debian:~/Documents/pycrawler/google_patent$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTSNAMES
53b52cd3d054 mzz2017/v2raya "v2raya" 3 weeks ago Up 2 hours 0.0.0.0:2017->2017/tcp, :::2017->2017/tcp, 0.0.0.0:20170-20172->20170-20172/tcp, :::20170-20172->20170-20172/tcpv2raya
Tips
默认情况下他会列出正在运行的命令,如果想要列出所有的需要指定 --all
参数,其中的 STATUS 会指出他们的状态。这在启动停止的容器时很有用。