Docker容器进入的4种方式

进入Docker容器比较常见的几种做法如下:

  • 使用docker attach
  • 使用SSH
  • 使用nsenter
  • 使用exec

一、使用docker attach进入Docker容器

Docker提供了attach命令来进入Docker容器。
创建一个守护态的Docker容器,然后使用docker attach命令进入该容器。
过程如下:

1
2
3
4
5
6
7
8
9
10
11
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 568c4670fa80 4 weeks ago 109MB
ghost latest dffc1260f5f5 4 weeks ago 814MB
# docker run -itd nginx /bin/bash
85c99fad833008a67114dab7f774e091e7286a58d13278dc984544e18eb5bf91
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
85c99fad8330 nginx "/bin/bash" 5 seconds ago Up 4 seconds 80/tcp cranky_hamilton
# docker attach 85c99fad8330
root@85c99fad8330:/#

可以看到我们已经进入到该容器中了。
但在,使用该命令有一个问题。当多个窗口同时使用该命令进入该容器时,所有的窗口都会同步显示。如果有一个窗口阻塞了,那么其他窗口也无法再进行操作。
因为这个原因,所以docker attach命令不太适合于生产环境,平时自己开发应用时可以使用该命令。

二、使用SSH进入Docker容器

在生产环境中排除了使用docker attach命令进入容器之后,相信大家第一个想到的就是ssh。在镜像(或容器)中安装SSH Server,这样就能保证多人进入容器且相互之间不受干扰了,相信大家在当前的生产环境中(没有使用Docker的情况)也是这样做的。但是使用了Docker容器之后不建议使用ssh进入到Docker容器内。
请参考文章:为什么不需要在 Docker 容器中运行 sshd

三、使用nsenter进入Docker容器

在上面两种方式都不适合的情况下,还有一种比较方便的方法,即使用nsenter进入Docker容器。关于什么是nsenter请参考如下文章:
https://github.com/jpetazzo/nsenter
在了解了什么是nsenter之后,系统默认将我们需要的nsenter安装到主机中
如果没有安装的话,按下面步骤安装即可(注意是主机而非容器或镜像)
下载地址:https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/
选择最新版本,具体的安装命令如下:

1
2
3
4
5
6
wget https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.33/util-linux-2.33.tar.gz
tar -zxvf util-linux-2.33.tar.gz
cd util-linux-2.33
./configure --without-ncurses
make nsenter
cp nsenter /usr/local/bin

安装好nsenter之后可以查看一下该命令的使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# nsenter --help

Usage:
nsenter [options] [<program> [<argument>...]]

Run a program with namespaces of other processes.

Options:
-a, --all enter all namespaces
-t, --target <pid> target process to get namespaces from
-m, --mount[=<file>] enter mount namespace
-u, --uts[=<file>] enter UTS namespace (hostname etc)
-i, --ipc[=<file>] enter System V IPC namespace
-n, --net[=<file>] enter network namespace
-p, --pid[=<file>] enter pid namespace
-C, --cgroup[=<file>] enter cgroup namespace
-U, --user[=<file>] enter user namespace
-S, --setuid <uid> set uid in entered namespace
-G, --setgid <gid> set gid in entered namespace
--preserve-credentials do not touch uids or gids
-r, --root[=<dir>] set the root directory
-w, --wd[=<dir>] set the working directory
-F, --no-fork do not fork before exec'ing <program>

-h, --help display this help
-V, --version display version

For more details see nsenter(1).

连接容器的格式

nsenter --target $PID --mount --uts --ipc --net --pid

容器的PID如何获取

PID=$(docker inspect --format "{{ .State.Pid}}" <container id>)

示例

1
2
3
4
5
6
7
8
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a409b84edf94 nginx "nginx -g 'daemon of…" 50 seconds ago Up 49 seconds 80/tcp nginx02
# docker inspect --format "{{ .State.Pid}}" a409b84edf94
8335
# nsenter --target 8335 --mount --uts --ipc --net --pid
root@a409b84edf94:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

如果觉得查找PID过程麻烦可以使用shell脚本docker-enter,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/sh

if [ -e $(dirname "$0")/nsenter ]; then
# with boot2docker, nsenter is not in the PATH but it is in the same folder
NSENTER=$(dirname "$0")/nsenter
else
NSENTER=nsenter
fi

if [ -z "$1" ]; then
echo "Usage: `basename "$0"` CONTAINER [COMMAND [ARG]...]"
echo ""
echo "Enters the Docker CONTAINER and executes the specified COMMAND."
echo "If COMMAND is not specified, runs an interactive shell in CONTAINER."
else
PID=$(docker inspect --format "{{.State.Pid}}" "$1")
if [ -z "$PID" ]; then
exit 1
fi
shift
OPTS="--target $PID --mount --uts --ipc --net --pid --"
if [ -z "$1" ]; then
# No command given.
# Use su to clear all host environment variables except for TERM,
# initialize the environment variables HOME, SHELL, USER, LOGNAME, PATH,
# and start a login shell.
"$NSENTER" $OPTS su - root
else
# Use env to clear all host environment variables.
"$NSENTER" $OPTS env --ignore-environment -- "$@"
fi
fi

增加执行权限chmod +x docker-enter,运行docker-enter <container id>,这样就进入到指定的容器中。

四、使用docker exec进入Docker容器

除了上面几种做法之外,docker在1.3.X版本之后还提供了一个新的命令exec用于进入容器,这种方式相对更简单一些,下面我们来看一下该命令的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 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
-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

示例

1
2
3
4
5
6
7
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a409b84edf94 nginx "nginx -g 'daemon of…" 24 minutes ago Up 24 minutes 80/tcp nginx02
# docker exec -it a409b84edf94 /bin/bash
root@a409b84edf94:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@a409b84edf94:/#

本文标题:Docker容器进入的4种方式

文章作者:Francis

原始链接:http://www.cnops.com/posts/ada60523.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。