如何在运行中的Docker容器内用Python脚本更新镜像并重启容器?
问题描述
我遇到了Docker容器更新的问题,具体场景和现象如下:
- 现有基于
1.0.1版本镜像的Python应用Docker容器,通过shell脚本以--restart=always选项启动,使用latest标签,运行正常。 - 手动关闭(Alt-F4)容器后,容器能按预期自动重启。
- 在运行的
1.0.1容器内,通过Docker SDK for Python从DockerHub拉取1.0.2版本镜像,标记为latest后,调用client.containers.get("mycontainername").restart()尝试重启容器。
成功的操作:新镜像已拉取并本地标记为latest,容器能停止,本地可见1.0.2镜像且与latest镜像ID一致。
未达预期的结果:容器停止后无法自动重启;调用stop()停止容器也无法触发自动重启。
额外观察:
- 重新执行启动shell脚本后,运行的仍是基于旧
1.0.1镜像的容器(尽管脚本用了latest标签)。 - 当前运行的容器始终基于
1.0.1版本镜像。 - 系统重启后,会基于正确的
1.0.2版本镜像创建新容器。
我的问题:如何在运行中的容器内通过Python脚本更新镜像,并重启基于新镜像的容器?
解决方案
问题核心在于:Docker的restart()操作只是重启现有容器的进程,不会重新拉取latest镜像或创建新容器;而--restart=always规则仅触发现有容器的重启,不会自动基于新镜像重建容器。要实现基于新镜像启动容器,需要删除旧容器并重新创建。
步骤说明
- 拉取新版本镜像并标记为
latest(你已完成这一步)。 - 停止目标容器。
- 删除已停止的旧容器。
- 使用与原容器相同的配置(端口映射、卷挂载、环境变量、
--restart=always等),基于latest镜像重新创建并启动容器。
代码示例
import docker def update_and_restart_container(client, container_name, image_name, container_config): # 1. 拉取新镜像并标记为latest(若未完成可取消注释以下代码) # client.images.pull(f"{image_name}:1.0.2") # client.images.get(f"{image_name}:1.0.2").tag(image_name, tag="latest") # 2. 停止目标容器 container = client.containers.get(container_name) container.stop() # 3. 删除旧容器 container.remove() # 4. 基于latest镜像重新创建并启动容器,复用原配置 new_container = client.containers.run( image=f"{image_name}:latest", name=container_name, restart_policy={"Name": "always"}, # 对应--restart=always ports=container_config["ports"], # 原容器的端口映射 volumes=container_config["volumes"],# 原容器的卷挂载 environment=container_config["env"],# 原容器的环境变量 detach=True # 后台运行 ) return new_container # 初始化Docker客户端 client = docker.from_env() # 动态获取原容器的配置信息 original_container = client.containers.get("mycontainername") container_config = { "ports": original_container.attrs["HostConfig"]["PortBindings"], "volumes": original_container.attrs["HostConfig"]["Binds"], "env": original_container.attrs["Config"]["Env"] } # 执行更新重启 update_and_restart_container(client, "mycontainername", "your-image-name", container_config)
关键注意事项
- 必须确保重新创建容器时复用原容器的所有必要配置(端口、卷、环境变量等),否则新容器可能无法正常工作。
- 命名卷默认不会随容器删除而消失,绑定挂载的本地文件也会保留,无需担心数据丢失;若使用临时卷,需提前做好数据备份。
- 若启动脚本包含
--network、--user等自定义参数,需在containers.run()中对应添加这些参数。
内容的提问来源于stack exchange,提问作者spcmicro
相关产品推荐
相关产品推荐

