Docker 容器操作退出后进入解决办法

在我们对Docker容器操作的时候,有时候会误操作或者其他的原因无意间退出了正在操作的容器,也许你会担忧你在其中的一些操作未保存下来,无须担忧,本文中将会提供各种方法供你参考(我的建议使用最后一种)。在本文,我们将讨论五种(4+1)连接Docker容器并与其进行交互的方法。例子中所有的代码都可以在GitHub中找到,你可以亲自对它们进行测试。

1.nsenter

安装

nsenter 工具在 util-Linux 包2.23版本后包含。 如果系统中 util-linux 包没有该命令,可以按照下面的方法从源码安装。

你也可以点击此链接进行下载  http://pan.baidu.com/s/1FEt8y

$ cd /tmp; 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;

$ ./configure --without-ncurses 
$ make nsenter && sudo cp nsenter /usr/local/bin

使用

nsenter 可以访问另一个进程的名字空间。nsenter 要正常工作需要有 root 权限。 很不幸,Ubuntu 14.4 仍然使用的是 util-linux 2.20。安装最新版本的 util-linux(2.24)版,请按照以下步骤:

$ wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz; tar xzvf util-linux-2.24.tar.gz
$ cd util-linux-2.24
$ ./configure --without-ncurses && make nsenter
$ sudo cp nsenter /usr/local/bin

从util-linux版本2.23开始,nsenter工具就包含在其中。它用来访问另一个进程的名字空间。nsenter要正常工作需要有root权限。很不幸,Ubuntu 14.4仍然使用的是util-linux版本2.20。安装最新版本的util-linux(2.24)版,请按照以下步骤:

cd /tmp

为了连接到容器,你还需要找到容器的第一个进程的PID,通过这个PID,你就可以连接到这个容器:

$ docker inspect --format "{{ .State.Pid }}" <container-id>
//or run 'docker inspect -f "{{ .State.Pid }}" <container-id>'
$ nsenter --target $PID --mount --uts --ipc --net --pid 

2.nsinit

从0.9版本开始,Docker自身就具有一个管理容器的库,名字为 libcontainer。libcontainer中的nsinit工具允许用户直接访问linux名字空间和cgroup内核。在安装nsinit之前,你首先需要安装Go运行时环境:

$ apt-get installgit golang-go  

$ mkdir-p $HOME/go-dev/binmkdir-p $HOME/go-dev/src 

$ echo"export GOPATH=\$HOME/go-dev" >> ~/.profileecho "PATH=\$PATH:\$GOPATH/bin">> ~/.profile  

$ source~/.profile

接下来才安装nsinit:

$ apt-get installgit golang-go  

$ mkdir-p $HOME/go-dev/binmkdir-p $HOME/go-dev/src 

$ echo"export GOPATH=\$HOME/go-dev" >> ~/.profileecho "PATH=\$PATH:\$GOPATH/bin">> ~/.profile  

$ source~/.profile

nsinit读取的是位于/var/lib/docer/execdriver/native/<Container-id>容器目录下的配置数据。要运行nsinit,你需要切换到容器目录下。由于/var/lib/docker目录对于root用户是只读权限,因此你还需要root权限。通过docker的ps命令,你可以确定容器ID。一旦你进入/var/lib/docker目录,你就可以连接容器了:

nsinit exec /bin/bash

3.lxc(-attach)

直到Docker 0.8.1版本为止,LXC一直是管理容器的基本工具,Docker一直支持这个工具。但是从0.9.0版本开始,Docker默认使用libcontainer管理容器,不再依赖LXC了。因此默认情况下,你不能使用lxc-attach了。

如果你仍然希望使用lxc-attach,那么你需要使用-e lxc选项来重新启动Docker服务进程。使用这个选项,Docker的内部将再次使用LXC管理容器了。完成这个任务最简单的做法就是创建/etc/default/docker文件(如果这个文件仍然不存在),并添加以下内容:

DOCKER_OPTS=" -e lxc"

现在你可以重新启动Docker服务了。要连接容器,你需要知道完整的容器ID:

docker ps --no-trunc

接下来,你就可以连接这个容器了。要完成下面工作,你还需要root权限:

lxc-attach -n <container-id> -- /bin/bash

 4.sshd

上面所有三种方法都要求具有主机系统的root权限。为了不采用root权限,通过ssh访问容器将是一个很好的选择。

要做到这一点,你需要构建一个支持SSH服务的基础映像。此时,我们可能遇到这样的问题:我们是不是用Docker CMD或者ENTRYPOINT运行一条命令就可以了?如果此时有sshd进程运行,那么我们就不要再运行其他进程了。接下来的工作是创建一个脚本或者使用像supervisord这样的进程管理工具来启动其它所有需要启动的进程。有关如何使用supervisord的优秀的文档可以在Docker的web站点上找到。一旦你启动了具有sshd进程的容器,你就可以像以往一样通过ssh客户端了连接这个容器了。

结论

sshd方法可能是最简单的连接容器的方法,而且大多数用户习惯通过ssh连接虚拟机。另外,连接容器时你也不需要一定使用root权限。不过,对于是否一个容器是否应当管理不止一个进程仍然存在许多争议。这种方法最终使得每个容器了多了一个sshd进程,这从根本上来说不是进程虚拟化的所提倡的。

另外三种方法都需要root权限。到0.8.1版本为止,Docker都是使用LXC来管理容器的。正是由于这个原因,使用lxc-attach连接容器就非常容易。不过从版本0.9.0开始Docker服务就必须使用 -e lxc选项启动才能在内部支持LXC管理容器。不过,由于设置了这个选项,Docker将再次依赖LXC,而LXC可能随着发布或者安装的不同可能被剔除。

nsenter和nsinit总的来说是相同的。这两个工具的主要区别是nsinit在本身的容器了建立了一个新的进程,而nsenter只是访问了名字空间。Jerome Petazzoni在Docker博客文章里对这一点说的很透彻。

上面的几种方法我也曾试过,他们基本上都是进入正在运行中的容器,nsenter还可实现多终端对一个容器的操作。如果进入已经终止的容器,第一次安装执行的时候是可以的,可以得到PID的值,不过之后再执行的时候发现PID的值为0,如果你接着执行

<del>nsenter --target $PID --mount --uts --ipc --net --pid</del>

你会发现 切换到了宿主机的超级管理员权限。

正确的方法会在下面介绍,首先先补充一下一些命令的参数的含义:

 查看镜像

docker images: 列出images

docker images -a :列出所有的images(包含历史)

docker images --tree :显示镜像的所有层(layer)

docker rmi  <image ID>: 删除一个或多个image

查看容器

docker ps :列出当前所有正在运行的container
    docker ps -l :列出最近一次启动的container
    docker ps -a :列出所有的container(包含历史,即运行过的container)
    docker ps -q :列出最近一次运行的container ID

 5.重点来了:

$ docker ps -a
CONTAINER ID    IMAGE        COMMAND       CREATED       STATUS      PORTS    NAMES
9cff554fb6d7    ubuntuold:14.04   /bin/bash      About an hour ago  Up About an hour    condescending_blackwell
e5c5498881ed    ubuntuold:14.04   /bin/bash      About an hour ago  Exited (0) 55 minutes ago backstabbing_bardeen

通过以上的信息可以看出两者之间的差别:前者是正在运行的容器;而后者是已经终止的容器(Exited(0))。

docker start/stop/restart<container> :开启/停止/重启container
    docker start [container_id] :再次运行某个container(包括历史container)
    docker attach [container_id]:连接一个正在运行的container实例(即实例必须为start状态,可以多个窗口同时attach一个container实例)
    docker start -i <container>:启动一个container并进入交互模式(相当于先start,在attach)

就以后者e5c5498881ed为例:首先执行

$ docker start e5c5498881ed 

//之后再一次查看的时候Exited(0)已经没有了,也就是说明该容器已经从终止的状态变为了正在运行的状态
 $docker attach e5c5498881ed 

//你会的发现已经进入该容器了,而且之前的操作的文件依然存在
//如果没有反应的话,再一次点击回车即可

docker run -i -t <image> /bin/bash:使用image创建container并进入交互模式, login shell是/bin/bash

docker run -i -t -p <host_port:contain_port>:映射 HOST 端口到容器,方便外部访问容器内服务,host_port 可以省略,省略表示把 container_port映射到一个动态端口。

注:使用start是启动已经创建过得container,使用run则通过image开启一个新的container。

 附加:

查看root密码

docker容器启动时的root用户的密码是随机分配的。所以,通过这种方式就可以得到容器的root用户的密码了。

docker logs 5817938c3f6e 2>&1 | grep 'User: ' | tail -n1

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • 关于docker容器优雅退出的问题详解

    前言 最近因为工作的原因,谈到了关于如何正确的退出运行中的docker容器,这是一个非常值得讨论的话题了.本文将给出详细的介绍,下面来一起看看吧. 容器信号使用 我们跑在容器中的程序通常想在容器退出之前做一些清理操作,比较常用的方式是监听一个信号,延迟关闭容器. docker提供了这样的功能: ╰─➤ docker stop --help Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...] Stop one or more running

  • Docker 容器操作退出后进入解决办法

    在我们对Docker容器操作的时候,有时候会误操作或者其他的原因无意间退出了正在操作的容器,也许你会担忧你在其中的一些操作未保存下来,无须担忧,本文中将会提供各种方法供你参考(我的建议使用最后一种).在本文,我们将讨论五种(4+1)连接Docker容器并与其进行交互的方法.例子中所有的代码都可以在GitHub中找到,你可以亲自对它们进行测试. 1.nsenter 安装 nsenter 工具在 util-Linux 包2.23版本后包含. 如果系统中 util-linux 包没有该命令,可以按照下

  • 一条命令重启所有已停止的docker容器操作

    一条命令重启所有已停止的docker容器 docker ps -a | grep Exited 查看所有已停止的容器 docker ps -a | grep Exited | awk '{print $1}' 获取已停止容器的ID docker ps -a | grep Exited | awk '{print $1}' |xargs docker start 把获取到的已停止容器的ID传送给容器启动命令 一条命令停止所有运行中的docker容器 docker ps -a | grep Up |

  • docker image删不掉的解决办法

    在使用Docker的时候遇到删不掉image的情况,如下: root@ubuntu:/opt/docker# docker images REPOSITORY TAG IMAGE ID CREATED SIZE door/ubuntu-nginx v2 5e4f2da203e2 5 minutes ago 283.3 MB <none> <none> 46987ed2da40 33 minutes ago 129 MB <none> <none> 20248

  • 关于CentOs系统自带python和yum卸载后的解决办法

    事故背景:前几天因项目需要,在服务器上搭建python-mysql模块,结果没安装好,于是乎想卸载重装,遂在网上查询卸载python的方法,结果一不小心直接把系统的python删了个干净.......... 现在只能含泪修复,博主在网上搜了一圈办法,基本上都不是那么的详细,现在记下这一方法,希望能帮到与我情况相同的朋友~ 1:卸载python(以免有些同学没有卸载干净) 2.卸载yum 3.验证是否删除干净 4.安装python和yum 在以下链接的镜像站中找到你系统对应版本的python rp

  • Docker运行Nacos容器自动退出问题的解决方法

    Dokcer运行Nacos容器自动退出问题 参考博文 学生党,租的云服务器,2核2G.使用Docker运行Nacos容器的时候发现总是自动退出.Nacos日志里面没有明显的报错信息.查了一下是内存溢出错误,指令如下 journalctl -k | grep -i -e memory -e oom 发生了OOM错误,自动杀死了相关进程 又重新看了下Nacos日志,如下图所示,发现堆内存设置的太大了,初始堆内存Xms设置的1G,最大堆内存Xmx设置的1G,年轻代Xmn设置的512M. 问题找到了,将

  • Docker 容器操作指令汇总详解

    1. 创建并运行 一个容器 docker run -it --rm centos:latest bash run 运行容器 -it 以交互方式运行容器 --rm 退出容器后删除容器 centos:latest 基于 镜像启动容器 bash 命令 交互式shell 2. 退出容器 exit 3. 查看容器 docker ps 查看正在运行的容器 docker ps -a 查看所有容器 4.删除容器 docker rm [容器id ] 5 . 查看 镜像 容器 数据卷 占用空间 docker sys

  • Docker容器端口映射后突然无法连接的排查过程

    一.背景 一般需要对外提供服务的Docker容器,我们在启动时后使用-p命令将对外访问端口暴露给外部,例如启动Docker Registry,我们将5000端口映射出来供外部访问: docker run -d -p 5000:5000 registry 但最近碰到一个非常奇怪的情况:研发组里一个CentOS 7测试环境里部署有Docker Registry,并对外暴露了端口.启动容器后一段时间内都是可以正常工作的,但在不定时间间隔后,外部主机就会出现无法从仓库中拉取镜像的情况,提示TimeOut

  • Asp.net Core 1.1 升级后操作mysql出错的解决办法

    遇到问题 core的版本从1.0升级到1.1,操作mysql数据库,查询数据时遇到MissingMethodException问题,更新.插入操作没有问题. 如果你也遇到这个问题,请参照以下步骤进行升级操作. 操作步骤及内容 如果你的项目已经引用过以下几部分内容,请依次升级内容: PM> Update-Package Microsoft.EntityFrameworkCore PM> Update-Package Microsoft.EntityFrameworkCore.SqlServer

  • Android中使用pull解析器操作xml文件的解决办法

    一.使用Pull解析器读取XML文件 除了可以使用SAX或DOM解析XML文件之外,大家也可以使用Android内置的Pull解析器解析XML文件. Pull解析器是一个开源的java项目,既可以用于android,也可以用于JavaEE.如果用在javaEE需要把其jar文件放入类路径中,因为Android已经集成进了Pull解析器,所以无需添加任何jar文件.android系统本身使用到的各种xml文件,其内部也是采用Pull解析器进行解析的. Pull解析器的运行方式与SAX 解析器相似.

随机推荐