Docker:更改已创建容器上的端口绑定而不会丢失数据
Posted
技术标签:
【中文标题】Docker:更改已创建容器上的端口绑定而不会丢失数据【英文标题】:Docker: change port binding on an already created container with no data loss 【发布时间】:2018-11-14 19:47:46 【问题描述】:假设我有一个带有大量数据的MongoDb
或Sql 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:更改已创建容器上的端口绑定而不会丢失数据的主要内容,如果未能解决你的问题,请参考以下文章