对于运行在后台的Docker容器,我们运维人员时常是有登陆进去的需求。登陆Docker容器的方式:
1)使用ssh登陆容器。这种方法需要在容器中启动sshd,存在开销和攻击面增大的问题。同时也违反了Docker所倡导的一个容器一个进程的原则。 参考Docker容器学习梳理--SSH方式登陆容器
2)使用自带命令docker attach登陆容器。命令格式:docker attach container_id。不过docker attach存在的问题是:当多个窗口同时attach到同一个容器时,所有的窗口都会同步的显示,假如其中的一个窗口发生阻塞时,其它的窗口也会阻塞,docker attach命令可以说是最不方便的进入后台docker容器的方法。
3)使用自带命令docker exec登陆容器。命令格式:docker exec -ti container_id /bin/bash。docker exec和docker attach是Docker的原生方法,大多数情况下就使用这两种命令登陆容器。docker exec命令是在docker1.3之后出现的,比docker attach命令更加方便!两者之间的区别:
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
1.Docker attach必须是登陆到一个已经运行的容器里。需要注意的是如果从这个容器中
exit
退出的话,就会导致容器停止!!这是极其不方便的!
[root@localhost ~]
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2faf24118766 192.168.1.23:5000
/tomcat7
"/bin/bash"
4 days ago Up About an hour 0.0.0.0:8888->8080
/tcp
tomcat
[root@localhost ~]
# docker attach tomcat
[root@2faf24118766 /]
# exit //按住ctrl+d退出当前窗口
[root@localhost ~]
# docker ps //发现该容器也停止了!!
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2.docker
exec
登陆容器,注意有两个参数:-t和-i,这两个参数很重要!
1)如果只用-i时,由于没有分配伪终端,看起来像pipe执行一样。但是执行结果、命令返回值都可以正确获取。
这种方式可以理解为:在运行的容器上执行新进程!即在宿主机上执行容器里的命令并查看到命令结果!这很方便的~但是仅仅使用-i参数无法直接登陆到容器内!
[root@localhost ~]
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2faf24118766 192.168.1.23:5000
/tomcat7
"/bin/bash"
4 days ago Up About a minute 0.0.0.0:8888->8080
/tcp
tomcat
[root@localhost ~]
# docker exec -i tomcat date
Sat Apr 1 06:53:46 UTC 2017
[root@localhost ~]
# docker exec -i tomcat uptime
06:54:44 up 163 days, 23:28, 0
users
, load average: 0.00, 0.01, 0.05
[root@localhost ~]
# docker exec -i tomcat /usr/local/tomcat7/bin/startup.sh
Tomcat started.
2)如果只使用-t参数,则可以看到一个console窗口,可以在宿主机上执行容器里的命令并查看到命令结果,但是这种方式登陆到容器内执行的命令是没有结果信息输出的!
[root@localhost ~]
# docker exec -t tomcat uptime
07:02:38 up 163 days, 23:36, 0
users
, load average: 0.00, 0.02, 0.05
[root@localhost ~]
# docker exec -t tomcat pwd
/
[root@localhost ~]
# docker exec -t tomcat /bin/bash //注意,使用-t参数登陆容器,退出当前窗口用的是ctrl+c而不是ctrl+d;而下面使用-ti参数,退出当前窗口使用ctrl+d
[root@2faf24118766 /]
# uptime //仅仅使用-t参数登陆容器内,发现执行命令后,没有结果输出!
3)使用-it时,则和我们平常操作console界面类似,而且不会像attach方式因为退出而导致 整个容器退出。 这种方式可以替代
ssh
或者nsenter方式,在容器内进行操作。
[root@localhost ~]
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2faf24118766 192.168.1.23:5000
/tomcat7
"/bin/bash"
4 days ago Up About a minute 0.0.0.0:8888->8080
/tcp
tomcat
[root@localhost ~]
# docker exec -t tomcat /bin/bash
[root@2faf24118766 /]
# exit //按住ctrl+d退出当前窗口
[root@localhost ~]
# docker ps //发现容器还在,并没有因为上面的窗口退出而停止容器!
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2faf24118766 192.168.1.23:5000
/tomcat7
"/bin/bash"
4 days ago Up About a minute 0.0.0.0:8888->8080
/tcp
tomcat
在使用docker
exec
登陆容器或执行容器中的命令时,最好都带上-t和-i参数
[root@localhost ~]
# docker exec -ti tomcat yum install -y net-tools
[root@localhost ~]
# docker exec -t -i tomcat ifconfig
----------------------------------------------
除此之外,docker
exec
还可以使用-d参数,表示在后台执行一个进程。如果一个命令需要长时间进程,使用-d参数会很快返回,程序在后台运行。
这一般用于容器中的命令长时间执行的情况下。
[root@localhost ~]
# docker exec -d tomcat yum install -y mysql
|
4)对于一个已关闭的容器的登陆,可以使用"docker start -ai container"登陆。这种其实就是先启动容器,然后再进入容器内。
1
2
3
4
5
6
7
8
9
10
|
[root@localhost ~]
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2faf24118766 192.168.1.23:5000
/tomcat7
"/bin/bash"
4 days ago Up 9 minutes 0.0.0.0:8888->8080
/tcp
tomcat
[root@localhost ~]
# docker stop tomcat
tomcat
[root@localhost ~]
# docker start -i tomcat //参数用-i或-a -i两个参数都可以
[root@2faf24118766 /]
# exit //不过这种方式,在退出当前窗口后,也会导致容器停止!
[root@localhost ~]
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
5)使用外部工具nsenter登陆容器,该工具和docker exec命令的效果差不多。使用nsenter或docker exec,都可以在容器的上下文(严格地说,是命名空间)中运行任意命令!
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
1.安装nsenter
nsenter 工具在util-linux包2.23版本后包含。如果系统中 util-linux 包没有该命令,可以按照下面的方法从源码安装。
[root@localhost ~]
# cd /usr/local/src/
[root@localhost src]
# curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-; cd util-linux-2.24;
[root@localhost util-linux-2.24]
# ./configure --without-ncurses
[root@localhost util-linux-2.24]
# make nsenter && cp nsenter /usr/local/bin
2.nsenter使用
在使用nsenter命令之前需要获取到docker容器的进程,然后再使用nsenter工具进去到docker容器中,具体的使用方法如下:
# docker inspect -f {{.State.Pid}} 容器名或者容器id //每一个容器都有.State.Pid,所以这个命令除了容器的id需要我们根据docker ps -a去查找,其他的全部为固定的格式
# nsenter --target 上面查到的进程id --mount --uts --ipc --net --pid // 输入该命令便进入到容器中
解释nsenter指令中进程
id
之后的参数的含义:
--
mount
参数是进去到
mount
namespace中
--uts参数是进入到uts namespace中
--ipc参数是进入到System V IPC namaspace中
--net参数是进入到network namespace中
--pid参数是进入到pid namespace中
--user参数是进入到user namespace中
在Linux中,最爱简单的查看指定命令参数含义的办法是在终端中输入:
# nsenter --help #会回显所有与该命令有关的参数
# man nsenter #能查到更加详细的使用示例和参数说明
[root@localhost ~]
# nsenter --help
Usage:
nsenter [options] <program> [args...]
Options:
-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
-U, --user [=<
file
>] enter user namespace
-S, --setuid <uid>
set
uid
in
user namespace
-G, --setgid <gid>
set
gid
in
user namespace
-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 and
exit
-V, --version output version information and
exit
实例如下:
[root@localhost ~]
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2faf24118766 192.168.1.23:5000
/tomcat7
"/bin/bash"
4 days ago Up 23 minutes 0.0.0.0:8888->8080
/tcp
tomcat
[root@localhost ~]
# docker inspect -f {{.State.Pid}} tomcat
31356
[root@localhost ~]
# nsenter --target 31356 --mount --uts --ipc --net --pid
[root@2faf24118766 /]
# exit //退出当前窗口,容器不会停止。
logout
[root@localhost ~]
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2faf24118766 192.168.1.23:5000
/tomcat7
"/bin/bash"
4 days ago Up 27 minutes 0.0.0.0:8888->8080
/tcp
tomcat
或者:
[root@localhost ~]
# nsenter -m -u -n -i -p -t 31356 bash
[root@2faf24118766 /]
#
[root@localhost ~]
# nsenter -m -u -n -i -p -t 31356 uptime
10:17:08 up 164 days, 2:50, 0
users
, load average: 0.00, 0.01, 0.05
[root@localhost ~]
# nsenter -m -u -n -i -p -t 31356 free -m
total used
free
shared buff
/cache
available
Mem: 65759080 591904 58142584 419724 7024592 64301784
Swap: 2097148 0 2097148
|
6)更简单的是,强烈推荐下载.bashrc_docker,并将内容放到.bashrc中。这个文件中定义了很多方便使用Docker的命令,比如docker-pid可以获取某个容器的 PID;而 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
33
34
35
36
37
38
39
40
41
42
|
[root@localhost ~]
# wget -P ~ https://github.com/yeasy/docker_practice/raw/master/_local/.bashrc_docker
[root@localhost ~]
# echo "[ -f ~/.bashrc_docker ] && . ~/.bashrc_docker" >> ~/.bashrc; source ~/.bashrc
举例:
[root@localhost ~]
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2faf24118766 192.168.1.23:5000
/tomcat7
"/bin/bash"
4 days ago Up 37 minutes 0.0.0.0:8888->8080
/tcp
tomcat
1)直接使用docker-enter命令进入容器,非常方便!
[root@localhost ~]
# docker-enter tomcat
Last login: Sat Apr 1 10:07:21 UTC 2017
[root@2faf24118766 ~]
# exit
logout
[root@localhost ~]
# docker ps //退出登陆窗口后,容器还在!
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2faf24118766 192.168.1.23:5000
/tomcat7
"/bin/bash"
4 days ago Up 39 minutes 0.0.0.0:8888->8080
/tcp
tomcat
以在容器的上下文中运行任意命令!即在宿主机上执行容器里的命令
[root@localhost ~]
# docker-enter tomcat uptime
10:11:05 up 164 days, 2:44, 0
users
, load average: 0.05, 0.03, 0.05
-----------------
注意:在宿主机上使用docker-enter命令执行容器中的命令时,最好后面加上--符号,这样容器里的所有存在的命令都可以正常执行。
[root@localhost ~]
# docker-enter tomcat -- uptime
10:49:08 up 164 days, 3:22, 0
users
, load average: 0.02, 0.02, 0.05
[root@localhost ~]
# docker-enter tomcat -- df -h //这条命令如果去掉--符号,就不会顺利执行容器中的df -h命令了
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/docker-253
:0-268868570-9ae66abb2dc10d8d1c4327a41bab376c3684f1c49af91cf6ca2b3a3d58a1d07f 10G 584M 9.5G 6% /
tmpfs 32G 0 32G 0%
/dev
tmpfs 32G 0 32G 0%
/sys/fs/cgroup
/dev/mapper/centos-root
150G 6.4G 144G 5%
/etc/hosts
shm
[root@localhost ~]
# docker-enter tomcat -- cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
2)使用docker-pid获取容器PID
[root@localhost ~]
# echo $(docker-pid tomcat)
31356
[root@localhost ~]
# nsenter --target 31356 --mount --uts --ipc --net --pid
[root@2faf24118766 /]
#
|