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)