更新正在运行的docker映像

时间:2019-12-02 11:32:19

标签: docker

我有一个通过docker映像运行的网站。一个脚本会定期更新映像,另一个脚本会加载新映像,从而有效地更新站点。对于这最后一个任务,我将以下脚本称为cron任务:

#!/bin/sh
DOCKER_USER="user"
DOCKER_APP="app:latest"
DOCKER_IMAGE="${DOCKER_USER}/${DOCKER_APP}"

docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
docker system prune -af
docker pull $DOCKER_IMAGE
docker run -t -d -p 80:80 $DOCKER_IMAGE &

但是,虽然我已经使用了一段时间,但我不认为这是最好的方法,因为有时可能会导致错误。如果在使用docker pull时出现问题,则该页面将无法正常工作。

有人知道更好的方式来运行更新的图像,同时又防止保存越来越多的旧图像(这就是脚本中修剪步骤的原因)吗?

1 个答案:

答案 0 :(得分:2)

您最容易做的是重新排列命令集,以便首先执行拉取操作,并使容器不运行的时间最小化。

#!/bin/sh
set -e
DOCKER_IMAGE="user/app:${1:-latest}"

# Pull the image first; if it fails don't keep going
docker pull "$DOCKER_IMAGE"

# Stop and restart the container
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
docker run -t -d -p 80:80 "$DOCKER_IMAGE"

# Clean up
docker system prune -af

使用一个已知名称docker run --name的容器,并在docker stoprm命令中使用该名称,可能更干净。这样可以避免破坏其他不相关的容器。

另一种有用的技术是在容器前面运行某种负载均衡器。在纯Docker空间中,Traefik是一种流行的选择。您可以运行自己的负载平衡HAProxy或Nginx;您可以使用云提供商负载平衡器,例如Amazon ELB;或者您可以使用更高级别的服务(例如Kubernetes或Amazon ECS)为您提供此服务。这样一来,您就可以先启动新容器,再停止旧容器,并由负载均衡器管理服务路由。

尝试避免使用latest标记或类似的固定字符串也是一种常见的做法。在上面的示例脚本中,我将标记设为可选的命令行选项。这使您可以轻松地回滚到以前的版本,并且如果确实要迁移到Kubernetes或ECS,则基本上是必需的。