Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to achieve a rolling update with docker-compose?

I have a following setup in docker compose

  • nginx for proxying to frontend, backend and serving images
  • backend app on port 8080 (spring boot)
  • frontend app on port 4000 (node for SSR)
  • mysql used by backend

Frontend can be updated relatively fast using

docker-compose up -d --no-deps frontend

Unfortunately backend takes about 1 minute to start.

Is there an easy way to achieve lower downtime without having to change the current setup too much? I like how simple it is right now.

I would imagine something like:

  1. Start a new instance of backend
  2. Wait till it starts (it could be per timer or a healthtest
  3. Close the perviously running instance
like image 791
Marcin Kunert Avatar asked Mar 03 '18 23:03

Marcin Kunert


People also ask

Does docker compose auto update?

In this tutorial, you will use Watchtower with both Docker's run command and Docker Compose to automatically update a Docker image. Both methods are functionally the same in creating a container running Watchtower, then pointing it towards a container you wish to keep automatically updated.

How do I refresh docker compose up?

Usage: compose-update [OPTIONS] [UPDATE_DIRS]... Update docker-compose images automatically. Takes one or more directorys as input and searches for a compose file in one of the following forms: "compose. yaml", "compose.

Does docker automatically pull latest?

By default, Docker pulls the latest version. To ensure it does so, you can add the :latest tag.


2 Answers

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)
like image 100
Siyu Avatar answered Sep 19 '22 19:09

Siyu


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
like image 21
Marcin Kunert Avatar answered Sep 21 '22 19:09

Marcin Kunert