容器
容器是 Docker 的另一个核心概念。简单来说,容器是镜像的一个运行实例。
所不同的是,镜像是静态的只读文件,而容器带有运行时需要的可写文件层,同时,容器中的应用进程处于运行状态。
如果认为虚拟机是模拟运行的一整套操作系统(包括内核、应用运行态环境和其他系统环境)和跑在上面的应用。
那么 Docker 容器就是独立运行的一个(或一组)应用,以及它们必须的运行环境。
创建容器
新建容器
可以使用docker [container] create
命令新建一个容器,例如
1 2 3 4 5 |
|
使用docker [container] create
命令新建的容器处于停止状态,可以使用docker [container] start
命令来启动它
由于容器是整个 Docker 技术栈的核心,create 命令和后续的 run 命令支持的选项都十分复杂,需要在实践中不断体会。
选项主要包括如下几大类:与容器运行模式相关、与容器环境配置相关、与容器资源限制和安全保护相关
create 命令与容器运行模式相关的选项
选项 | 说明 |
---|---|
-a, --attach=[] |
是否绑定到标准输入、输出和错误 |
-d, --detach=true|false |
是否在后台运行容器,默认为否 |
--detach-keys="" |
从 attach 模式退出的快捷键 |
--entrypoint="" |
镜像存在入口命令时,覆盖为新的命令 |
--expose=[] |
指定容器会暴露出来的端口或端口范围 |
--group-add=[] |
运行容器的用户组 |
-i, --interactive=true|false |
保持标准输入打开,默认为 false |
--ipc="" |
容器 IPC 命名空间,可以为其他容器或主机 |
--isolation="default" |
容器使用的隔离机制 |
--log-driver="json-file" |
指定容器的日志驱动类型,可以为json-file、syslog、journald、gelf、fluentd、awslogs、splunk、etwlogs、gcplogs 或 none |
--log-opt=[] |
传递给日志驱动的选项 |
--net="bridge" |
指定容器网络模式,包括 bridge、none、其他容器内网络、host的网络或某个现有网络等 |
--net=alias=[] |
容器在网络中的别名 |
-p, --publish-all-true|false |
通过NAT机制将容器标记暴露的端口自动映射到本地主机的临时端口 |
-p, --publish=[] |
指定如何映射到本地主机端口,例如 -p 11234-12234:1234-2234 |
--pid=host |
容器的 PID 命名空间 |
--userns="" |
启动 userns-remap 时配置用户命名空间的模式 |
--uts=host |
容器的 UTS 命名空间 |
--restart="no" |
容器的重启策略,包括 no、on-failure[:max-retry]、always、unless-stopped 等 |
--rm, --rm=true|false |
容器退出后是否自动删除,不能跟 -d 同时使用 |
-t, --tty=true|false |
是否分配一个伪终端,默认为 false |
--tmpfs=[] |
挂在临时文件系统到容器 |
-v|--volume[=[HOST-DIR:]CONTAINER-DIR[:OPTIONS]]] |
挂载主机上的文件卷到容器内 |
--volume-driver="" |
挂载文件卷的驱动类型 |
--volumes-from=[] |
从其他容器挂载卷 |
-w, --workdir="" |
容器内的默认工作目录 |
create 命令与容器环境和配置相关的选项
选项 | 说明 |
---|---|
--add-host=[] |
在容器内添加一个主机名到 IP 地址的映射关系(通过/etc/hosts文件) |
--device=[] |
映射物理机上的设备到容器内 |
--dns-search=[] |
DNS搜索域 |
--dns-opt=[] |
自定义的 DNS 选型 |
--dns=[] |
自定义的 DNS 服务器 |
-e, --env=[] |
指定容器内的环境变量 |
--env-file=[] |
从文件中读取环境变量到容器内 |
-h, --hostname="" |
指定容器内的容器内 |
--ip="" |
指定容器的 IPv4 地址 |
--ip6="" |
指定容器的 IPv6 地址 |
--link=[<name or id>:alias] |
链接到其他容器 |
--link-local-ip=[]: |
容器的本地链接地址列表 |
--mac-address="" |
指定容器的 Mac 地址 |
--name="" |
指定容器的别名 |
启动容器
使用docker [container] start
命令来启动一个已经创建的容器。
1 2 3 4 5 6 7 8 |
|
新建并启动容器
除了创建容器后通过 start 命令来启动,也可以直接新建并启动容器
所需要的命令主要为docker [comntainer] run
,等价于先执行docker [container] create
命令,再执行docker [container] start
命令。
例如,下面的命令输出一个"Hello World"
,之后容器自动终止:
1 2 |
|
这跟在本地直接执行/bin/echo 'hello world'
相比几乎感觉不出任何区别
当利用docker [container] run
来创建并启动容器时,Docker 在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建一个容器,并启动该容器
- 分配一个文件系统给容器,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从网桥的地址池配置一个 IP 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被自动终止
下面的命令启动一个 bash 终端,允许用户进行交互:
1 2 |
|
其中,-t
选项让 Docker 分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上,-i
则让容器的标准输入保持打开。
更多的命令选项可以通过docker run --help
命令来查看
在交互模式下,用户可以通过所创建的终端来输入命令,例如:
1 2 3 4 5 6 7 8 |
|
在容器内用 ps 命令查看进程,可以看到,只运行了 bash 应用,并没有运行其他无关的进程。
用户可以按Ctrl + d
或输入exit
命令来退出容器:
1 2 |
|
对于所创建的 bash 容器,当用户使用exit
命令退出 bash 进程之后,容器也会自动退出。
这是因为对于容器来说,当其中的应用退出后,容器的使命完成,也就没有继续执行的必要了
可以使用docker container wait CONTAINER[CONTAINER...]
子命令来等待容器退出,并打印退出返回结果。
某些时候,执行docker [container] run
时候因为命令无法正常执行容器会出错直接退出,此时可以查看退出的错误代码。
默认情况下,常见的错误代码包括:
- 125: Docker daemon 执行出错,例如指定了不支持的 Docker 命令参数
- 126: 所指定命令无法执行,例如权限出错
- 127: 容器内命令无法找到
命令执行后出错,会默认返回命令的退出错误码
守护态运行
更多的时候,需要让 Docker 容器在后台以守护态形式运行。
此时,可以通过添加-d
参数来实现。
例如,下面的命令会在后台运行容器:
1 2 |
|
容器启动后会返回一个唯一的 id,也可以通过docker ps
或docker container ls
命令来查看容器信息
查看容器输出
要获取容器的输出信息,可以通过docker [container] logs
命令。
该命令支持的选项包括:
-details
: 打印详细信息-f, -follow
: 持续保持输出-since string
:输出从某个时间开始的日志-tail string
: 输出最近的若干日志-t, -timestamps
: 显示时间戳信息-until string
: 输出某个时间之前的日志
例如,查看某容器的输出可以使用如下命令:
1 2 3 4 5 6 7 |
|
停止容器
暂停容器
可以使用docker [container] pause CONTAINER[CONTAINER...]
命令来暂停一个运行中的容器。
例如,启动一个容器,并将其暂停:
1 2 3 4 5 6 7 8 9 |
|
处于 paused 状态的容器,可以使用docker [container] unpause CONTAINER[CONTAINER...]
命令来恢复到运行状态。
1 2 3 |
|
终止容器
可以使用docker [container] stop
来终止一个运行中的运行中的容器。
该命令的格式为docker [container] stop [-t| --time[=10]][CONTAINER...]
该命令会首先向容器发送 SIGTERM 信号,等待一段超时时间后(默认为 10 秒),再发送 SIGKILL 信号来终止容器
1 2 3 4 5 |
|
此时,执行docker container prune
命令,会自动清除掉所有处于停止状态的容器
此外,还可以通过docker [container] kill
直接发送 SIGKILL 信号来强行终止容器
当 Docker 容器中指定的应用终结时,容器也会自动终止。
对于启动了一个终端的容器,用户通过 exit 命令或Ctrl + d
来退出终端时,所创建的容器立刻停止,处于stopper
状态
可以用docker ps -qa
命令看到所有容器的 ID。例如:
1 2 |
|
处于停止状态的容器,可以通过docker [container] start
命令来重新启动:
docker [container] restart
命令会将一个运行态的容器先终止,然后再重新启动
进入容器
在使用-d
参数时,容器启动后会进入后台,用户无法看到容器中的信息,也无法进行操作。
这个时候如果需要进入容器进行操作,推荐使用官方的attach
或exec
命令。
attach 命令
attach 是 Docker 自带的命令,命令格式为:
docker [container] attach [--detach-keys[=[]]] [--no-stdin] [--sig-proxy[=true]] CONTAINER
这个命令支持三个主要选项:
--detach-keys[=[]]
: 指定退出 attach 模式的快捷键序列,默认是CTRL -p CRTL -q
--no-stdin=true|false
: 是否关闭标准输入,默认是保持打开--sig-proxy=true|false
: 是否代理收到的系统信号给应用进程,默认为 true
示例:
1 2 3 4 5 6 7 |
|
然而使用 attach 命令有时候并不方便。
当多个窗口同时 attach 到同一个容器的时候,所有窗口都会同步显示;
当某个窗口因命令阻塞时,其他窗口也无法执行操作了
exec 命令
从 Docker 的 1.3.0 版本起,Docker 提供了一个更加方便的工具exec
命令,可以在运行中容器内直接执行任意命令。
该命令的基本格式为:
docker [container] exec [-d|--detach] [--detach-key[=[]] [-i|--interactive] [--privileged] [-t|--tty] [-u|--user[=USER]] CONTAINER COMMAND [ARG...]
比较重要的参数有:
-d, --detach
: 在容器中后台执行命令--detach-keys=""
: 指定将容器切回后台的按键-e, --env=[]
: 指定环境变量列表-i, --interactive=true|false
: 打开标准输入接受用户输入命令,默认值为 false--privileged=true|false
: 是否给执行命令以高权限,默认值为 false-t, --tty=true|false
: 分配伪终端,默认值为false-u, --user=""
: 执行命令的用户名或 ID
例如,进入到刚创建的容器中,并启动一个 bash
1 2 3 4 5 |
|
可以看到会打开一个新的 bash 终端,在不影响容器内其他应用的前提下,用户可以与容器进行交互
注意:
通过指定-it
参数来保持标准输入打开,并且分配一个伪终端。
通过exec
命令对容器执行操作是最为推荐的方式
进一步地,可以在容器中查看用户和进程信息:
1 2 3 4 5 6 7 8 |
|
删除容器
可以使用docker [container] rm
命令来删除处于终止或退出状态的容器,命令格式为docker [container] rm [-f|--force] [-l|--link] [-v|--volumes] CONTAINER [CONTAINER...]
主要支持的选项包括:
-f, --force=false
: 是否强行终止并删除一个运行中的容器-l, --link=false
: 删除容器的连接,但保留容器-v, --volumes=false
: 删除容器挂载的数据卷。
例如,查看处于终止状态的容器,并删除
1 2 3 4 5 |
|
默认情况下,docker rm
命令只能删除已经处于终止或退出状态的容器,并不能删除还处于运行状态的容器。
如果要直接删除一个运行中的容器,可以添加-f
参数。
Docker 会先发送SIGKILL
信号给容器,终止其中的应用,之后强行删除
1 2 3 4 5 6 |
|
1 2 3 |
|
容器与本地拷贝文件
https://docs.docker.com/engine/reference/commandline/cp/
1 2 |
|
导入和导出容器
某些时候,需要将容器从一个系统迁移到另外一个系统,此时可以使用 Docker 的导入和导出功能,这也是 Docker 自身提供的一个重要特性
导出容器
导出容器是指,导出一个已经创建的容器到一个文件,不管此时这个容器是否处于运行状态。
可以使用docker [container] export
命令,该命令格式为
docker [container] export [-o|--output[=""]] CONTAINER
其中,可以通过-o
选项来指定导出的tar
文件名,也可以直接通过重定向来实现
首先,查看所有的容器,如下所示:
1 2 3 |
|
导出27cdfbff5999
容器到文件test_for_run.tar
1 2 3 |
|
之后,可将导出的 tar 文件传输到其他机器上,然后再通过导入到系统中,实现如果容器的迁移