当容器退出时,我丢失了数据

ima*_*man 364 docker

尽管Docker的交互式教程常见问题我在容器退出时丢失了数据.

我安装了Docker,如下所述:http://docs.docker.io/en/latest/installation/ubuntulinux 在ubuntu 13.04上没有任何问题.

但它在退出时会丢失所有数据.

iman@test:~$ sudo docker version
Client version: 0.6.4 
Go version (client): go1.1.2 
Git commit (client): 2f74b1c 
Server version: 0.6.4 
Git commit (server): 2f74b1c 
Go version (server): go1.1.2 
Last stable version: 0.6.4 


iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:05:47 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu apt-get install ping
Reading package lists... 
Building dependency tree... 
The following NEW packages will be installed: 
  iputils-ping 
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. 
Need to get 56.1 kB of archives. 
After this operation, 143 kB of additional disk space will be used. 
Get:1 http://archive.ubuntu.com/ubuntu/ precise/main iputils-ping amd64 3:20101006-1ubuntu1 [56.1 kB] 
debconf: delaying package configuration, since apt-utils is not installed 
Fetched 56.1 kB in 0s (195 kB/s) 
Selecting previously unselected package iputils-ping. 
(Reading database ... 7545 files and directories currently installed.) 
Unpacking iputils-ping (from .../iputils-ping_3%3a20101006-1ubuntu1_amd64.deb) ... 
Setting up iputils-ping (3:20101006-1ubuntu1) ... 
iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:06:11 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu touch /home/test
iman@test:~$ sudo docker run ubuntu ls /home/test
ls: cannot access /home/test: No such file or directory 
Run Code Online (Sandbox Code Playgroud)

我还使用相同结果的交互式会话对其进行了测试.我忘记了什么吗?

编辑:新的DOCKER用户的重要性

正如@ mohammed-noureldin和其他人所说,实际上这不是一个容器退出.每次它只是创建一个新容器.

Unf*_*rth 382

您需要提交对容器所做的更改,然后运行它.试试这个:

sudo docker pull ubuntu

sudo docker run ubuntu apt-get install -y ping
Run Code Online (Sandbox Code Playgroud)

然后使用以下命令获取容器ID:

sudo docker ps -l
Run Code Online (Sandbox Code Playgroud)

提交对容器的更改:

sudo docker commit <container_id> iman/ping 
Run Code Online (Sandbox Code Playgroud)

然后运行容器:

sudo docker run iman/ping ping www.google.com
Run Code Online (Sandbox Code Playgroud)

这应该工作.

  • 递增提交不是"码头工作方式".使用DOCKERFILE. (60认同)
  • 你会如何从容器中承诺?考虑以下场景:1)我正在运行这样的容器:docker run -i -t myimage/bin/bash 2)我做了一些更改3)我无法从容器中提交,所以当我退出容器时,我将丢失我的所有数据,而没有机会提交我以前的更改 (21认同)
  • 所以我应该在每次*run*之后使用*commit*来保存数据. (9认同)
  • @Unferth如果我想继续改变怎么办?到目前为止,它使用`<none>`创建了更多图像.如何在现有图像的基础上继续附加提交? (7认同)
  • 只有在容器中进行CHANGES(如安装新工具或数据)时才应使用Commit,以便保存这些更改,并且下次从该Image运行新容器时,它将从上次保存时开始或提交,保留您的数据. (5认同)
  • 这是否意味着,每当你在守护进程中测试一些代码并希望在完成后查看输出.你必须提交并且`docker run -t -i <newimage>/bin/bash`?登录回容器查看输出? (2认同)
  • @qgicup我相信Ctrl + p,Ctrl + q会在保持当前容器运行的情况下退出当前容器。 (2认同)
  • @javadba编号。AFAIK,Ctrl + p,Ctrl + q会在不退出外壳的情况下分离tty。因此,容器内的进程继续运行。我提到它是为了响应qgicup在他的评论中提出的场景,该场景是一种与容器的tty分离并有机会提交或执行任何其他必要命令的方式。 (2认同)

Zei*_*ssS 348

当您docker run用来启动容器时,它实际上根据您指定的图像创建一个新容器.

除了其他有用的答案,请注意您可以在退出后重新启动现有容器,并且您的更改仍然存在.

docker start f357e2faab77 # restart it in the background
docker attach f357e2faab77 # reattach the terminal & stdin
Run Code Online (Sandbox Code Playgroud)

  • `docker ps`显示你只运行docker容器.`docker ps -a`还会显示已经退出的那些 - 并且您可以继续运行.如果您想在将来制作快照以供将来使用,则每次运行后都需要提交,否则容器本身将一直存在以供您继续使用. (85认同)
  • 退出后,这是将文件从容器中复制出来的一种方便方法:`docker cp $(docker ps -alq):/ path/to/file .` (6认同)
  • 你也可以用它的名字开始和附加一个容器.(例如`docker run -it --name my_debian debian`和`docker start my_debian && docker attach my_debian`) (3认同)
  • 请问,所以,如果我下载一个`jenkins`服务器docker,我在我的ci主机上运行它,它运行我有一些工作,因此jenkins服务器写入磁盘一些日志.现在,如果我的服务器(托管我的docker)重新启动,我再次启动我的jenkins docker会不会意味着我丢失了所有日志文件?如果是这样的话我怎么可能使用`jenkins` docker来缓解我在CI上的jenkins安装呢? (2认同)
  • @Jas如果你坚持使用同一个容器而不是创建新容器,那就没有问题.Docker现在有重启策略,因此您可以将其配置为在机器重启时重新启动相同的容器.我还建议你将你的jenkins放入一个卷中,以便能够从外部访问它(备份等). (2认同)

kal*_*ari 114

有以下方法可以持久保存容器数据:

  1. Docker卷

  2. Docker提交

    a)从ubuntu映像创建容器并运行bash终端.

       $ docker run -i -t ubuntu:14.04 /bin/bash
    
    Run Code Online (Sandbox Code Playgroud)

    b)在终端内安装卷曲

       # apt-get update
       # apt-get install curl
    
    Run Code Online (Sandbox Code Playgroud)

    c)退出集装箱码头

       # exit
    
    Run Code Online (Sandbox Code Playgroud)

    d)通过执行以下命令记下您的容器ID:

       $ docker ps -a
    
    Run Code Online (Sandbox Code Playgroud)

    e)将容器保存为新图像

       $ docker commit <container_id> new_image_name:tag_name(optional)
    
    Run Code Online (Sandbox Code Playgroud)

    f)确认您可以在安装了curl的情况下看到新图像.

       $ docker images           
    
       $ docker run -it new_image_name:tag_name bash
          # which curl
            /usr/bin/curl
    
    Run Code Online (Sandbox Code Playgroud)

  • @AbhishekAnand是的,因为使用docker run命令,您在容器中运行bash,并且由于使用-i和-t选项(与TTY交互)而停留在该容器中。但是,Docker在容器外部的机器上运行,因此从内部对容器进行必要的更改后,要返回到系统的外壳,您必须“退出”(或Ctrl + D)容器的外壳。还要注意答案中的`#`和`$`,它们表示命令被写入的不同shell。 (2认同)

sal*_*the 59

除了Unferth的答案,建议创建一个Dockerfile.

在空目录中,使用以下内容创建名为"Dockerfile"的文件.

FROM ubuntu
RUN apt-get install ping
ENTRYPOINT ["ping"]
Run Code Online (Sandbox Code Playgroud)

使用Dockerfile创建映像.让我们使用标签,这样我们就不需要记住十六进制图像编号了.

$ docker build -t iman/ping .
Run Code Online (Sandbox Code Playgroud)

然后在容器中运行映像.

$ docker run iman/ping stackoverflow.com
Run Code Online (Sandbox Code Playgroud)


Mag*_*win 11

我对您的问题有一个简单得多的答案,请运行以下两个命令

sudo docker run -t -d ubuntu --name mycontainername /bin/bash
sudo docker ps -a
Run Code Online (Sandbox Code Playgroud)

上面的ps -a命令返回所有容器的列表。引用引用图像名称的容器名称-'ubuntu'。docker auto会为容器生成名称,例如- 'lightlyxuyzx',也就是说,如果您不使用--name选项。

-t和-d选项很重要,已创建的容器已分离,可以使用-t选项重新附加,如下所示。

使用--name选项,可以在我的情况下将容器命名为“ mycontainername”。

sudo docker exec -ti mycontainername bash
Run Code Online (Sandbox Code Playgroud)

以上命令可以帮助您使用bash shell登录到容器。从这一点开始,您在容器中所做的任何更改都会被docker自动保存。例如- apt-get install curl在容器内部您可以退出容器而没有任何问题,docker auto会保存更改。

在下一个用法中,您要做的就是,每次要使用此容器时都运行这两个命令。

以下命令将启动已停止的容器:

sudo docker start mycontainername

sudo docker exec -ti mycontainername bash
Run Code Online (Sandbox Code Playgroud)

另一个具有端口和共享空间的示例如下:

docker run -t -d --name mycontainername -p 5000:5000 -v ~/PROJECTS/SPACE:/PROJECTSPACE 7efe2989e877 /bin/bash
Run Code Online (Sandbox Code Playgroud)

在我的情况下:7efe2989e877-是我使用之前运行的容器的imageid

泊坞窗ps -a

  • 在Ubuntu 18.04上使用Docker 18.09.2时,它无法按原样工作。如果我在映像名称之前放置`--name`和option,则可以正常工作,如下所示:`docker run --name mycontainername -t -d ubuntu / bin / bash` (4认同)
  • 我不知道为什么这个答案没有更多的支持。 (2认同)

小智 9

如果要将数据保留在容器中,可能需要查看docker卷.访问https://docs.docker.com/engine/tutorials/dockervolumes/.docker文档是一个非常好的起点


blu*_*hts 8

上面对提出的问题有很好的答案。可能不需要另一个答案,但我仍然想用最简单的词就这个话题发表我的个人意见。

以下是有关容器和图像的一些要点,可以帮助我们得出结论:

  • 泊坞窗图像可以是
    1. 从一个给定的容器创建
    2. 已删除
    3. 用于创建任意数量的容器
  • 一个 docker 容器可以是
    1. 从图像创建
    2. 开始
    3. 停止
    4. 重新启动
    5. 已删除
    6. 用于创建任意数量的图像
  • docker run 命令执行以下操作
    1. 下载图像或使用缓存的图像
    2. 从中创建一个新容器
    3. 启动容器
  • 当使用 Dockerfile 创建镜像时
    1. 众所周知,该映像最终将用于运行 docker 容器。
    2. 发出 docker build 命令后,docker 在幕后创建一个带有基本文件系统的正在运行的容器,并按照 Dockerfile 中的步骤根据开发人员的需要配置该容器。
    3. 使用 Dockerfile 的规范配置容器后,它将作为映像提交。
    4. 图像已准备好摇滚!

结论

正如我们所见,docker 容器独立于 docker 镜像。

如果容器的唯一 ID [用于docker ps --all获取 ID],则可以重新启动容器。

创建新目录、创建文件、安装工具等任何操作都可以在容器运行时在容器内完成。一旦容器停止,它会保留所有更改。容器停止和重新启动就像重新启动计算机系统。

一个已经创建的容器总是可以重新启动,但是当我们发出docker run命令时,一个新的容器会从一个镜像中创建出来,因此它就像一个新的计算机系统。在旧容器中所做的更改 - 正如我们现在可以理解的 - 在这个新容器中不可用。

最后一点

我想现在很明显为什么数据似乎丢失了但它总是在那里......但在不同的[旧]容器中。因此,请注意docker start&docker run命令中的区别,永远不要混淆它们。