435

尽管有 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 

我还通过交互式会话对其进行了测试,结果相同。我是不是忘记了什么?

编辑:对新的 Docker 用户很重要

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

4

11 回答 11

436

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

sudo docker pull ubuntu

sudo docker run ubuntu apt-get install -y ping

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

sudo docker ps -l

提交对容器的更改:

sudo docker commit <container_id> iman/ping 

然后运行容器:

sudo docker run iman/ping ping www.google.com

这应该有效。

于 2013-10-25T09:42:08.543 回答
408

当你docker run用来启动一个容器时,它实际上是根据你指定的镜像创建一个新的容器。

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

docker start f357e2faab77 # restart it in the background
docker attach f357e2faab77 # reattach the terminal & stdin
于 2013-10-27T09:37:59.970 回答
143

持久化容器数据有以下几种方式:

  1. Docker 卷

  2. Docker 提交

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

       $ docker run -i -t ubuntu:14.04 /bin/bash
    

    b) 在终端内安装 curl

       # apt-get update
       # apt-get install curl
    

    c) 离开集装箱码头

       # exit
    

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

       $ docker ps -a
    

    e) 将容器保存为新图像

       $ docker commit <container_id> new_image_name:tag_name(optional)
    

    f) 验证您是否可以看到安装了 curl 的新图像。

       $ docker images           
    
       $ docker run -it new_image_name:tag_name bash
          # which curl
            /usr/bin/curl
    
于 2016-05-17T08:48:38.217 回答
62

除了Unferth 的 answer之外,建议创建一个Dockerfile

在一个空目录中,使用以下内容创建一个名为“Dockerfile”的文件。

FROM ubuntu
RUN apt-get install ping
ENTRYPOINT ["ping"]

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

$ docker build -t iman/ping .

然后在容器中运行图像。

$ docker run iman/ping stackoverflow.com
于 2013-10-25T09:55:14.130 回答
16

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

sudo docker run -t -d ubuntu --name mycontainername /bin/bash
sudo docker ps -a

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

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

使用 --name 选项,您可以将容器命名为“mycontainername”。

sudo docker exec -ti mycontainername bash

上面的命令可以帮助您使用 bash shell 登录到容器。从此时起,您在容器中所做的任何更改都会由 docker 自动保存。例如 -apt-get install curl在容器内您可以毫无问题地退出容器,docker auto 会保存更改。

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

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

sudo docker start mycontainername

sudo docker exec -ti mycontainername bash

下面给出了另一个带有端口和共享空间的示例:

docker run -t -d --name mycontainername -p 5000:5000 -v ~/PROJECTS/SPACE:/PROJECTSPACE 7efe2989e877 /bin/bash

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

码头工人ps -a

于 2018-10-04T07:02:10.870 回答
14

上面提出的问题确实有很好的答案。可能不需要另一个答案,但我仍然想用最简单的语言表达我对这个话题的个人看法。

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

  • 泊坞窗图像可以是
    1. 从给定容器创建
    2. 已删除
    3. used-to-create-any-number-of-containers
  • A docker container can be:
    1. created-from-an-image
    2. started
    3. stopped
    4. restarted
    5. deleted
    6. used-to-create-any-number-of-images
  • A docker run command does this:
    1. Downloads an image or uses a cached image
    2. Creates a new container out of it
    3. Starts the container
  • When a Dockerfile is used to create an image:
    1. It is already well known that the image will eventually be used to run a docker container.
    2. After issuing docker build command, docker behind-the-scenes creates a running container with a base-file-system and follows steps inside the Dockerfile to configure that container as per the developers need.
    3. After the container is configured with specs of the Dockerfile, it will be committed as an image.
    4. The image gets ready to rock & roll!

Conclusion:

As we can see, a docker container is independent of a docker image.

A container can be restarted provided the unique ID of that container [use docker ps --all to get the id].

Any operation like making a new directory, creating files, installing tools, etc. can be done inside the container when it is running. Once the container is stopped, it persists all the changes. Container stopping and restarting is like rebooting a computer system.

An already created container is always available for a restart but when we issue docker run command, a new container is created out of an image and hence it is like a new computer system. The changes made inside the old container - as we can understand now - are not available in this new container.

A final note:

I guess it's now obvious why the data seems to be lost yet it is always there.. but in a different [old] container. So, take a good note of the difference in docker start & docker run command & never get confused in them.

于 2019-11-15T11:19:21.850 回答
8

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

于 2015-10-20T14:58:57.880 回答
4

我的建议是使用 docker compose 来管理 docker。是一种为您的项目管理所有 docker 容器的简单方法,您可以映射版本并链接不同的容器以协同工作。

文档非常易于理解,比 docker 的文档更好。

Docker-撰写文档

最好的

于 2017-04-11T02:54:31.763 回答
1

类似的问题(单独使用 Dockerfile 无法解决)将我带到了这个页面。

阶段 0: 总而言之,希望 Dockerfile 可以修复它:直到 --dns 和 --dns-search 出现在 Dockerfile 支持中 - 没有办法将基于 Intranet 的资源集成到其中。

第 1 阶段: 使用 Dockerfile 构建映像后(顺便说一下,这是一个严重的故障 Dockerfile 必须在当前文件夹中),通过运行 docker run 脚本来部署基于 Intranet 的映像。例子: docker run -d \ --dns=${DNSLOCAL} \ --dns=${DNSGLOBAL} \ --dns-search=intranet \ -t pack/bsp \ --name packbsp-cont \ bash -c " \ wget -r --no-parent http://intranet/intranet-content.tar.gz \ tar -xvf intranet-content.tar.gz \ sudo -u ${USERNAME} bash --norc"

第 2 阶段:在守护进程模式下 应用 docker run 脚本,提供本地 dns 记录,以便能够下载和部署本地内容。

重要的一点:运行脚本应该/usr/bin/sudo -u ${USERNAME} bash --norc以保持容器运行的方式结束,即使在安装脚本完成后也是如此。

,对于完全自动化的问题,不可能在交互模式下运行容器,因为它将保留在内部命令提示符中,直到按下CTRL-p CTRL-q 。

,如果在安装脚本结束时不执行交互 bash,则容器将在脚本执行完成后立即终止,丢失所有安装结果。

阶段 3: 容器仍在后台运行,但尚不清楚容器是否已结束安装过程。使用以下块来确定执行过程是否完成: while ! docker container top ${CONTNAME} | grep "00[[:space:]]\{12\}bash \--norc" - do echo "." sleep 5 done 只有在完成安装后,脚本才会继续执行。这是调用的正确时机:commit,提供当前容器 id 以及目标映像名称(它可能与构建/运行过程中的相同,但附加了本地安装目的标签。示例:docker commit containerID pack/bsp:toolchained。请参阅此链接如何获得正确的容器ID

第 4 阶段:容器已使用本地安装进行更新,并已提交到新分配的映像(添加了目的标签的映像)。现在停止容器运行是安全的。例子:docker stop packbsp-cont

stage5:本地安装的容器需要运行的任何时候,使用之前保存的图像启动它。例子:docker run -d -t pack/bsp:toolchained

于 2017-11-03T09:20:23.720 回答
1

这里有一个绝妙的答案 How to continue a docker which is exited from user kgs

docker start $(docker ps -a -q --filter "status=exited")
(or in this case just docker start $(docker ps -ql) 'cos you don't want to start all of them)

docker exec -it <container-id> /bin/bash

第二条线至关重要。因此使用 exec 代替 run,而不是在图像上,而是在 containerid 上。您在容器启动后执行此操作。

于 2018-02-27T02:14:27.887 回答
0

没有一个答案解决了这种设计选择的要点。我认为 docker 以这种方式工作是为了防止这两个错误:

  • 反复重启
  • 部分错误
于 2019-07-28T10:57:19.963 回答