How to rebuild and update a container without downtime with docker-compose?

DockerDocker Compose

Docker Problem Overview


I enjoy a lot using docker-compose.

Eg. on my server, when I want to update my app with minor changes, I only need to git pull origin master && docker-compose restart, works perfectly.

But sometimes, I need to rebuild (eg. I added an npm dependency, need to run npm install again).

In this case, I do docker-compose build --no-cache && docker-compose restart.

I would expect this to :

  • create a new instance of my container
  • stop the existing container (after the newer has finished building)
  • start the new one
  • optionally remove the old one, but this could be done manually

But in practice it seems to restart the former one again.

Is it the expected behavior?

How can I handle a rebuild and start the new one after it is built?

Maybe I missed a specific command? Or would it make sense to have it?

Docker Solutions


Solution 1 - Docker

from the manual docker-compose restart

> If you make changes to your docker-compose.yml configuration these > changes will not be reflected after running this command.

you should be able to do

$docker-compose up -d --no-deps --build <service_name>

The --no-deps will not start linked services.

Solution 2 - Docker

The problem is that restart will restart your current containers, which is not what you want.

As an example, I just did this

  • change the docker file for one of the images
  • call docker-compose build to build the images
  • call docker-compose down1 and docker-compose up
    • docker-compose restart will NOT work here
    • using docker-compose start instead also does not work

To be honest, i'm not completly sure you need to do a down first, but that should be easy to check.1 The bottomline is that you need to call up. You will see the containers of unchanged images restarting, but for the changed image you'll see recreating.

The advantage of this over just calling up --build is that you can see the building-process first before you restart.

1: from the comments; down is not needed, you can just call up --build. Down has some "down"-sides, including possible being destructive to your (volume-)data.

Solution 3 - Docker

Use the --build flag to the up command, along with the -d flag to run your containers in the background:

docker-compose up -d --build

This will rebuild all images defined in your compose file, then restart any containers whose images have changed.

-d assumes that you don't want to keep everything running in your shell foreground. This makes it act more like restart, but it's not required.

Solution 4 - Docker

Don't manage your application environment directly. Use deployment tool like Rancher / Kubernetes. Using one you will be able to upgrade your dockerized application without any downtime and even downgrade it should you need to.

Running Rancher is as easy as running another docker container as this tool is available in the Docker Hub.

Solution 5 - Docker

Though the accepted answer shall work to rebuild the container before starting the new one as a replacement, it is ok for simple use case, but the container will still be down during new container initialization process. If this is quite long, it can be an issue.

I managed to achieve rolling updates with docker-compose (along with a nginx reverse proxy), and detailed how I built that in this github issue: https://github.com/docker/compose/issues/1786#issuecomment-579794865

Hope it can help!

Solution 6 - Docker

You can use Swarm. Init swarm first by docker swarm init command and use healthcheck in docker-compose.yml.

Then run below command:

docker stack deploy -c docker-compose.yml project_name

instead of

docker-compose up -d.

When docker-compose.yml file is updated only run this command again:

docker stack deploy -c docker-compose.yml project_name

Docker Swarm will create new version of services and stop old version after that.

Solution 7 - Docker

Run the following commands:

docker-compose pull

docker-compose up -d --no-deps --build <service_name>

As the top rated answer mentioned

docker-compose up -d --no-deps --build <service_name>

will restart a single service without taking down the whole compose.

I just wanted to add to the top answer in case anyone is unsure how to update an image without restarting the container.

Solution 8 - Docker

Another way:

docker-compose restart in your case could be replaced with docker-compose up -d --force-recreate, see https://docs.docker.com/compose/reference/up/

Solution 9 - Docker

Running docker-compose up while docker-compose is in the running state, will recreate container that got their configuration changed.

Thats the easiest way, and it will only affect containers that got their configuration changed.

root@docker:~# docker-compose up
traefik is up-to-date
nginx is up-to-date
Recreating php ... done

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAugustin RiedingerView Question on Stackoverflow
Solution 1 - DockerdenovView Answer on Stackoverflow
Solution 2 - DockerNanneView Answer on Stackoverflow
Solution 3 - DockerjkinkeadView Answer on Stackoverflow
Solution 4 - DockeremixView Answer on Stackoverflow
Solution 5 - DockerAugustin RiedingerView Answer on Stackoverflow
Solution 6 - DockerHosseinView Answer on Stackoverflow
Solution 7 - DockerAndrew IrwinView Answer on Stackoverflow
Solution 8 - DockerAleksejs SpiridonovsView Answer on Stackoverflow
Solution 9 - Dockerdisco_stuView Answer on Stackoverflow