How to achieve a rolling update with docker-compose?

Here is the script I've ended up using:

PREVIOUS_CONTAINER=$(docker ps --format "table {{.ID}}  {{.Names}}  {{.CreatedAt}}" | grep backend | awk -F  "  " '{print $1}')
docker-compose up -d --no-deps --scale backend=2 --no-recreate backend
sleep 100
docker kill -s SIGTERM $PREVIOUS_CONTAINER
sleep 1
docker rm -f $PREVIOUS_CONTAINER
docker-compose up -d --no-deps --scale backend=1 --no-recreate backend
docker-compose stop http-nginx
docker-compose up -d --no-deps --build http-nginx

Swarm is the right solution to go, but this is still painfully doable with docker-compose.

First, ensure your proxy can do service discovery. You can't use container_name (as you can't use it in swarm) because your will increase the number of container of the same service. Proxy like traefik or nginx-proxy uses labels to do this.

Then, docker-compose up -d --scale backend=2 --no-recreate this creates a new container with the new image without touching the running one.

After it's up and running, docker kill old_container, then docker-compose up -d --scale backend=1 --no-recreate just to reset the number.


EDIT 1

docker kill old_container should be docker rm -f old_container

EDIT 2

how to handle even and not even runs

We want to always kill the oldest containers

docker rm -f $(docker ps --format "table {{.ID}}  {{.Names}}  {{.CreatedAt}}" | grep backend | (read -r; printf "%s\n" "$REPLY"; sort -k 3 ) | awk -F  "  " '{print $1}' | head -1)