ma6174 / blog

博客
https://ma6174.github.io/blog/
138 stars 18 forks source link

如何进入正在执行的 docker container #8

Open ma6174 opened 10 years ago

ma6174 commented 10 years ago

当一个container起来之后,我们有时候希望能进入container内部去看看,比如查查日志,执行些操作等。目前有几种方式可以实现:

1. docker attach

这个是官方提供的一种方法。

测试,首先启动一个container:

$ docker run -i -t ubuntu bash
root@4556f5ad6067:/#

不要退出,打开另一个终端:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
4556f5ad6067        ubuntu:14.04        "bash"              45 seconds ago      Up 43 seconds                           jolly_ardinghelli

$ docker attach 4556f5ad6067
root@4556f5ad6067:/#

这样就连接进去了。这时候如果我们输入一些命令,就能看到在两个终端都有显示和输出。这种方式有比较大的局限性,如果知道了entrypoint或者有程序正在执行,通过docker attach进入之后是不能执行操作的,一个终端退出之后整个container就终止了。不推荐使用这种方式。

2. lxc-attach

如果使用这种方式,首先要保证docker是以lxc方式启动的,具体可以这样做:

  1. 修改/etc/default/docker增加DOCKER_OPTS="-e lxc"
  2. 重启docker服务sudo service docker restart

启动container的方式和之前一样:

$ docker run -i -t ubuntu bash
root@e7f01f0ff598:/#

进入container可以这样:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
e7f01f0ff598        ubuntu:14.04        "bash"              17 seconds ago      Up 15 seconds                           grave_jones

$ ps aux | grep e7f01f0ff598
root     23691  0.0  0.0  43140  1876 pts/9    Ss   21:47   0:00 lxc-start -n e7f01f0ff598c80d70a996135c98fbaeddc6daa61436bbbfa735233e8b6f8ebe -f /var/lib/docker/containers/e7f01f0ff598c80d70a996135c98fbaeddc6daa61436bbbfa735233e8b6f8ebe/config.lxc -- /.dockerinit -g 172.17.42.1 -i 172.17.0.3/16 -mtu 1500 -- bash
ma6174   23756  0.0  0.0  13428   928 pts/12   S+   21:47   0:00 grep --color=auto e7f01f0ff598

$ sudo lxc-attach -n e7f01f0ff598c80d70a996135c98fbaeddc6daa61436bbbfa735233e8b6f8ebe
root@e7f01f0ff598:/#

这种方式还是很方便的。前提是需要重启docker服务以lxc的方式执行,进入container之后会有一个终端可以执行命令,不影响正在执行的程序。

3. nsenter

如果docker不是以lxc方式启动的,这时候还想进入一个正在执行的container的话,可以考虑使用nsenter

这个程序的安装方式很独特,使用docker进行安装:

$ docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter

使用方法也很简单,首先你要进入的container的PID

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

然后就可以用这个命令进入container了:

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

为了使用方便可以写一个脚本自动完成:

$ cat /bin/docker_enter
#!/bin/bash
sudo nsenter --target `docker inspect --format {{.State.Pid}} $1` --mount --uts --ipc --net --pid bash

这样每次要进入某个container只需要执行docker_enter <container_name_or_ID>就可以了。

4. ssh

这个原理也很简单,在container里面启动ssh服务,然后通过ssh的方式去登陆到container里面,不推荐这种方式,主要是配置ssh登陆比较繁琐,开启ssh服务也会耗费资源,完全没有必要。

~~~~~~~~~~~~~~~华丽的分割线~~~~~~~~~~~~~~~

docker 1.2.0发布,带来一个比较实用的特性的是支持restart参数,可以在docker run的时候指定:

  --restart=""               Restart policy to apply when a container exits (no, on-failure, always)

有这个参数就比较方便了,比如container里面的服务因为某些原因退出了,之前只能通过外部程序去重新启动container,有了这参数之后可以放container自动重启,当然也可以设置失败重试次数,通过on-failure:5这种方式来指定失败后最多尝试重启5次。

官方的两个例子:

docker run --restart=always redis

docker run --restart=on-failure:5 redis

其他新特性参考:https://blog.docker.com/2014/08/announcing-docker-1-2-0/

ma6174 commented 10 years ago

docker1.3增加新的exec命令行工具,进入container更加方便,简单说命令是:“docker exec -i -t bash”

$ docker version
Client version: 1.3.0
Client API version: 1.15
Go version (client): go1.3.3
Git commit (client): c78088f
OS/Arch (client): linux/amd64
Server version: 1.3.0
Server API version: 1.15
Go version (server): go1.3.3
Git commit (server): c78088f
$ ps aux | grep docker
root      2940  0.0  0.1 396092  8640 ?        Ssl  10:40   0:00 /usr/bin/docker -d --dns 8.8.8.8 --dns 8.8.4.4
ma6174    5971  0.0  0.0  13432   940 pts/0    R+   15:15   0:00 grep --color=auto -i docker
$ docker run -i -t -d ubuntu bash
740e78a3406f72db08973c2db6c2e60286504135d48ab5d431b706a342b051bd
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
740e78a3406f        ubuntu:14.04        "bash"              4 seconds ago       Up 3 seconds                            cocky_pike
$ docker exec -i -t 740e78a3406f bash
root@740e78a3406f:$ ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@740e78a3406f:$ touch a
root@740e78a3406f:$ ls
a  bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@740e78a3406f:$ exit
exit
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
740e78a3406f        ubuntu:14.04        "bash"              46 seconds ago      Up 46 seconds                           cocky_pike
$ docker exec -i -t 740e78a3406f bash
root@740e78a3406f:$ ls
a  bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@740e78a3406f:$ exit
exit

这个不支持以lxc方式启动的container

$ ps aux | grep docker
root      6657  0.5  0.1 248500  8924 ?        Ssl  15:22   0:00 /usr/bin/docker -d --dns 8.8.8.8 --dns 8.8.4.4 -e lxc
ma6174    6746  0.0  0.0  13428   940 pts/0    R+   15:22   0:00 grep --color=auto -i docker
$ docker run -i -t -d ubuntu bash
c18652dcc369bf31b622c3e7fe38f5e16a9a3d3f3f40e97a81c962828c4ef9de
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c18652dcc369        ubuntu:14.04        "bash"              4 seconds ago       Up 3 seconds                            trusting_euclid
$ docker exec -i -t c18652dcc369 bash
2014/10/18 15:23:28 Error response from daemon: Unsupported: Exec is not supported by the lxc driver
VectorHo commented 8 years ago

goodgood

kevien commented 8 years ago

zan

yangqinjiang commented 8 years ago

我刚刚了解到这种docker exec -i -t bash

wustudent commented 6 years ago

赞一个!消除了我长久以来的困惑!

MwumLi commented 6 years ago

在运行状态的容器内部运行新进程, 退出不会关闭 container : docker exec -i -t container_name/container_id bash

chuansh commented 4 years ago

请教个问题,进入容器后显示的是:bash-4.2$,是怎么回事呢?

chuansh commented 4 years ago

接上一条,一共3个容器,不是进入所有容器都显示bash-4.2$,有的显示正常,从网上看很多说法,但都没解决

Ma233 commented 4 years ago

@chuansh 这个是对应的 shell 解释器,进入后默认的显示内容是由容器的镜像决定的

MwumLi commented 4 years ago

bash-4.2$ 是命令提示符, 提示你在此之后可以输入命令
而命令提示符展示成什么样是可以定制的,具体取决于容器内的 shell 解释器以及配置
所谓的 shell 解释器常见的就是 bash, sh, 还有大家比较喜欢用的 zsh

tmacychen commented 4 years ago

docker attach 后,可以通过 ctrl + p + ctrl +q 退出一个,而不是都退出:link