Docker:更改已创建容器上的端口绑定而不会丢失数据

Posted

技术标签:

【中文标题】Docker:更改已创建容器上的端口绑定而不会丢失数据【英文标题】:Docker: change port binding on an already created container with no data loss 【发布时间】:2018-11-14 19:47:46 【问题描述】:

假设我有一个带有大量数据的MongoDbSql Server 容器,突然间(这很可能)我需要更改端口!可能是因为突然的安全问题!我需要停止容器并重新启动它在不同的端口上运行。为什么 docker 不允许我这样做,如果我再次运行映像,将创建一个内部没有数据的新容器,这会导致很多混乱。

有合适的内置解决方案吗?我的意思是一种不需要我备份数据库、将它们移出容器卷并再次恢复它们的解决方案。诸如 command 之类的逻辑内容可以让我更改转发的端口,例如 -p 1433:1234 to 27017:1234

【问题讨论】:

【参考方案1】:

BLUF:使用映射的卷启动 MongoDB 容器,以使用以下格式保持数据持久性:docker run --name some-mongo -v /my/own/datadir:/data/db -d mongo

虽然我同意,但如果 Docker 能够在正在运行的容器中切换端口号,那就太好了。正如其他人所说,每个容器都是一个进程,我不知道如何更改正在运行的进程上的端口。

如果您已正确设置卷,则无需导入数据。我一直为 mysql 数据库这样做。如果您正确映射卷,MyQSL 映像只是与数据库分离的数据库引擎。这就是 Docker 的设计方式。

在查看“存储数据的位置”部分时,它提供了一个将卷安装到主机上的文件夹以保存数据的示例。这应该允许您使用相同的数据启动一个新容器,而无需重新导入。但我对 NoSQL 的 MongoDB 不太熟悉。

https://hub.docker.com/_/mongo/#!

您可能需要使用此转储命令备份您的数据库:

docker exec some-mongo sh -c 'exec mongodump -d <database_name> --archive' > /some/path/on/your/host/all-collections.archive

使用映射的卷启动一个新容器并恢复数据。

docker run --name some-mongo -v /my/own/datadir:/data/db -v /some/path/on/your/host/all-collections.archive:/data/db/collections.archive -d mongo

您需要恢复该备份。

docker exec some-mongo sh -c 'exec mongorestore --db <database_name> --archive=/data/db/collections.archive

从那时起,您应该能够简单地停止并启动一个映射了卷的新容器。您的数据应该保持持久性。您应该不再需要转储和恢复(嗯,显然是出于正常备份目的)。

【讨论】:

【参考方案2】:

容器是图像的实例化。

端口号是容器的实例化状态,所以只能在创建容器时更改。

【讨论】:

这意味着 Docker 属于垃圾箱 :) 实际上这里的端口号涉及创建主机网络和docker网络之间的网络流。所以这不能动态改变。 正如我所说,它不适合生产环境。因为在生产环境中,特别是可能需要在运行时更改端口。 “正在运行”的容器是进程,因此很难更改它们的配置。你不能配置一个进程,你可以杀死它并使用正确的参数启动一个新进程。容器应该被认为是短暂的。 详情请参考docker卷文档docs.docker.com/storage/volumes【参考方案3】:

您可以通过直接编辑 /var/lib/docker/containers/[hash_of_the_container]/hostconfig.json 中的 hostconfig.json 文件来更改端口映射

您可以通过 docker inspect 命令确定 [hash_of_the_container] 并且“Id”字段的值是哈希。

1) stop the container 
2) change the file
3) restart your docker engine (to flush/clear config caches)
4) start the container

参考:How do I assign a port mapping to an existing Docker container?

【讨论】:

我明确提到了'诸如命令之类的东西',我对编辑文件不感兴趣。我想知道那个框架是否有这样的功能。如果没有,那将是缺乏很多考虑的东西,这意味着它不适合商业环境。 对不起,我错过了那部分,但是这会很简单,因为在运行的容器中没有直接的方法来更改端口。你不想以这种方式修改的任何具体原因......是你的容器在集群中......我必须说你的容器应该将数据存储到卷中,以便创建一个新的容器永远不会丢失任何现有数据。将此视为重新设计它的机会。 一个新的容器,尤其是一个数据库,没有数据是新鲜的,所以你必须恢复很多东西。在具有许多主要任务的商业环境中,我们需要对开发人员友好的程序,而不是黑客、变通方法和愚蠢的程序。 不,实际上乍一看,docker 看起来不错,可能会让您考虑从 ESXi 完全切换到 docker 提供的基于容器的轻量级虚拟化环境。但仔细一看,原来是一个设计考量不足的玩具。我只是想向我的同事证明它确实是一个愚蠢的玩具:) 祝你好运...如果可用,我会密切关注解决方案.....除了端口转发之外,我想不出其他临时解决方案,为此你必须执行某些命令集...

以上是关于Docker:更改已创建容器上的端口绑定而不会丢失数据的主要内容,如果未能解决你的问题,请参考以下文章

#云原生征文# docker数据卷与DockerFile学习

docker volume

docker简单介绍----存储

为Docker创建自动化nginx反向代理

群晖docker更新数据会不会丢失

从现有的 docker 容器中删除端口绑定